]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: For deterministic MED build a multipath set for each peer AS as the
authorJosh Bailey <joshb@google.com>
Thu, 21 Jul 2011 03:48:20 +0000 (20:48 -0700)
committerJosh Bailey <joshb@google.com>
Thu, 21 Jul 2011 03:48:20 +0000 (20:48 -0700)
first stage of the best path calculation. The second stage then
selects a winner from each peer AS's best path. In the second stage we
clear multipath set of the non-selected best paths via
bgp_mp_dmed_deselect(). Since the multipath set is already marked up
for the winning path, we don't call bgp_info_mpath_update() after the
second stage calculation.

* bgpd/bgp_mpath.c
  * bgp_mp_dmed_deselect(): New function to cleanup the multipath
    markup if a DMED selected path loses in stage 2 of the best path
    calculation
* bgpd/bgp_mpath.h
  * Add external declaration of bgp_mp_dmed_deselect()
* bgpd/bgp_route.c
  * bgp_best_selection(): If multipath is enabled, build up the mp_list
    for the current peer AS, and do the RIB markup the best path from
    that AS. In the second stage, clear the RIB markup for the DMED
    selected path if it is not selected as best. Only call
    bgp_info_mpath_update() in the second stage when not doing
    deterministic MED.

bgpd/bgp_mpath.c
bgpd/bgp_mpath.h
bgpd/bgp_route.c

index af1c342c62ed688b6ece79e233a8c86b04025c4b..7944c55fc46631e2de857d479ad9a3a08d63e439 100644 (file)
@@ -513,3 +513,28 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
         SET_FLAG (new_best->flags, BGP_INFO_MULTIPATH_CHG);
     }
 }
+
+/*
+ * bgp_mp_dmed_deselect
+ *
+ * Clean up multipath information for BGP_INFO_DMED_SELECTED path that
+ * is not selected as best path
+ */
+void
+bgp_mp_dmed_deselect (struct bgp_info *dmed_best)
+{
+  struct bgp_info *mpinfo, *mpnext;
+
+  if (!dmed_best)
+    return;
+
+  for (mpinfo = bgp_info_mpath_first (dmed_best); mpinfo; mpinfo = mpnext)
+    {
+      mpnext = bgp_info_mpath_next (mpinfo);
+      bgp_info_mpath_dequeue (mpinfo);
+    }
+
+  bgp_info_mpath_count_set (dmed_best, 0);
+  UNSET_FLAG (dmed_best->flags, BGP_INFO_MULTIPATH_CHG);
+  assert (bgp_info_mpath_first (dmed_best) == 0);
+}
index 1dc2687e22baf326a693793fbce16c62010ece8f..3712493ed67d080a6ceb51e8290833558cc5dc83 100644 (file)
@@ -55,6 +55,7 @@ extern int bgp_maximum_paths_unset (struct bgp *, afi_t, safi_t, int);
 extern void bgp_mp_list_init (struct list *);
 extern void bgp_mp_list_clear (struct list *);
 extern void bgp_mp_list_add (struct list *, struct bgp_info *);
+extern void bgp_mp_dmed_deselect (struct bgp_info *);
 extern void bgp_info_mpath_update (struct bgp_node *, struct bgp_info *,
                                    struct bgp_info *, struct list *,
                                    struct bgp_maxpaths_cfg *);
index f3e46221caf0b57a856f10de80bd48bdec731d0b..5c4ab266634de4170ad68f03ad61acf6c8f38748 100644 (file)
@@ -1316,6 +1316,9 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn,
          continue;
 
        new_select = ri1;
+       if (do_mpath)
+         bgp_mp_list_add (&mp_list, ri1);
+       old_select = CHECK_FLAG (ri1->flags, BGP_INFO_SELECTED) ? ri1 : NULL;
        if (ri1->next)
          for (ri2 = ri1->next; ri2; ri2 = ri2->next)
            {
@@ -1328,17 +1331,30 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn,
                  || aspath_cmp_left_confed (ri1->attr->aspath,
                                             ri2->attr->aspath))
                {
+                 if (CHECK_FLAG (ri2->flags, BGP_INFO_SELECTED))
+                   old_select = ri2;
                  if (bgp_info_cmp (bgp, ri2, new_select, &paths_eq))
                    {
                      bgp_info_unset_flag (rn, new_select, BGP_INFO_DMED_SELECTED);
                      new_select = ri2;
+                     if (do_mpath && !paths_eq)
+                       {
+                         bgp_mp_list_clear (&mp_list);
+                         bgp_mp_list_add (&mp_list, ri2);
+                       }
                    }
 
+                 if (do_mpath && paths_eq)
+                   bgp_mp_list_add (&mp_list, ri2);
+
                  bgp_info_set_flag (rn, ri2, BGP_INFO_DMED_CHECK);
                }
            }
        bgp_info_set_flag (rn, new_select, BGP_INFO_DMED_CHECK);
        bgp_info_set_flag (rn, new_select, BGP_INFO_DMED_SELECTED);
+
+       bgp_info_mpath_update (rn, new_select, old_select, &mp_list, mpath_cfg);
+       bgp_mp_list_clear (&mp_list);
       }
 
   /* Check old selected route and new selected route. */
@@ -1372,6 +1388,9 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn,
 
       if (bgp_info_cmp (bgp, ri, new_select, &paths_eq))
        {
+         if (do_mpath && bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
+           bgp_mp_dmed_deselect (new_select);
+
          new_select = ri;
 
          if (do_mpath && !paths_eq)
@@ -1380,13 +1399,16 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn,
              bgp_mp_list_add (&mp_list, ri);
            }
        }
+      else if (do_mpath && bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
+       bgp_mp_dmed_deselect (ri);
 
       if (do_mpath && paths_eq)
        bgp_mp_list_add (&mp_list, ri);
     }
     
 
-  bgp_info_mpath_update (rn, new_select, old_select, &mp_list, mpath_cfg);
+  if (!bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
+    bgp_info_mpath_update (rn, new_select, old_select, &mp_list, mpath_cfg);
 
   bgp_mp_list_clear (&mp_list);