diff options
author | Chirag Shah <chirag@cumulusnetworks.com> | 2018-05-02 01:34:31 +0200 |
---|---|---|
committer | Chirag Shah <chirag@cumulusnetworks.com> | 2018-05-17 20:10:09 +0200 |
commit | 804a32941084bc0da2c26f6948fff1003458988a (patch) | |
tree | 3a77fdb89e92c04e19e27cd3ecb6b66c29215fd8 /ospf6d | |
parent | Merge pull request #2221 from rodnymolina/vtysh_extension (diff) | |
download | frr-804a32941084bc0da2c26f6948fff1003458988a.tar.xz frr-804a32941084bc0da2c26f6948fff1003458988a.zip |
ospf6d: Fix ECMP for asbr external routes
Use brouter table to fetch nexthops for
asbr prefix (external) routes.
Change adv. router of the router's path once
the DB/FIB is updated with effective nexthops.
Cleanup of nexthop update when route's adv
router changes cost.
Ticket:CM-16139
Testing Done:
Tested ASBR external routes in CLOS topology with
multiple paths asbr originator at tor to spine.
Validated external route's nexthop within
area and inter area.
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
Diffstat (limited to 'ospf6d')
-rw-r--r-- | ospf6d/ospf6_asbr.c | 113 | ||||
-rw-r--r-- | ospf6d/ospf6_intra.c | 2 |
2 files changed, 57 insertions, 58 deletions
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index 0fe0cada3..8bd0683f1 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -260,12 +260,12 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old, listnode_delete(old_route->nh_list, rnh); ospf6_nexthop_delete(rnh); - route_updated = true; } } listnode_delete(old_route->paths, o_path); ospf6_path_free(o_path); + route_updated = true; /* Current route's path (adv_router info) is similar * to route being added. @@ -273,6 +273,19 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old, * Update FIB with effective NHs. */ if (listcount(old_route->paths)) { + for (ALL_LIST_ELEMENTS(old_route->paths, + anode, anext, o_path)) { + ospf6_merge_nexthops( + old_route->nh_list, + o_path->nh_list); + } + /* Update RIB/FIB with effective + * nh_list + */ + if (ospf6->route_table->hook_add) + (*ospf6->route_table->hook_add) + (old_route); + if (old_route->path.origin.id == route->path.origin.id && old_route->path.origin.adv_router @@ -290,23 +303,7 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old, 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)) { - ospf6_merge_nexthops( - old_route->nh_list, - o_path->nh_list); - } - /* Update RIB/FIB with effective - * nh_list - */ - if (ospf6->route_table->hook_add) - (*ospf6->route_table->hook_add)( - old_route); - break; - } + break; } else { if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) { prefix2str(&old_route->prefix, buf, @@ -374,13 +371,6 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old, /* 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); - - /* Update RIB/FIB */ - if (ospf6->route_table->hook_add) - (*ospf6->route_table->hook_add)( - old_route); /* Add the new path to route's path list */ listnode_add_sort(old_route->paths, ecmp_path); @@ -400,46 +390,52 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old, 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); - } - } 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); + /* Reset nexthop lists, rebuild from brouter table + * for each adv. router. + */ + list_delete_all_node(old_route->nh_list); - if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) { - prefix2str(&route->prefix, buf, - sizeof(buf)); - zlog_debug( - "%s: existing route %s with effective nh count %u", - __PRETTY_FUNCTION__, buf, - old_route->nh_list - ? listcount( - old_route - ->nh_list) - : 0); + for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode, + o_path)) { + struct ospf6_route *asbr_entry; + + asbr_entry = ospf6_route_lookup( + &o_path->ls_prefix, + ospf6->brouter_table); + if (asbr_entry == NULL) { + if (IS_OSPF6_DEBUG_EXAMIN( + AS_EXTERNAL)) { + prefix2str(&old_route->prefix, + buf, sizeof(buf)); + zlog_debug("%s: ls_prfix %s asbr_entry not found.", + __PRETTY_FUNCTION__, + buf); + } + continue; } + ospf6_route_merge_nexthops(old_route, + asbr_entry); + } - /* Update RIB/FIB */ - if (ospf6->route_table->hook_add) - (*ospf6->route_table->hook_add)( - old_route); + if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) { + prefix2str(&route->prefix, buf, sizeof(buf)); + zlog_debug("%s: route %s with effective paths %u nh %u", + __PRETTY_FUNCTION__, buf, + old_route->paths ? + listcount(old_route->paths) : 0, + old_route->nh_list ? + listcount(old_route->nh_list) : 0); } + + /* Update RIB/FIB */ + if (ospf6->route_table->hook_add) + (*ospf6->route_table->hook_add)(old_route); + /* Delete the new route its info added to existing * route. */ @@ -509,8 +505,9 @@ void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa) route->path.origin.type = lsa->header->type; route->path.origin.id = lsa->header->id; route->path.origin.adv_router = lsa->header->adv_router; - route->path.prefix_options = external->prefix.prefix_options; + memcpy(&route->path.ls_prefix, &asbr_id, sizeof(struct prefix)); + if (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_E)) { route->path.type = OSPF6_PATH_TYPE_EXTERNAL2; route->path.metric_type = 2; diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c index 26e6deada..d99541eba 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -2037,6 +2037,8 @@ static void ospf6_brouter_debug_print(struct ospf6_route *brouter) 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) |