]> git.puffer.fish Git - mirror/frr.git/commitdiff
ospf6d: Fix ECMP for asbr external routes 2253/head
authorChirag Shah <chirag@cumulusnetworks.com>
Tue, 1 May 2018 23:34:31 +0000 (16:34 -0700)
committerChirag Shah <chirag@cumulusnetworks.com>
Thu, 17 May 2018 18:10:09 +0000 (11:10 -0700)
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>
ospf6d/ospf6_asbr.c
ospf6d/ospf6_intra.c

index 0fe0cada391d10b712ab7f7bd314f9ce8089b330..8bd0683f14da5add8fc8f16d2fced19b21085877 100644 (file)
@@ -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;
index 26e6deadae89636490f744d00f41cebc79f054cc..d99541ebaddfa8c28ae9a1423546b551921d3430 100644 (file)
@@ -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)