summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Bailey <joshb@google.com>2011-07-20 20:48:20 -0700
committerJosh Bailey <joshb@google.com>2011-07-20 20:48:20 -0700
commit6918e74b97fd40f947ebd2eded9ab24b8569d3b8 (patch)
treee7d5e43b25eaf963065016d3998a78e5e5568111
parent8196f13d2ab7f3b09150c00328228f90391acb7c (diff)
bgpd: For deterministic MED build a multipath set for each peer AS as the
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.
-rw-r--r--bgpd/bgp_mpath.c25
-rw-r--r--bgpd/bgp_mpath.h1
-rw-r--r--bgpd/bgp_route.c24
3 files changed, 49 insertions, 1 deletions
diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c
index af1c342c..7944c55f 100644
--- a/bgpd/bgp_mpath.c
+++ b/bgpd/bgp_mpath.c
@@ -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);
+}
diff --git a/bgpd/bgp_mpath.h b/bgpd/bgp_mpath.h
index 1dc2687e..3712493e 100644
--- a/bgpd/bgp_mpath.h
+++ b/bgpd/bgp_mpath.h
@@ -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 *);
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index f3e46221..5c4ab266 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -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);