From 96450faf3385a6ed9f4dd5c2c58776c4a664a8da Mon Sep 17 00:00:00 2001 From: Josh Bailey Date: Wed, 20 Jul 2011 20:45:12 -0700 Subject: bgpd: Adds equal-paths check to path comparison. Paths that are equal to the best path are accumulated onto an ordered list (mp_list) if maximum-paths is configured. A future commit will add the multipath markup to the BGP rib table based on the mp_list. Add unit test for the added mp_list functions. Deterministic MED is not supported in this commit, it will be added later. * bgpd/bgp_aspath.c * Make aspath_cmp() an external symbol so it can be used in equivalent paths check * bgpd/bgp_aspath.h * Add extern declaration of aspath_cmp() * bgpd/bgp_mpath.c * bgp_info_nexthop_cmp(): Compares nexthops of two paths * bgp_info_mpath_cmp(): Compare function to order multipaths by nexthop and then by peer address * bgp_mp_list_init(): Initialize a list with the multipath order function * bgp_mp_list_clear(): Clear out the mp_list * bgp_mp_list_add(): Add a multipath to mp_list * bgpd/bgp_mpath.h * External declarations for above added functions in bgp_mpath.c * bgpd/bgp_route.c * bgp_info_cmp(): Add equivalent paths result (paths_eq). If eBGP paths are equal down to IGP metric check, flag as equal if peer AS matches. Similarly for iBGP paths but compare full AS_PATH. * bgp_best_selection(): If multipath is enabled, accumulate equivalent paths in mp_list. Add debug bgp event output to see result (will be filtered later to display only when change occurs) * bgp_process_rsclient(): Pass multipath config to bgp_best_selection() * bgp_process_main(): Pass multipath config to bgp_best_selection() * tests/bgp_mpath_test.c * Add unit test case for bgp_mp_list functions --- bgpd/bgp_route.c | 113 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 92 insertions(+), 21 deletions(-) (limited to 'bgpd/bgp_route.c') diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 5c516f02..718e25ff 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -54,6 +54,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_advertise.h" #include "bgpd/bgp_zebra.h" #include "bgpd/bgp_vty.h" +#include "bgpd/bgp_mpath.h" /* Extern from bgp_dump.c */ extern const char *bgp_origin_str[]; @@ -316,7 +317,8 @@ bgp_med_value (struct attr *attr, struct bgp *bgp) /* Compare two bgp route entity. br is preferable then return 1. */ static int -bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist) +bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist, + int *paths_eq) { u_int32_t new_pref; u_int32_t exist_pref; @@ -331,6 +333,9 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist) int internal_as_route = 0; int confed_as_route = 0; int ret; + uint32_t newm, existm; + + *paths_eq = 0; /* 0. Null check. */ if (new == NULL) @@ -454,18 +459,32 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist) return 0; /* 8. IGP metric check. */ - if (new->extra || exist->extra) - { - uint32_t newm = (new->extra ? new->extra->igpmetric : 0); - uint32_t existm = (exist->extra ? exist->extra->igpmetric : 0); - - if (newm < existm) - return 1; - if (newm > existm) - return 0; - } + newm = (new->extra ? new->extra->igpmetric : 0); + existm = (exist->extra ? exist->extra->igpmetric : 0); + if (newm < existm) + ret = 1; + if (newm > existm) + ret = 0; /* 9. Maximum path check. */ + if (newm == existm) + { + if ((peer_sort (new->peer) == BGP_PEER_IBGP)) + { + if (aspath_cmp (new->attr->aspath, exist->attr->aspath)) + *paths_eq = 1; + } + else if (new->peer->as == exist->peer->as) + *paths_eq = 1; + } + else + { + /* + * TODO: If unequal cost ibgp multipath is enabled we can + * mark the paths as equal here instead of returning + */ + return ret; + } /* 10. If both paths are external, prefer the path that was received first (the oldest one). This step minimizes route-flap, since a @@ -1267,7 +1286,9 @@ struct bgp_info_pair }; static void -bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, struct bgp_info_pair *result) +bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, + struct bgp_maxpaths_cfg *mpath_cfg, + struct bgp_info_pair *result) { struct bgp_info *new_select; struct bgp_info *old_select; @@ -1275,7 +1296,13 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, struct bgp_info_pair * struct bgp_info *ri1; struct bgp_info *ri2; struct bgp_info *nextri = NULL; - + int paths_eq, do_mpath; + struct list mp_list; + + bgp_mp_list_init (&mp_list); + do_mpath = (mpath_cfg->maxpaths_ebgp != BGP_DEFAULT_MAXPATHS || + mpath_cfg->maxpaths_ibgp != BGP_DEFAULT_MAXPATHS); + /* bgp deterministic-med */ new_select = NULL; if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED)) @@ -1299,7 +1326,7 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, struct bgp_info_pair * || aspath_cmp_left_confed (ri1->attr->aspath, ri2->attr->aspath)) { - if (bgp_info_cmp (bgp, ri2, new_select)) + if (bgp_info_cmp (bgp, ri2, new_select, &paths_eq)) { bgp_info_unset_flag (rn, new_select, BGP_INFO_DMED_SELECTED); new_select = ri2; @@ -1341,14 +1368,58 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, struct bgp_info_pair * bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_CHECK); bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_SELECTED); - if (bgp_info_cmp (bgp, ri, new_select)) - new_select = ri; + if (bgp_info_cmp (bgp, ri, new_select, &paths_eq)) + { + new_select = ri; + + if (do_mpath && !paths_eq) + { + bgp_mp_list_clear (&mp_list); + bgp_mp_list_add (&mp_list, ri); + } + } + + if (do_mpath && paths_eq) + bgp_mp_list_add (&mp_list, ri); } - result->old = old_select; - result->new = new_select; - return; + /* + * TODO: Will add some additional filtering later to only + * output debugs when multipath state for the route changes + */ + if (BGP_DEBUG (events, EVENTS) && do_mpath) + { + struct listnode *mp_node; + struct bgp_info *mp_info; + char buf[2][INET_ADDRSTRLEN]; + + prefix2str (&rn->p, buf[0], sizeof (buf[0])); + zlog_debug ("%s bestpath nexthop %s, %d mpath candidates", + buf[0], + (new_select ? + inet_ntop(AF_INET, &new_select->attr->nexthop, + buf[1], sizeof (buf[1])) : + "None"), + listcount (&mp_list)); + for (mp_node = listhead (&mp_list); mp_node; + mp_node = listnextnode (mp_node)) + { + mp_info = listgetdata (mp_node); + if (mp_info == new_select) + continue; + zlog_debug (" candidate mpath nexthop %s", + inet_ntop(AF_INET, &mp_info->attr->nexthop, buf[0], + sizeof (buf[0]))); + } + } + + bgp_mp_list_clear (&mp_list); + + result->old = old_select; + result->new = new_select; + + return; } static int @@ -1422,7 +1493,7 @@ bgp_process_rsclient (struct work_queue *wq, void *data) struct peer *rsclient = rn->table->owner; /* Best path selection. */ - bgp_best_selection (bgp, rn, &old_and_new); + bgp_best_selection (bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new); new_select = old_and_new.new; old_select = old_and_new.old; @@ -1483,7 +1554,7 @@ bgp_process_main (struct work_queue *wq, void *data) struct peer *peer; /* Best path selection. */ - bgp_best_selection (bgp, rn, &old_and_new); + bgp_best_selection (bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new); old_select = old_and_new.old; new_select = old_and_new.new; -- cgit v1.2.1 From de8d5dff1523bb9fe47d54f31c9e5322bd805b44 Mon Sep 17 00:00:00 2001 From: Josh Bailey Date: Wed, 20 Jul 2011 20:46:01 -0700 Subject: bgpd: Adds support to mark up the BGP rib table entry with multipath information based on the multipath list (mp_list) generated during the best path calculation. Display "multipath" for paths that are multipath and also on bestpath if the route is multipath. Flag a best path with the BGP_INFO_MULTIPATH_CHG if the multipath set has changed since the last update. This can be used to trigger updates to zebra and peers. The multipath markup is a lazily allocated bgp_info_mpath structure that is added to the best path and any multipaths. The mpath structures are linked together with the best path element at the head and the other elements ordered by nexthop and then by peer address. This markup scheme is updated by calling bgp_info_mpath_update() and passing in a new mp_list the the current multipath set. There are additional API's for walking the multipath set, querying the count of multipaths, and for cleaning up the multipath markup information when freeing path information. * bgpd/bgp_mpath.c * bgp_info_mpath_new(): Allocation of new mpath element * bgp_info_mpath_free(): Release memory for mpath element * bgp_info_mpath_get(): Access mpath element of path. Allocate memory on-demand * bgp_info_mpath_enqueue(): Enqueue a path onto the multipath list * bgp_info_mpath_dequeue(): Remove a path from the multipath list * bgp_info_mpath_first(): Return first path on the multipath list * bgp_info_mpath_next(): Return next path on the multipath list * bgp_info_mpath_count(): Return the number of paths on the multipath list * bgp_info_mpath_count_set(): Set the number of paths on the multipath list * bgp_info_mpath_update(): Update multipath markup on bgp route table entry and flag any changes. Emit 'debug bgp event' output on any multipath change. * bgpd/bgp_mpath.h * struct bgp_info_mpath: Information added to a bgp_info path to record multipath information * External declarations for new functions in bgp_mpath.c * bgpd/bgp_route.c * bgp_info_free(): Free mpath memory when freeing path information * bgp_info_reap(): Dequeue path from multipath queue before deleting it * bgp_best_selection(): Calls bgp_info_mpath_update() with latest mp_list to mark-up rib table entry * bgp_vty_out_detail(): Add display of multipath flag for a path. Also display 'multipath' for bestpath if it is a multipath route * bgpd/bgp_route.h * struct bgp_info: Add pointer to bgp_info_mpath information * Add flags to mark a path as multipath (BGP_INFO_MULTIPATH) and to mark bestpath if multipath information has changed (BGP_INFO_MULTIPATH_CHG) * lib/memtypes.c * Add MTYPE_BGP_MPATH_INFO for allocating memory for bgp_info_mpath * tests/bgp_mpath_test.c * Add test case for bgp_info_mpath_update() and supporting functions --- bgpd/bgp_route.c | 37 ++++++++----------------------------- 1 file changed, 8 insertions(+), 29 deletions(-) (limited to 'bgpd/bgp_route.c') diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 718e25ff..ec17dc61 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -141,6 +141,7 @@ bgp_info_free (struct bgp_info *binfo) bgp_attr_unintern (binfo->attr); bgp_info_extra_free (&binfo->extra); + bgp_info_mpath_free (&binfo->mpath); peer_unlock (binfo->peer); /* bgp_info peer reference */ @@ -211,6 +212,7 @@ bgp_info_reap (struct bgp_node *rn, struct bgp_info *ri) else rn->info = ri->next; + bgp_info_mpath_dequeue (ri); bgp_info_unlock (ri); bgp_unlock_node (rn); } @@ -1384,35 +1386,7 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, } - /* - * TODO: Will add some additional filtering later to only - * output debugs when multipath state for the route changes - */ - if (BGP_DEBUG (events, EVENTS) && do_mpath) - { - struct listnode *mp_node; - struct bgp_info *mp_info; - char buf[2][INET_ADDRSTRLEN]; - - prefix2str (&rn->p, buf[0], sizeof (buf[0])); - zlog_debug ("%s bestpath nexthop %s, %d mpath candidates", - buf[0], - (new_select ? - inet_ntop(AF_INET, &new_select->attr->nexthop, - buf[1], sizeof (buf[1])) : - "None"), - listcount (&mp_list)); - for (mp_node = listhead (&mp_list); mp_node; - mp_node = listnextnode (mp_node)) - { - mp_info = listgetdata (mp_node); - if (mp_info == new_select) - continue; - zlog_debug (" candidate mpath nexthop %s", - inet_ntop(AF_INET, &mp_info->attr->nexthop, buf[0], - sizeof (buf[0]))); - } - } + bgp_info_mpath_update (rn, new_select, old_select, &mp_list, mpath_cfg); bgp_mp_list_clear (&mp_list); @@ -5995,6 +5969,11 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) vty_out (vty, ", atomic-aggregate"); + if (CHECK_FLAG (binfo->flags, BGP_INFO_MULTIPATH) || + (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED) && + bgp_info_mpath_count (binfo))) + vty_out (vty, ", multipath"); + if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED)) vty_out (vty, ", best"); -- cgit v1.2.1 From 8196f13d2ab7f3b09150c00328228f90391acb7c Mon Sep 17 00:00:00 2001 From: Josh Bailey Date: Wed, 20 Jul 2011 20:47:07 -0700 Subject: bgpd: Modify the BGP to zebra route announcement to support multipath routes. Use a growable buffer (bgp_nexthop_buf) to collect nexthops that are included in the announcement. Use the BGP_INFO_MULTIPATH_CHG flag to trigger zebra announcement so zebra will be updated if the multipath set changes. Display all multipath nexthops in 'debug bgp zebra' output. * bgpd/bgp_main.c * bgp_exit(): Free bgp_nexthop_buf when exiting * bgpd/bgp_route.c * bgp_process_rsclient(): Clear BGP_INFO_MULTIPATH_CHG after processing * bgp_process_main(): Check BGP_INFO_MULTIPATH_CHG to trigger zebra announcement and clear aftr processing * bgpd/bgp_zebra.c * bgp_nexthop_buf: Growable buffer used to collect nexthops for zebra announcement * bgp_zebra_announce(): Grow bgp_nexthop_buf if needed. Include multipath count in zebra announcement and add all nexthops to bgp_nexthop_buf. Pass bgp_nexthop_buf data to zebra announcement. Added nexthops to debug output. * bgp_zebra_init(): Initialize bgp_nexthop_buf at startup * bgpd/bgp_zebra.h * BGP_NEXTHOP_BUF_SIZE: Default initial bgp_nexthop_buf size has room for 8 nexthops --- bgpd/bgp_route.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'bgpd/bgp_route.c') diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index ec17dc61..f3e46221 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1487,7 +1487,8 @@ bgp_process_rsclient (struct work_queue *wq, void *data) { bgp_info_set_flag (rn, new_select, BGP_INFO_SELECTED); bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED); - } + UNSET_FLAG (new_select->flags, BGP_INFO_MULTIPATH_CHG); + } bgp_process_announce_selected (rsclient, new_select, rn, afi, safi); @@ -1501,6 +1502,7 @@ bgp_process_rsclient (struct work_queue *wq, void *data) { bgp_info_set_flag (rn, new_select, BGP_INFO_SELECTED); bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED); + UNSET_FLAG (new_select->flags, BGP_INFO_MULTIPATH_CHG); } bgp_process_announce_selected (rsclient, new_select, rn, afi, safi); } @@ -1537,9 +1539,11 @@ bgp_process_main (struct work_queue *wq, void *data) { if (! CHECK_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED)) { - if (CHECK_FLAG (old_select->flags, BGP_INFO_IGP_CHANGED)) + if (CHECK_FLAG (old_select->flags, BGP_INFO_IGP_CHANGED) || + CHECK_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG)) bgp_zebra_announce (p, old_select, bgp); + UNSET_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG); UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED); return WQ_SUCCESS; } @@ -1551,6 +1555,7 @@ bgp_process_main (struct work_queue *wq, void *data) { bgp_info_set_flag (rn, new_select, BGP_INFO_SELECTED); bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED); + UNSET_FLAG (new_select->flags, BGP_INFO_MULTIPATH_CHG); } -- cgit v1.2.1 From 6918e74b97fd40f947ebd2eded9ab24b8569d3b8 Mon Sep 17 00:00:00 2001 From: Josh Bailey Date: Wed, 20 Jul 2011 20:48:20 -0700 Subject: 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. --- bgpd/bgp_route.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'bgpd/bgp_route.c') 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); -- cgit v1.2.1 From 0b597ef00ec7c7eebd836e2b1d5a266efcd60005 Mon Sep 17 00:00:00 2001 From: Josh Bailey Date: Wed, 20 Jul 2011 20:49:11 -0700 Subject: bgpd: When advertising a multipath route, the attribute set to be advertised is based on the bestpath attribute set, but the following attributes are aggregated from the attribute sets of the multipath constituents: - AS_PATH - ORIGIN - COMMUNITIES - EXTENDED COMMUNITIES In addition the route is advertised with the NEXT_HOP set to the router's interface IP address, instead of the NEXT_HOP of the best path. This is to ensure that traffic will go to this router so it can be fanned out via the multipath route. * bgpd/ecommunity.c * ecommunity_uniq_sort(): Make this function externally accessible * bgpd/ecommunity.h * Add external declaration for ecommunity_uniq_sort() * bgpd/bgp_mpath.c * bgp_info_nexthop_cmp(): Replace calls to bgp_attr_extra_get() to avoid unwanted memory allocation * bgp_info_mpath_free(): Free aggregate attribute for multipath * bgp_info_mpath_attr(): Lookup aggregate attribute of a multipath route * bgp_info_mpath_attr_set(): Set aggregate attribute of a multipath route * bgp_info_mpath_aggregate_update(): Update the aggregate attribute of a multipath route * bgpd/bgp_mpath.h * bgp_info_mpath: Add pointer to hold aggregate attribute of a multipath * Add external declarations for new functions * bgpd/bgp_route.c * bgp_announce_check(): Use aggregate attribute when announcing multipath route * bgp_announce_check_rsclient(): Use aggregate attribute when announcing multipath route * bgp_best_selection(): After updating multipath set, update the multipath aggregate attribute --- bgpd/bgp_route.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'bgpd/bgp_route.c') diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 5c4ab266..a4923f57 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -785,10 +785,12 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, struct bgp *bgp; int transparent; int reflect; + struct attr *riattr; from = ri->peer; filter = &peer->filter[afi][safi]; bgp = peer->bgp; + riattr = bgp_info_mpath_count (ri) ? bgp_info_mpath_attr (ri) : ri->attr; if (DISABLE_BGP_ANNOUNCE) return 0; @@ -803,11 +805,11 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, /* If peer's id and route's nexthop are same. draft-ietf-idr-bgp4-23 5.1.3 */ if (p->family == AF_INET - && IPV4_ADDR_SAME(&peer->remote_id, &ri->attr->nexthop)) + && IPV4_ADDR_SAME(&peer->remote_id, &riattr->nexthop)) return 0; #ifdef HAVE_IPV6 if (p->family == AF_INET6 - && IPV6_ADDR_SAME(&peer->remote_id, &ri->attr->nexthop)) + && IPV6_ADDR_SAME(&peer->remote_id, &riattr->nexthop)) return 0; #endif @@ -835,14 +837,14 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, transparent = 0; /* If community is not disabled check the no-export and local. */ - if (! transparent && bgp_community_filter (peer, ri->attr)) + if (! transparent && bgp_community_filter (peer, riattr)) return 0; /* If the attribute has originator-id and it is same as remote peer's id. */ - if (ri->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID)) + if (riattr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID)) { - if (IPV4_ADDR_SAME (&peer->remote_id, &ri->attr->extra->originator_id)) + if (IPV4_ADDR_SAME (&peer->remote_id, &riattr->extra->originator_id)) { if (BGP_DEBUG (filter, FILTER)) zlog (peer->log, LOG_DEBUG, @@ -865,7 +867,7 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, } /* Output filter check. */ - if (bgp_output_filter (peer, p, ri->attr, afi, safi) == FILTER_DENY) + if (bgp_output_filter (peer, p, riattr, afi, safi) == FILTER_DENY) { if (BGP_DEBUG (filter, FILTER)) zlog (peer->log, LOG_DEBUG, @@ -878,7 +880,7 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, #ifdef BGP_SEND_ASPATH_CHECK /* AS path loop check. */ - if (aspath_loop_check (ri->attr->aspath, peer->as)) + if (aspath_loop_check (riattr->aspath, peer->as)) { if (BGP_DEBUG (filter, FILTER)) zlog (peer->log, LOG_DEBUG, @@ -891,7 +893,7 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, /* If we're a CONFED we need to loop check the CONFED ID too */ if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) { - if (aspath_loop_check(ri->attr->aspath, bgp->confed_id)) + if (aspath_loop_check(riattr->aspath, bgp->confed_id)) { if (BGP_DEBUG (filter, FILTER)) zlog (peer->log, LOG_DEBUG, @@ -932,7 +934,7 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, } /* For modify attribute, copy it to temporary structure. */ - bgp_attr_dup (attr, ri->attr); + bgp_attr_dup (attr, riattr); /* If local-preference is not set. */ if ((peer_sort (peer) == BGP_PEER_IBGP @@ -1091,10 +1093,12 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, struct bgp_info info; struct peer *from; struct bgp *bgp; + struct attr *riattr; from = ri->peer; filter = &rsclient->filter[afi][safi]; bgp = rsclient->bgp; + riattr = bgp_info_mpath_count (ri) ? bgp_info_mpath_attr (ri) : ri->attr; if (DISABLE_BGP_ANNOUNCE) return 0; @@ -1122,10 +1126,10 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, /* If the attribute has originator-id and it is same as remote peer's id. */ - if (ri->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID)) + if (riattr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID)) { if (IPV4_ADDR_SAME (&rsclient->remote_id, - &ri->attr->extra->originator_id)) + &riattr->extra->originator_id)) { if (BGP_DEBUG (filter, FILTER)) zlog (rsclient->log, LOG_DEBUG, @@ -1148,7 +1152,7 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, } /* Output filter check. */ - if (bgp_output_filter (rsclient, p, ri->attr, afi, safi) == FILTER_DENY) + if (bgp_output_filter (rsclient, p, riattr, afi, safi) == FILTER_DENY) { if (BGP_DEBUG (filter, FILTER)) zlog (rsclient->log, LOG_DEBUG, @@ -1161,7 +1165,7 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, #ifdef BGP_SEND_ASPATH_CHECK /* AS path loop check. */ - if (aspath_loop_check (ri->attr->aspath, rsclient->as)) + if (aspath_loop_check (riattr->aspath, rsclient->as)) { if (BGP_DEBUG (filter, FILTER)) zlog (rsclient->log, LOG_DEBUG, @@ -1172,7 +1176,7 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, #endif /* BGP_SEND_ASPATH_CHECK */ /* For modify attribute, copy it to temporary structure. */ - bgp_attr_dup (attr, ri->attr); + bgp_attr_dup (attr, riattr); /* next-hop-set */ if ((p->family == AF_INET && attr->nexthop.s_addr == 0) @@ -1410,6 +1414,7 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, if (!bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED)) bgp_info_mpath_update (rn, new_select, old_select, &mp_list, mpath_cfg); + bgp_info_mpath_aggregate_update (new_select, old_select); bgp_mp_list_clear (&mp_list); result->old = old_select; -- cgit v1.2.1