diff options
Diffstat (limited to 'bgpd/bgp_updgrp_adv.c')
| -rw-r--r-- | bgpd/bgp_updgrp_adv.c | 110 | 
1 files changed, 85 insertions, 25 deletions
diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index 33617811cf..ccbb23ebb4 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -87,6 +87,67 @@ static void adj_free(struct bgp_adj_out *adj)  	XFREE(MTYPE_BGP_ADJ_OUT, adj);  } +static void +subgrp_announce_addpath_best_selected(struct bgp_dest *dest, +				      struct update_subgroup *subgrp) +{ +	afi_t afi = SUBGRP_AFI(subgrp); +	safi_t safi = SUBGRP_SAFI(subgrp); +	struct peer *peer = SUBGRP_PEER(subgrp); +	enum bgp_path_selection_reason reason; +	char pfx_buf[PREFIX2STR_BUFFER] = {}; +	int paths_eq = 0; +	int best_path_count = 0; +	struct list *list = list_new(); +	struct bgp_path_info *pi = NULL; + +	if (peer->addpath_type[afi][safi] == BGP_ADDPATH_BEST_SELECTED) { +		while (best_path_count++ < +		       peer->addpath_best_selected[afi][safi]) { +			struct bgp_path_info *exist = NULL; + +			for (pi = bgp_dest_get_bgp_path_info(dest); pi; +			     pi = pi->next) { +				if (listnode_lookup(list, pi)) +					continue; + +				if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) +					continue; + +				if (bgp_path_info_cmp(peer->bgp, pi, exist, +						      &paths_eq, NULL, 0, +						      pfx_buf, afi, safi, +						      &reason)) +					exist = pi; +			} + +			if (exist) +				listnode_add(list, exist); +		} +	} + +	for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) { +		uint32_t id = bgp_addpath_id_for_peer(peer, afi, safi, +						      &pi->tx_addpath); + +		if (peer->addpath_type[afi][safi] == +		    BGP_ADDPATH_BEST_SELECTED) { +			if (listnode_lookup(list, pi)) +				subgroup_process_announce_selected( +					subgrp, pi, dest, afi, safi, id); +			else +				subgroup_process_announce_selected( +					subgrp, NULL, dest, afi, safi, id); +		} else { +			subgroup_process_announce_selected(subgrp, pi, dest, +							   afi, safi, id); +		} +	} + +	if (list) +		list_delete(&list); +} +  static void subgrp_withdraw_stale_addpath(struct updwalk_context *ctx,  					  struct update_subgroup *subgrp)  { @@ -125,7 +186,6 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg)  {  	struct updwalk_context *ctx = arg;  	struct update_subgroup *subgrp; -	struct bgp_path_info *pi;  	afi_t afi;  	safi_t safi;  	struct peer *peer; @@ -143,7 +203,6 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg)  			   bgp_dest_to_rnode(ctx->dest));  	UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) { -  		/*  		 * Skip the subgroups that have coalesce timer running. We will  		 * walk the entire prefix table for those subgroups when the @@ -155,19 +214,8 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg)  			if (addpath_capable) {  				subgrp_withdraw_stale_addpath(ctx, subgrp); -				for (pi = bgp_dest_get_bgp_path_info(ctx->dest); -				     pi; pi = pi->next) { -					/* Skip the bestpath for now */ -					if (pi == ctx->pi) -						continue; - -					subgroup_process_announce_selected( -						subgrp, pi, ctx->dest, afi, -						safi, -						bgp_addpath_id_for_peer( -							peer, afi, safi, -							&pi->tx_addpath)); -				} +				subgrp_announce_addpath_best_selected(ctx->dest, +								      subgrp);  				/* Process the bestpath last so the "show [ip]  				 * bgp neighbor x.x.x.x advertised" @@ -307,6 +355,7 @@ static void subgroup_coalesce_timer(struct event *thread)  {  	struct update_subgroup *subgrp;  	struct bgp *bgp; +	safi_t safi;  	subgrp = EVENT_ARG(thread);  	if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0)) @@ -317,7 +366,7 @@ static void subgroup_coalesce_timer(struct event *thread)  	subgrp->v_coalesce = 0;  	bgp = SUBGRP_INST(subgrp);  	subgroup_announce_route(subgrp); - +	safi = SUBGRP_SAFI(subgrp);  	/* While the announce_route() may kick off the route advertisement timer  	 * for @@ -328,14 +377,18 @@ static void subgroup_coalesce_timer(struct event *thread)  	 * announce, this is the method currently employed to trigger the EOR.  	 */  	if (!bgp_update_delay_active(SUBGRP_INST(subgrp)) && -	    !(BGP_SUPPRESS_FIB_ENABLED(bgp))) { +	    !(bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp))) { +  		struct peer_af *paf;  		struct peer *peer;  		SUBGRP_FOREACH_PEER (subgrp, paf) {  			peer = PAF_PEER(paf); -			EVENT_OFF(peer->t_routeadv); -			BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0); +			struct peer_connection *connection = peer->connection; + +			EVENT_OFF(connection->t_routeadv); +			BGP_TIMER_ON(connection->t_routeadv, bgp_routeadv_timer, +				     0);  		}  	}  } @@ -549,7 +602,8 @@ void bgp_adj_out_set_subgroup(struct bgp_dest *dest,  			 * the flag PEER_STATUS_ADV_DELAY which will allow  			 * more routes to be sent in the update message  			 */ -			if (BGP_SUPPRESS_FIB_ENABLED(bgp)) { +			if (bgp_fibupd_safi(safi) && +			    BGP_SUPPRESS_FIB_ENABLED(bgp)) {  				adv_peer = PAF_PEER(paf);  				if (!bgp_adv_fifo_count(  						&subgrp->sync->withdraw)) @@ -686,6 +740,10 @@ void subgroup_announce_table(struct update_subgroup *subgrp,  	SET_FLAG(subgrp->sflags, SUBGRP_STATUS_TABLE_REPARSING);  	for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) { + +		if (addpath_capable) +			subgrp_announce_addpath_best_selected(dest, subgrp); +  		for (ri = bgp_dest_get_bgp_path_info(dest); ri; ri = ri->next) {  			if (!bgp_check_selected(ri, peer, addpath_capable, afi, @@ -703,10 +761,12 @@ void subgroup_announce_table(struct update_subgroup *subgrp,  			    is_default_prefix(bgp_dest_get_prefix(dest)))  				break; -			subgroup_process_announce_selected( -				subgrp, ri, dest, afi, safi_rib, -				bgp_addpath_id_for_peer(peer, afi, safi_rib, -							&ri->tx_addpath)); +			if (CHECK_FLAG(ri->flags, BGP_PATH_SELECTED)) +				subgroup_process_announce_selected( +					subgrp, ri, dest, afi, safi_rib, +					bgp_addpath_id_for_peer( +						peer, afi, safi_rib, +						&ri->tx_addpath));  		}  	}  	UNSET_FLAG(subgrp->sflags, SUBGRP_STATUS_TABLE_REPARSING); @@ -1014,7 +1074,7 @@ void group_announce_route(struct bgp *bgp, afi_t afi, safi_t safi,  	/* If suppress fib is enabled, the route will be advertised when  	 * FIB status is received  	 */ -	if (!bgp_check_advertise(bgp, dest)) +	if (!bgp_check_advertise(bgp, dest, safi))  		return;  	update_group_af_walk(bgp, afi, safi, group_announce_route_walkcb, &ctx);  | 
