return 0;
}
+static void ospf6_intra_prefix_update_route_origin(struct ospf6_route *oa_route)
+{
+ struct ospf6_path *h_path;
+ struct ospf6_route *g_route, *nroute;
+
+ /* Update Global ospf6 route path */
+ g_route = ospf6_route_lookup(&oa_route->prefix,
+ ospf6->route_table);
+
+ assert(g_route);
+
+ for (ospf6_route_lock(g_route); g_route &&
+ ospf6_route_is_prefix(&oa_route->prefix, g_route);
+ g_route = nroute) {
+ nroute = ospf6_route_next(g_route);
+ if (g_route->type != oa_route->type)
+ continue;
+ if (g_route->path.area_id != oa_route->path.area_id)
+ continue;
+ if (g_route->path.type != OSPF6_PATH_TYPE_INTRA)
+ continue;
+ if (g_route->path.cost != oa_route->path.cost)
+ continue;
+
+ if (ospf6_route_is_same_origin(g_route, oa_route)) {
+ h_path = (struct ospf6_path *)listgetdata(
+ listhead(g_route->paths));
+ g_route->path.origin.type = h_path->origin.type;
+ g_route->path.origin.id = h_path->origin.id;
+ g_route->path.origin.adv_router =
+ h_path->origin.adv_router;
+ break;
+ }
+ }
+
+ h_path = (struct ospf6_path *)listgetdata(
+ listhead(oa_route->paths));
+ oa_route->path.origin.type = h_path->origin.type;
+ oa_route->path.origin.id = h_path->origin.id;
+ oa_route->path.origin.adv_router = h_path->origin.adv_router;
+}
+
void ospf6_intra_prefix_route_ecmp_path(struct ospf6_area *oa,
struct ospf6_route *old,
struct ospf6_route *route)
{
- struct ospf6_route *old_route;
+ struct ospf6_route *old_route, *ls_entry;
struct ospf6_path *ecmp_path, *o_path = NULL;
struct listnode *anode, *anext;
struct listnode *nnode, *rnode, *rnext;
struct ospf6_nexthop *nh, *rnh;
char buf[PREFIX2STR_BUFFER];
bool route_found = false;
+ struct interface *ifp;
+ struct ospf6_lsa *lsa;
+ struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
/* check for old entry match with new route origin,
* delete old entry.
o_path->cost, route->path.cost);
}
- /* Remove selected current rout path's nh from
+ /* Remove selected current path's nh from
* effective nh list.
*/
for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
* Update FIB with effective NHs.
*/
if (listcount(old_route->paths)) {
- if (old_route->path.origin.id ==
- route->path.origin.id &&
- old_route->path.origin.adv_router ==
- route->path.origin.adv_router) {
- struct ospf6_path *h_path;
-
- h_path = (struct ospf6_path *)
- listgetdata(listhead(old_route->paths));
- old_route->path.origin.type =
- h_path->origin.type;
- old_route->path.origin.id =
- h_path->origin.id;
- old_route->path.origin.adv_router =
- h_path->origin.adv_router;
- }
-
if (route_updated) {
for (ALL_LIST_ELEMENTS(old_route->paths,
anode, anext, o_path)) {
if (oa->route_table->hook_add)
(*oa->route_table->hook_add)
(old_route);
+
+ if (old_route->path.origin.id ==
+ route->path.origin.id &&
+ old_route->path.origin.adv_router ==
+ route->path.origin.adv_router) {
+ ospf6_intra_prefix_update_route_origin(
+ old_route);
+ }
break;
}
} else {
old_route->path.cost,
route->path.cost);
}
- ospf6_route_remove(old_route,
+ if (oa->route_table->hook_remove)
+ ospf6_route_remove(old_route,
oa->route_table);
+ else
+ SET_FLAG(old_route->flag,
+ OSPF6_ROUTE_REMOVE);
break;
}
}
/* Add a nh_list to new ecmp path */
ospf6_copy_nexthops(ecmp_path->nh_list,
route->nh_list);
- /* Merge nexthop to existing route's nh_list */
- ospf6_route_merge_nexthops(old_route, route);
/* Add the new path to route's path list */
listnode_add_sort(old_route->paths, ecmp_path);
- UNSET_FLAG(old_route->flag, OSPF6_ROUTE_REMOVE);
- SET_FLAG(old_route->flag, OSPF6_ROUTE_CHANGE);
- /* Update RIB/FIB */
- if (oa->route_table->hook_add)
- (*oa->route_table->hook_add)
- (old_route);
if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
prefix2str(&route->prefix, buf,
sizeof(buf));
- zlog_debug("%s: route %s %p another path added with nh %u, effective paths %u nh %u",
+ zlog_debug(
+ "%s: route %s %p another path added with nh %u, effective paths %u nh %u",
__PRETTY_FUNCTION__, buf,
(void *)old_route,
listcount(ecmp_path->nh_list),
old_route->paths ?
- listcount(old_route->paths)
- : 0,
+ listcount(old_route->paths) : 0,
listcount(old_route->nh_list));
- }
- } else {
- for (ALL_LIST_ELEMENTS_RO(o_path->nh_list,
- nnode, nh)) {
- for (ALL_LIST_ELEMENTS(
- old_route->nh_list,
- rnode, rnext, rnh)) {
- if (!ospf6_nexthop_is_same(rnh,
- nh))
- continue;
- listnode_delete(
- old_route->nh_list,
- rnh);
- ospf6_nexthop_delete(rnh);
- }
}
+ } else {
list_delete_all_node(o_path->nh_list);
ospf6_copy_nexthops(o_path->nh_list,
route->nh_list);
- /* Merge nexthop to existing route's nh_list */
- ospf6_route_merge_nexthops(old_route,
- route);
+ }
- if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
- prefix2str(&route->prefix,
- buf, sizeof(buf));
- zlog_debug("%s: existing route %s %p with effective paths %u nh count %u",
- __PRETTY_FUNCTION__, buf,
- (void *)old_route,
- listcount(old_route->paths),
- old_route->nh_list ?
- listcount(old_route->nh_list)
- : 0);
+ list_delete_all_node(old_route->nh_list);
+
+ for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode,
+ o_path)) {
+ ls_entry = ospf6_route_lookup(
+ &o_path->ls_prefix,
+ oa->spf_table);
+ if (ls_entry == NULL) {
+ if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
+ zlog_debug("%s: ls_prfix %s ls_entry not found.",
+ __PRETTY_FUNCTION__,
+ buf);
+ continue;
}
+ lsa = ospf6_lsdb_lookup(o_path->origin.type,
+ o_path->origin.id,
+ o_path->origin.adv_router,
+ oa->lsdb);
+ if (lsa == NULL) {
+ if (IS_OSPF6_DEBUG_EXAMIN(
+ INTRA_PREFIX)) {
+ struct prefix adv_prefix;
- UNSET_FLAG(old_route->flag, OSPF6_ROUTE_REMOVE);
- SET_FLAG(old_route->flag, OSPF6_ROUTE_CHANGE);
- /* Update ospf6 route table and RIB/FIB */
- if (oa->route_table->hook_add)
- (*oa->route_table->hook_add)
- (old_route);
+ ospf6_linkstate_prefix(
+ o_path->origin.adv_router,
+ o_path->origin.id, &adv_prefix);
+ prefix2str(&adv_prefix, buf,
+ sizeof(buf));
+ zlog_debug("%s: adv_router %s lsa not found",
+ __PRETTY_FUNCTION__,
+ buf);
+ }
+ continue;
+ }
+ intra_prefix_lsa =
+ (struct ospf6_intra_prefix_lsa *)
+ OSPF6_LSA_HEADER_END(lsa->header);
+
+ if (intra_prefix_lsa->ref_adv_router
+ == oa->ospf6->router_id) {
+ ifp = if_lookup_prefix(
+ &old_route->prefix,
+ VRF_DEFAULT);
+ if (ifp)
+ ospf6_route_add_nexthop(
+ old_route,
+ ifp->ifindex,
+ NULL);
+ } else {
+ ospf6_route_merge_nexthops(old_route,
+ ls_entry);
+ }
}
+
+ if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
+ prefix2str(&route->prefix, buf, sizeof(buf));
+ zlog_debug("%s: route %s %p with final effective paths %u nh%u",
+ __PRETTY_FUNCTION__, buf,
+ (void *)old_route,
+ old_route->paths ?
+ listcount(old_route->paths) : 0,
+ listcount(old_route->nh_list));
+ }
+
+ /* used in intra_route_calculation() to add to
+ * global ospf6 route table.
+ */
+ UNSET_FLAG(old_route->flag, OSPF6_ROUTE_REMOVE);
+ SET_FLAG(old_route->flag, OSPF6_ROUTE_ADD);
+ /* Update ospf6 route table and RIB/FIB */
+ if (oa->route_table->hook_add)
+ (*oa->route_table->hook_add)(old_route);
/* Delete the new route its info added to existing
* route.
*/
memset(&route->prefix, 0, sizeof(struct prefix));
route->prefix.family = AF_INET6;
route->prefix.prefixlen = op->prefix_length;
- ospf6_prefix_in6_addr(&route->prefix.u.prefix6, op);
+ ospf6_prefix_in6_addr(&route->prefix.u.prefix6,
+ intra_prefix_lsa, op);
route->type = OSPF6_DEST_TYPE_NETWORK;
route->path.origin.type = lsa->header->type;
route->path.metric_type = 1;
route->path.cost =
ls_entry->path.cost + ntohs(op->prefix_metric);
-
+ memcpy(&route->path.ls_prefix, &ls_prefix,
+ sizeof(struct prefix));
if (direct_connect) {
ifp = if_lookup_prefix(&route->prefix, VRF_DEFAULT);
if (ifp)
listnode_add_sort(route->paths, path);
old = ospf6_route_lookup(&route->prefix, oa->route_table);
- if (old && (ospf6_route_cmp(route, old) == 0)) {
+ if (old) {
if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
prefix2str(&route->prefix, buf, sizeof(buf));
- zlog_debug(" Update route: %s old cost %u new cost %u nh count %u paths %u",
- buf,
+ zlog_debug("%s Update route: %s old cost %u new cost %u paths %u nh %u",
+ __PRETTY_FUNCTION__, buf,
old->path.cost, route->path.cost,
- listcount(route->nh_list),
- listcount(route->paths));
+ listcount(route->paths),
+ listcount(route->nh_list));
}
ospf6_intra_prefix_route_ecmp_path(oa, old, route);
} else {
if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
prefix2str(&route->prefix, buf, sizeof(buf));
- zlog_debug(" route %s add with cost %u nh %u paths %u",
- buf, route->path.cost,
- listcount(route->nh_list),
- listcount(route->paths));
+ zlog_debug("%s route %s add with cost %u paths %u nh %u",
+ __PRETTY_FUNCTION__, buf,
+ route->path.cost,
+ listcount(route->paths),
+ listcount(route->nh_list));
}
ospf6_route_add(route, oa->route_table);
}
zlog_debug("Trailing garbage ignored");
}
+static void ospf6_intra_prefix_lsa_remove_update_route(struct ospf6_lsa *lsa,
+ struct ospf6_area *oa,
+ struct ospf6_route *route)
+{
+ struct listnode *anode, *anext;
+ struct listnode *nnode, *rnode, *rnext;
+ struct ospf6_nexthop *nh, *rnh;
+ struct ospf6_path *o_path;
+ bool nh_updated = false;
+ char buf[PREFIX2STR_BUFFER];
+
+ /* Iterate all paths of route to find maching
+ * with LSA remove info.
+ * If route->path is same, replace
+ * from paths list.
+ */
+ for (ALL_LIST_ELEMENTS(route->paths, anode, anext, o_path)) {
+ if ((o_path->origin.type != lsa->header->type) ||
+ (o_path->origin.adv_router != lsa->header->adv_router) ||
+ (o_path->origin.id != lsa->header->id))
+ continue;
+
+ if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
+ prefix2str(&route->prefix, buf, sizeof(buf));
+ zlog_debug(
+ "%s: route %s path found with cost %u nh %u to remove.",
+ __PRETTY_FUNCTION__, buf, o_path->cost,
+ listcount(o_path->nh_list));
+ }
+
+ /* Remove found path's nh_list from
+ * the route's nh_list.
+ */
+ for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
+ for (ALL_LIST_ELEMENTS(route->nh_list, rnode,
+ rnext, rnh)) {
+ if (!ospf6_nexthop_is_same(rnh, nh))
+ continue;
+ listnode_delete(route->nh_list, rnh);
+ ospf6_nexthop_delete(rnh);
+ }
+ }
+ /* Delete the path from route's
+ * path list
+ */
+ listnode_delete(route->paths, o_path);
+ ospf6_path_free(o_path);
+ nh_updated = true;
+ break;
+ }
+
+ if (nh_updated) {
+ /* Iterate all paths and merge nexthop,
+ * unlesss any of the nexthop similar to
+ * ones deleted as part of path deletion.
+ */
+ for (ALL_LIST_ELEMENTS(route->paths, anode, anext, o_path))
+ ospf6_merge_nexthops(route->nh_list, o_path->nh_list);
+
+
+ if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
+ prefix2str(&route->prefix, buf, sizeof(buf));
+ zlog_debug("%s: route %s update paths %u nh %u",
+ __PRETTY_FUNCTION__, buf,
+ route->paths ? listcount(route->paths) : 0,
+ route->nh_list ? listcount(route->nh_list)
+ : 0);
+ }
+
+ /* Update Global Route table and
+ * RIB/FIB with effective
+ * nh_list
+ */
+ if (oa->route_table->hook_add)
+ (*oa->route_table->hook_add)(route);
+
+ /* route's primary path is similar
+ * to LSA, replace route's primary
+ * path with route's paths list
+ * head.
+ */
+ if ((route->path.origin.id == lsa->header->id) &&
+ (route->path.origin.adv_router ==
+ lsa->header->adv_router)) {
+ ospf6_intra_prefix_update_route_origin(route);
+ }
+ }
+
+}
+
void ospf6_intra_prefix_lsa_remove(struct ospf6_lsa *lsa)
{
struct ospf6_area *oa;
struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
struct prefix prefix;
- struct ospf6_route *route, *nroute, *route_to_del;
+ struct ospf6_route *route, *nroute;
int prefix_num;
struct ospf6_prefix *op;
char *start, *current, *end;
break;
prefix_num--;
- route_to_del = ospf6_route_create();
-
- memset(&route_to_del->prefix, 0, sizeof(struct prefix));
- route_to_del->prefix.family = AF_INET6;
- route_to_del->prefix.prefixlen = op->prefix_length;
- ospf6_prefix_in6_addr(&route_to_del->prefix.u.prefix6, op);
-
- route_to_del->type = OSPF6_DEST_TYPE_NETWORK;
- route_to_del->path.origin.type = lsa->header->type;
- route_to_del->path.origin.id = lsa->header->id;
- route_to_del->path.origin.adv_router = lsa->header->adv_router;
- route_to_del->path.prefix_options = op->prefix_options;
- route_to_del->path.area_id = oa->area_id;
- route_to_del->path.type = OSPF6_PATH_TYPE_INTRA;
- route_to_del->path.metric_type = 1;
-
memset(&prefix, 0, sizeof(struct prefix));
prefix.family = AF_INET6;
prefix.prefixlen = op->prefix_length;
- ospf6_prefix_in6_addr(&prefix.u.prefix6, op);
+ ospf6_prefix_in6_addr(&prefix.u.prefix6, intra_prefix_lsa, op);
route = ospf6_route_lookup(&prefix, oa->route_table);
if (route == NULL)
* after removal of one of the path.
*/
if (listcount(route->paths) > 1) {
- struct listnode *anode, *anext;
- struct listnode *nnode, *rnode, *rnext;
- struct ospf6_nexthop *nh, *rnh;
- struct ospf6_path *o_path;
- bool nh_updated = false;
-
- /* Iterate all paths of route to find maching
- * with LSA remove info.
- * If route->path is same, replace
- * from paths list.
- */
- for (ALL_LIST_ELEMENTS(route->paths, anode,
- anext, o_path)) {
- if ((o_path->origin.type !=
- lsa->header->type) ||
- (o_path->origin.adv_router !=
- lsa->header->adv_router) ||
- (o_path->origin.id !=
- lsa->header->id))
- continue;
-
- if (IS_OSPF6_DEBUG_EXAMIN
- (INTRA_PREFIX)) {
- prefix2str(&prefix, buf,
- sizeof(buf));
- zlog_debug(
- "%s: route %s path found with cost %u nh %u to remove.",
- __PRETTY_FUNCTION__,
- buf, o_path->cost,
- listcount(
- o_path->nh_list));
- }
- /* Remove old route from global
- * ospf6 route table.
- * nh_update section will add
- * back with effective nh.
- */
- if (oa->route_table->hook_remove)
- (*oa->route_table->hook_remove)
- (route);
- /* Remove found path's nh_list from
- * the route's nh_list.
- */
- for (ALL_LIST_ELEMENTS_RO(
- o_path->nh_list,
- nnode, nh)) {
- for (ALL_LIST_ELEMENTS(
- route->nh_list,
- rnode, rnext, rnh)) {
- if (
- !ospf6_nexthop_is_same(
- rnh, nh))
- continue;
- listnode_delete(
- route->nh_list,
- rnh);
- ospf6_nexthop_delete(
- rnh);
- }
- }
- /* Delete the path from route's
- * path list
- */
- listnode_delete(route->paths, o_path);
- ospf6_path_free(o_path);
- nh_updated = true;
- break;
- }
-
- if (nh_updated) {
-
- /* Iterate all paths and merge nexthop,
- * unlesss any of the nexthop similar to
- * ones deleted as part of path
- * deletion.
- */
- for (ALL_LIST_ELEMENTS(route->paths,
- anode, anext, o_path)) {
- ospf6_merge_nexthops(
- route->nh_list,
- o_path->nh_list);
- }
-
- if (IS_OSPF6_DEBUG_EXAMIN(
- INTRA_PREFIX)) {
- prefix2str(&route->prefix, buf,
- sizeof(buf));
- zlog_debug("%s: route %s update paths %u nh %u"
- , __PRETTY_FUNCTION__,
- buf,
- listcount(route->paths),
- listcount(
- route->nh_list));
- }
-
- /* route's primary path is similar
- * to LSA, replace route's primary
- * path with route's paths list
- * head.
- */
- if ((route->path.origin.id ==
- lsa->header->id) &&
- (route->path.origin.adv_router
- == lsa->header->adv_router)) {
- struct ospf6_path *h_path;
-
- h_path = (struct ospf6_path *)
- listgetdata(listhead(
- route->paths));
- route->path.origin.type =
- h_path->origin.type;
- route->path.origin.id =
- h_path->origin.id;
- route->path.origin.adv_router =
- h_path->origin.adv_router;
- }
-
- /* Update Global Route table and
- * RIB/FIB with effective
- * nh_list
- */
- if (oa->route_table->hook_add)
- (*oa->route_table->hook_add)
- (route);
- }
- continue;
-
+ ospf6_intra_prefix_lsa_remove_update_route(
+ lsa, oa, route);
} else {
if (route->path.origin.type != lsa->header->type
if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
prefix2str(&route->prefix, buf,
sizeof(buf));
- zlog_debug("route remove %s with path %u cost %u nh %u",
- buf, route->path.type,
+ zlog_debug("%s: route remove %s with path type %u cost %u paths %u nh %u",
+ __PRETTY_FUNCTION__, buf,
+ route->path.type,
route->path.cost,
+ listcount(route->paths),
listcount(route->nh_list));
}
ospf6_route_remove(route, oa->route_table);
}
if (route)
ospf6_route_unlock(route);
-
- ospf6_route_delete(route_to_del);
}
if (current != end && IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
zlog_info(" options: %s router-bits: %s metric-type: %d metric: %d/%d",
options, capa, brouter->path.metric_type, brouter->path.cost,
brouter->path.u.cost_e2);
+ zlog_info(" paths %u nh %u", listcount(brouter->paths),
+ listcount(brouter->nh_list));
}
void ospf6_intra_brouter_calculation(struct ospf6_area *oa)
uint32_t brouter_id;
char brouter_name[16];
- if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa->area_id))
- zlog_info("border-router calculation for area %s", oa->name);
+ if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa->area_id) ||
+ IS_OSPF6_DEBUG_ROUTE(MEMORY))
+ zlog_info("%s: border-router calculation for area %s",
+ __PRETTY_FUNCTION__, oa->name);
hook_add = oa->ospf6->brouter_table->hook_add;
hook_remove = oa->ospf6->brouter_table->hook_remove;
for (brouter = ospf6_route_head(oa->ospf6->brouter_table); brouter;
brouter = nbrouter) {
+
/*
* brouter may have been "deleted" in the last loop iteration.
* If this is the case there is still 1 final refcount lock
* skip processing the deleted route.
*/
if (brouter->lock == 1) {
+ if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
+ ospf6_brouter_debug_print(brouter);
nbrouter = ospf6_route_next(brouter);
continue;
} else {
brouter_id)
|| IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
oa->area_id))
- zlog_info("brouter %s disappears via area %s",
- brouter_name, oa->name);
+ zlog_info("%s: brouter %s disappears via area %s",
+ __PRETTY_FUNCTION__, brouter_name,
+ oa->name);
+ /* This is used to protect nbrouter from removed from
+ * the table. For an example, ospf6_abr_examin_summary,
+ * removes brouters which are marked for remove.
+ */
+ oa->intra_brouter_calc = 1;
ospf6_route_remove(brouter, oa->ospf6->brouter_table);
brouter = NULL;
} else if (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_ADD)
brouter_id)
|| IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
oa->area_id))
- zlog_info("brouter %s appears via area %s",
- brouter_name, oa->name);
+ zlog_info("%s: brouter %s appears via area %s",
+ __PRETTY_FUNCTION__, brouter_name,
+ oa->name);
/* newly added */
if (hook_add)
UNSET_FLAG(brouter->flag, OSPF6_ROUTE_ADD);
UNSET_FLAG(brouter->flag, OSPF6_ROUTE_CHANGE);
}
+ /* Reset for nbrouter */
+ oa->intra_brouter_calc = 0;
}
- if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa->area_id))
- zlog_info("border-router calculation for area %s: done",
- oa->name);
+ if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa->area_id) ||
+ IS_OSPF6_DEBUG_ROUTE(MEMORY))
+ zlog_info("%s: border-router calculation for area %s: done",
+ __PRETTY_FUNCTION__, oa->name);
}
struct ospf6_lsa_handler router_handler = {.lh_type = OSPF6_LSTYPE_ROUTER,