diff options
Diffstat (limited to 'bgpd/bgp_route.c')
| -rw-r--r-- | bgpd/bgp_route.c | 17922 | 
1 files changed, 9058 insertions, 8864 deletions
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 9b85ad3d96..f8db12df59 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -77,119 +77,109 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  extern const char *bgp_origin_str[];  extern const char *bgp_origin_long_str[]; -struct bgp_node * -bgp_afi_node_get (struct bgp_table *table, afi_t afi, safi_t safi, struct prefix *p, -		  struct prefix_rd *prd) -{ -  struct bgp_node *rn; -  struct bgp_node *prn = NULL; -   -  assert (table); -  if (!table) -    return NULL; -   -  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || -      (safi == SAFI_EVPN)) -    { -      prn = bgp_node_get (table, (struct prefix *) prd); - -      if (prn->info == NULL) -	prn->info = bgp_table_init (afi, safi); -      else -	bgp_unlock_node (prn); -      table = prn->info; -    } +struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi, +				  safi_t safi, struct prefix *p, +				  struct prefix_rd *prd) +{ +	struct bgp_node *rn; +	struct bgp_node *prn = NULL; + +	assert(table); +	if (!table) +		return NULL; + +	if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) +	    || (safi == SAFI_EVPN)) { +		prn = bgp_node_get(table, (struct prefix *)prd); + +		if (prn->info == NULL) +			prn->info = bgp_table_init(afi, safi); +		else +			bgp_unlock_node(prn); +		table = prn->info; +	} -  rn = bgp_node_get (table, p); +	rn = bgp_node_get(table, p); -  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || -      (safi == SAFI_EVPN)) -    rn->prn = prn; +	if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) +	    || (safi == SAFI_EVPN)) +		rn->prn = prn; -  return rn; +	return rn;  }  /* Allocate bgp_info_extra */ -static struct bgp_info_extra * -bgp_info_extra_new (void) +static struct bgp_info_extra *bgp_info_extra_new(void)  { -  struct bgp_info_extra *new; -  new = XCALLOC (MTYPE_BGP_ROUTE_EXTRA, sizeof (struct bgp_info_extra)); -  return new; +	struct bgp_info_extra *new; +	new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA, sizeof(struct bgp_info_extra)); +	return new;  } -static void -bgp_info_extra_free (struct bgp_info_extra **extra) +static void bgp_info_extra_free(struct bgp_info_extra **extra)  { -  if (extra && *extra) -    { -      if ((*extra)->damp_info) -        bgp_damp_info_free ((*extra)->damp_info, 0); -       -      (*extra)->damp_info = NULL; -       -      XFREE (MTYPE_BGP_ROUTE_EXTRA, *extra); -       -      *extra = NULL; -    } +	if (extra && *extra) { +		if ((*extra)->damp_info) +			bgp_damp_info_free((*extra)->damp_info, 0); + +		(*extra)->damp_info = NULL; + +		XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra); + +		*extra = NULL; +	}  }  /* Get bgp_info extra information for the given bgp_info, lazy allocated   * if required.   */ -struct bgp_info_extra * -bgp_info_extra_get (struct bgp_info *ri) +struct bgp_info_extra *bgp_info_extra_get(struct bgp_info *ri)  { -  if (!ri->extra) -    ri->extra = bgp_info_extra_new(); -  return ri->extra; +	if (!ri->extra) +		ri->extra = bgp_info_extra_new(); +	return ri->extra;  }  /* Allocate new bgp info structure. */ -struct bgp_info * -bgp_info_new (void) +struct bgp_info *bgp_info_new(void)  { -  return XCALLOC (MTYPE_BGP_ROUTE, sizeof (struct bgp_info)); +	return XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_info));  }  /* Free bgp route information. */ -static void -bgp_info_free (struct bgp_info *binfo) +static void bgp_info_free(struct bgp_info *binfo)  { -  if (binfo->attr) -    bgp_attr_unintern (&binfo->attr); +	if (binfo->attr) +		bgp_attr_unintern(&binfo->attr); -  bgp_unlink_nexthop(binfo); -  bgp_info_extra_free (&binfo->extra); -  bgp_info_mpath_free (&binfo->mpath); +	bgp_unlink_nexthop(binfo); +	bgp_info_extra_free(&binfo->extra); +	bgp_info_mpath_free(&binfo->mpath); -  peer_unlock (binfo->peer); /* bgp_info peer reference */ +	peer_unlock(binfo->peer); /* bgp_info peer reference */ -  XFREE (MTYPE_BGP_ROUTE, binfo); +	XFREE(MTYPE_BGP_ROUTE, binfo);  } -struct bgp_info * -bgp_info_lock (struct bgp_info *binfo) +struct bgp_info *bgp_info_lock(struct bgp_info *binfo)  { -  binfo->lock++; -  return binfo; +	binfo->lock++; +	return binfo;  } -struct bgp_info * -bgp_info_unlock (struct bgp_info *binfo) +struct bgp_info *bgp_info_unlock(struct bgp_info *binfo)  { -  assert (binfo && binfo->lock > 0); -  binfo->lock--; -   -  if (binfo->lock == 0) -    { +	assert(binfo && binfo->lock > 0); +	binfo->lock--; + +	if (binfo->lock == 0) {  #if 0        zlog_debug ("%s: unlocked and freeing", __func__);        zlog_backtrace (LOG_DEBUG);  #endif -      bgp_info_free (binfo); -      return NULL; -    } +		bgp_info_free(binfo); +		return NULL; +	}  #if 0    if (binfo->lock == 1) @@ -198,1642 +188,1664 @@ bgp_info_unlock (struct bgp_info *binfo)        zlog_backtrace (LOG_DEBUG);      }  #endif -   -  return binfo; + +	return binfo;  } -void -bgp_info_add (struct bgp_node *rn, struct bgp_info *ri) +void bgp_info_add(struct bgp_node *rn, struct bgp_info *ri)  { -  struct bgp_info *top; +	struct bgp_info *top; -  top = rn->info; -   -  ri->next = rn->info; -  ri->prev = NULL; -  if (top) -    top->prev = ri; -  rn->info = ri; -   -  bgp_info_lock (ri); -  bgp_lock_node (rn); -  peer_lock (ri->peer); /* bgp_info peer reference */ +	top = rn->info; + +	ri->next = rn->info; +	ri->prev = NULL; +	if (top) +		top->prev = ri; +	rn->info = ri; + +	bgp_info_lock(ri); +	bgp_lock_node(rn); +	peer_lock(ri->peer); /* bgp_info peer reference */  } -/* Do the actual removal of info from RIB, for use by bgp_process  +/* Do the actual removal of info from RIB, for use by bgp_process     completion callback *only* */ -static void -bgp_info_reap (struct bgp_node *rn, struct bgp_info *ri) +static void bgp_info_reap(struct bgp_node *rn, struct bgp_info *ri)  { -  if (ri->next) -    ri->next->prev = ri->prev; -  if (ri->prev) -    ri->prev->next = ri->next; -  else -    rn->info = ri->next; -   -  bgp_info_mpath_dequeue (ri); -  bgp_info_unlock (ri); -  bgp_unlock_node (rn); +	if (ri->next) +		ri->next->prev = ri->prev; +	if (ri->prev) +		ri->prev->next = ri->next; +	else +		rn->info = ri->next; + +	bgp_info_mpath_dequeue(ri); +	bgp_info_unlock(ri); +	bgp_unlock_node(rn);  } -void -bgp_info_delete (struct bgp_node *rn, struct bgp_info *ri) +void bgp_info_delete(struct bgp_node *rn, struct bgp_info *ri)  { -  bgp_info_set_flag (rn, ri, BGP_INFO_REMOVED); -  /* set of previous already took care of pcount */ -  UNSET_FLAG (ri->flags, BGP_INFO_VALID); +	bgp_info_set_flag(rn, ri, BGP_INFO_REMOVED); +	/* set of previous already took care of pcount */ +	UNSET_FLAG(ri->flags, BGP_INFO_VALID);  }  /* undo the effects of a previous call to bgp_info_delete; typically     called when a route is deleted and then quickly re-added before the     deletion has been processed */ -void -bgp_info_restore (struct bgp_node *rn, struct bgp_info *ri) +void bgp_info_restore(struct bgp_node *rn, struct bgp_info *ri)  { -  bgp_info_unset_flag (rn, ri, BGP_INFO_REMOVED); -  /* unset of previous already took care of pcount */ -  SET_FLAG (ri->flags, BGP_INFO_VALID); +	bgp_info_unset_flag(rn, ri, BGP_INFO_REMOVED); +	/* unset of previous already took care of pcount */ +	SET_FLAG(ri->flags, BGP_INFO_VALID);  } -/* Adjust pcount as required */    -static void -bgp_pcount_adjust (struct bgp_node *rn, struct bgp_info *ri) +/* Adjust pcount as required */ +static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_info *ri)  { -  struct bgp_table *table; +	struct bgp_table *table; -  assert (rn && bgp_node_table (rn)); -  assert (ri && ri->peer && ri->peer->bgp); +	assert(rn && bgp_node_table(rn)); +	assert(ri && ri->peer && ri->peer->bgp); -  table = bgp_node_table (rn); +	table = bgp_node_table(rn); -  if (ri->peer == ri->peer->bgp->peer_self) -    return; -     -  if (!BGP_INFO_COUNTABLE (ri) -      && CHECK_FLAG (ri->flags, BGP_INFO_COUNTED)) -    { -           -      UNSET_FLAG (ri->flags, BGP_INFO_COUNTED); -       -      /* slight hack, but more robust against errors. */ -      if (ri->peer->pcount[table->afi][table->safi]) -        ri->peer->pcount[table->afi][table->safi]--; -      else -        { -          zlog_warn ("%s: Asked to decrement 0 prefix count for peer %s", -                     __func__, ri->peer->host); -          zlog_backtrace (LOG_WARNING); -          zlog_warn ("%s: Please report to Quagga bugzilla", __func__); -        }       -    } -  else if (BGP_INFO_COUNTABLE (ri) -           && !CHECK_FLAG (ri->flags, BGP_INFO_COUNTED)) -    { -      SET_FLAG (ri->flags, BGP_INFO_COUNTED); -      ri->peer->pcount[table->afi][table->safi]++; -    } +	if (ri->peer == ri->peer->bgp->peer_self) +		return; + +	if (!BGP_INFO_COUNTABLE(ri) +	    && CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) { + +		UNSET_FLAG(ri->flags, BGP_INFO_COUNTED); + +		/* slight hack, but more robust against errors. */ +		if (ri->peer->pcount[table->afi][table->safi]) +			ri->peer->pcount[table->afi][table->safi]--; +		else { +			zlog_warn( +				"%s: Asked to decrement 0 prefix count for peer %s", +				__func__, ri->peer->host); +			zlog_backtrace(LOG_WARNING); +			zlog_warn("%s: Please report to Quagga bugzilla", +				  __func__); +		} +	} else if (BGP_INFO_COUNTABLE(ri) +		   && !CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) { +		SET_FLAG(ri->flags, BGP_INFO_COUNTED); +		ri->peer->pcount[table->afi][table->safi]++; +	}  }  /* Set/unset bgp_info flags, adjusting any other state as needed.   * This is here primarily to keep prefix-count in check.   */ -void -bgp_info_set_flag (struct bgp_node *rn, struct bgp_info *ri, u_int32_t flag) +void bgp_info_set_flag(struct bgp_node *rn, struct bgp_info *ri, u_int32_t flag)  { -  SET_FLAG (ri->flags, flag); -   -  /* early bath if we know it's not a flag that changes countability state */ -  if (!CHECK_FLAG (flag, BGP_INFO_VALID|BGP_INFO_HISTORY|BGP_INFO_REMOVED)) -    return; -   -  bgp_pcount_adjust (rn, ri); +	SET_FLAG(ri->flags, flag); + +	/* early bath if we know it's not a flag that changes countability state +	 */ +	if (!CHECK_FLAG(flag, +			BGP_INFO_VALID | BGP_INFO_HISTORY | BGP_INFO_REMOVED)) +		return; + +	bgp_pcount_adjust(rn, ri);  } -void -bgp_info_unset_flag (struct bgp_node *rn, struct bgp_info *ri, u_int32_t flag) +void bgp_info_unset_flag(struct bgp_node *rn, struct bgp_info *ri, +			 u_int32_t flag)  { -  UNSET_FLAG (ri->flags, flag); -   -  /* early bath if we know it's not a flag that changes countability state */ -  if (!CHECK_FLAG (flag, BGP_INFO_VALID|BGP_INFO_HISTORY|BGP_INFO_REMOVED)) -    return; -   -  bgp_pcount_adjust (rn, ri); +	UNSET_FLAG(ri->flags, flag); + +	/* early bath if we know it's not a flag that changes countability state +	 */ +	if (!CHECK_FLAG(flag, +			BGP_INFO_VALID | BGP_INFO_HISTORY | BGP_INFO_REMOVED)) +		return; + +	bgp_pcount_adjust(rn, ri);  }  /* Get MED value.  If MED value is missing and "bgp bestpath     missing-as-worst" is specified, treat it as the worst value. */ -static u_int32_t -bgp_med_value (struct attr *attr, struct bgp *bgp) -{ -  if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) -    return attr->med; -  else -    { -      if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST)) -	return BGP_MED_MAX; -      else -	return 0; -    } +static u_int32_t bgp_med_value(struct attr *attr, struct bgp *bgp) +{ +	if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) +		return attr->med; +	else { +		if (bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST)) +			return BGP_MED_MAX; +		else +			return 0; +	}  } -void -bgp_info_path_with_addpath_rx_str (struct bgp_info *ri, char *buf) +void bgp_info_path_with_addpath_rx_str(struct bgp_info *ri, char *buf)  { -  if (ri->addpath_rx_id) -    sprintf(buf, "path %s (addpath rxid %d)", ri->peer->host, ri->addpath_rx_id); -  else -    sprintf(buf, "path %s", ri->peer->host); -} - -/* Compare two bgp route entity.  If 'new' is preferable over 'exist' return 1. */ -static int -bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist, -	      int *paths_eq, struct bgp_maxpaths_cfg *mpath_cfg, int debug, -              const char *pfx_buf) -{ -  struct attr *newattr, *existattr; -  struct attr_extra *newattre, *existattre; -  bgp_peer_sort_t new_sort; -  bgp_peer_sort_t exist_sort; -  u_int32_t new_pref; -  u_int32_t exist_pref; -  u_int32_t new_med; -  u_int32_t exist_med; -  u_int32_t new_weight; -  u_int32_t exist_weight; -  uint32_t newm, existm; -  struct in_addr new_id; -  struct in_addr exist_id; -  int new_cluster; -  int exist_cluster; -  int internal_as_route; -  int confed_as_route; -  int ret; -  char new_buf[PATH_ADDPATH_STR_BUFFER]; -  char exist_buf[PATH_ADDPATH_STR_BUFFER]; - -  *paths_eq = 0; - -  /* 0. Null check. */ -  if (new == NULL) -    { -      if (debug) -        zlog_debug("%s: new is NULL", pfx_buf); -      return 0; -    } - -  if (debug) -    bgp_info_path_with_addpath_rx_str (new, new_buf); - -  if (exist == NULL) -    { -      if (debug) -        zlog_debug("%s: %s is the initial bestpath", pfx_buf, new_buf); -      return 1; -    } +	if (ri->addpath_rx_id) +		sprintf(buf, "path %s (addpath rxid %d)", ri->peer->host, +			ri->addpath_rx_id); +	else +		sprintf(buf, "path %s", ri->peer->host); +} -  if (debug) -    { -      bgp_info_path_with_addpath_rx_str (exist, exist_buf); -      zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x", -                 pfx_buf, new_buf, new->flags, exist_buf, exist->flags); -    } +/* Compare two bgp route entity.  If 'new' is preferable over 'exist' return 1. + */ +static int bgp_info_cmp(struct bgp *bgp, struct bgp_info *new, +			struct bgp_info *exist, int *paths_eq, +			struct bgp_maxpaths_cfg *mpath_cfg, int debug, +			const char *pfx_buf) +{ +	struct attr *newattr, *existattr; +	struct attr_extra *newattre, *existattre; +	bgp_peer_sort_t new_sort; +	bgp_peer_sort_t exist_sort; +	u_int32_t new_pref; +	u_int32_t exist_pref; +	u_int32_t new_med; +	u_int32_t exist_med; +	u_int32_t new_weight; +	u_int32_t exist_weight; +	uint32_t newm, existm; +	struct in_addr new_id; +	struct in_addr exist_id; +	int new_cluster; +	int exist_cluster; +	int internal_as_route; +	int confed_as_route; +	int ret; +	char new_buf[PATH_ADDPATH_STR_BUFFER]; +	char exist_buf[PATH_ADDPATH_STR_BUFFER]; + +	*paths_eq = 0; + +	/* 0. Null check. */ +	if (new == NULL) { +		if (debug) +			zlog_debug("%s: new is NULL", pfx_buf); +		return 0; +	} -  newattr = new->attr; -  existattr = exist->attr; -  newattre = newattr->extra; -  existattre = existattr->extra; +	if (debug) +		bgp_info_path_with_addpath_rx_str(new, new_buf); -  /* 1. Weight check. */ -  new_weight = exist_weight = 0; +	if (exist == NULL) { +		if (debug) +			zlog_debug("%s: %s is the initial bestpath", pfx_buf, +				   new_buf); +		return 1; +	} -  if (newattre) -    new_weight = newattre->weight; -  if (existattre) -    exist_weight = existattre->weight; +	if (debug) { +		bgp_info_path_with_addpath_rx_str(exist, exist_buf); +		zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x", +			   pfx_buf, new_buf, new->flags, exist_buf, +			   exist->flags); +	} -  if (new_weight > exist_weight) -    { -      if (debug) -        zlog_debug("%s: %s wins over %s due to weight %d > %d", -                   pfx_buf, new_buf, exist_buf, new_weight, exist_weight); -      return 1; -    } +	newattr = new->attr; +	existattr = exist->attr; +	newattre = newattr->extra; +	existattre = existattr->extra; + +	/* 1. Weight check. */ +	new_weight = exist_weight = 0; + +	if (newattre) +		new_weight = newattre->weight; +	if (existattre) +		exist_weight = existattre->weight; + +	if (new_weight > exist_weight) { +		if (debug) +			zlog_debug("%s: %s wins over %s due to weight %d > %d", +				   pfx_buf, new_buf, exist_buf, new_weight, +				   exist_weight); +		return 1; +	} -  if (new_weight < exist_weight) -    { -      if (debug) -        zlog_debug("%s: %s loses to %s due to weight %d < %d", -                   pfx_buf, new_buf, exist_buf, new_weight, exist_weight); -      return 0; -    } +	if (new_weight < exist_weight) { +		if (debug) +			zlog_debug("%s: %s loses to %s due to weight %d < %d", +				   pfx_buf, new_buf, exist_buf, new_weight, +				   exist_weight); +		return 0; +	} -  /* 2. Local preference check. */ -  new_pref = exist_pref = bgp->default_local_pref; +	/* 2. Local preference check. */ +	new_pref = exist_pref = bgp->default_local_pref; + +	if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) +		new_pref = newattr->local_pref; +	if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) +		exist_pref = existattr->local_pref; + +	if (new_pref > exist_pref) { +		if (debug) +			zlog_debug( +				"%s: %s wins over %s due to localpref %d > %d", +				pfx_buf, new_buf, exist_buf, new_pref, +				exist_pref); +		return 1; +	} -  if (newattr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) -    new_pref = newattr->local_pref; -  if (existattr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) -    exist_pref = existattr->local_pref; +	if (new_pref < exist_pref) { +		if (debug) +			zlog_debug( +				"%s: %s loses to %s due to localpref %d < %d", +				pfx_buf, new_buf, exist_buf, new_pref, +				exist_pref); +		return 0; +	} -  if (new_pref > exist_pref) -    { -      if (debug) -        zlog_debug("%s: %s wins over %s due to localpref %d > %d", -                   pfx_buf, new_buf, exist_buf, new_pref, exist_pref); -      return 1; -    } +	/* 3. Local route check. We prefer: +	 *  - BGP_ROUTE_STATIC +	 *  - BGP_ROUTE_AGGREGATE +	 *  - BGP_ROUTE_REDISTRIBUTE +	 */ +	if (!(new->sub_type == BGP_ROUTE_NORMAL)) { +		if (debug) +			zlog_debug( +				"%s: %s wins over %s due to preferred BGP_ROUTE type", +				pfx_buf, new_buf, exist_buf); +		return 1; +	} -  if (new_pref < exist_pref) -    { -      if (debug) -        zlog_debug("%s: %s loses to %s due to localpref %d < %d", -                   pfx_buf, new_buf, exist_buf, new_pref, exist_pref); -      return 0; -    } +	if (!(exist->sub_type == BGP_ROUTE_NORMAL)) { +		if (debug) +			zlog_debug( +				"%s: %s loses to %s due to preferred BGP_ROUTE type", +				pfx_buf, new_buf, exist_buf); +		return 0; +	} -  /* 3. Local route check. We prefer: -   *  - BGP_ROUTE_STATIC -   *  - BGP_ROUTE_AGGREGATE -   *  - BGP_ROUTE_REDISTRIBUTE -   */ -  if (! (new->sub_type == BGP_ROUTE_NORMAL)) -    { -      if (debug) -        zlog_debug("%s: %s wins over %s due to preferred BGP_ROUTE type", -                   pfx_buf, new_buf, exist_buf); -      return 1; -    } +	/* 4. AS path length check. */ +	if (!bgp_flag_check(bgp, BGP_FLAG_ASPATH_IGNORE)) { +		int exist_hops = aspath_count_hops(existattr->aspath); +		int exist_confeds = aspath_count_confeds(existattr->aspath); + +		if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_CONFED)) { +			int aspath_hops; + +			aspath_hops = aspath_count_hops(newattr->aspath); +			aspath_hops += aspath_count_confeds(newattr->aspath); + +			if (aspath_hops < (exist_hops + exist_confeds)) { +				if (debug) +					zlog_debug( +						"%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d", +						pfx_buf, new_buf, exist_buf, +						aspath_hops, +						(exist_hops + exist_confeds)); +				return 1; +			} + +			if (aspath_hops > (exist_hops + exist_confeds)) { +				if (debug) +					zlog_debug( +						"%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d", +						pfx_buf, new_buf, exist_buf, +						aspath_hops, +						(exist_hops + exist_confeds)); +				return 0; +			} +		} else { +			int newhops = aspath_count_hops(newattr->aspath); + +			if (newhops < exist_hops) { +				if (debug) +					zlog_debug( +						"%s: %s wins over %s due to aspath hopcount %d < %d", +						pfx_buf, new_buf, exist_buf, +						newhops, exist_hops); +				return 1; +			} + +			if (newhops > exist_hops) { +				if (debug) +					zlog_debug( +						"%s: %s loses to %s due to aspath hopcount %d > %d", +						pfx_buf, new_buf, exist_buf, +						newhops, exist_hops); +				return 0; +			} +		} +	} -  if (! (exist->sub_type == BGP_ROUTE_NORMAL)) -    { -      if (debug) -        zlog_debug("%s: %s loses to %s due to preferred BGP_ROUTE type", -                   pfx_buf, new_buf, exist_buf); -      return 0; -    } +	/* 5. Origin check. */ +	if (newattr->origin < existattr->origin) { +		if (debug) +			zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s", +				   pfx_buf, new_buf, exist_buf, +				   bgp_origin_long_str[newattr->origin], +				   bgp_origin_long_str[existattr->origin]); +		return 1; +	} -  /* 4. AS path length check. */ -  if (! bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE)) -    { -      int exist_hops = aspath_count_hops (existattr->aspath); -      int exist_confeds = aspath_count_confeds (existattr->aspath); -       -      if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED)) -	{ -	  int aspath_hops; -	   -	  aspath_hops = aspath_count_hops (newattr->aspath); -          aspath_hops += aspath_count_confeds (newattr->aspath); -           -	  if ( aspath_hops < (exist_hops + exist_confeds)) -            { -              if (debug) -                zlog_debug("%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d", -                           pfx_buf, new_buf, exist_buf, -                           aspath_hops, (exist_hops + exist_confeds)); -	      return 1; -            } - -	  if ( aspath_hops > (exist_hops + exist_confeds)) -            { -              if (debug) -                zlog_debug("%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d", -                           pfx_buf, new_buf, exist_buf, -                           aspath_hops, (exist_hops + exist_confeds)); -	      return 0; -            } -	} -      else -	{ -	  int newhops = aspath_count_hops (newattr->aspath); -	   -	  if (newhops < exist_hops) -            { -              if (debug) -                zlog_debug("%s: %s wins over %s due to aspath hopcount %d < %d", -                           pfx_buf, new_buf, exist_buf, newhops, exist_hops); -	      return 1; -            } - -          if (newhops > exist_hops) -            { -              if (debug) -                zlog_debug("%s: %s loses to %s due to aspath hopcount %d > %d", -                           pfx_buf, new_buf, exist_buf, newhops, exist_hops); -	      return 0; -            } +	if (newattr->origin > existattr->origin) { +		if (debug) +			zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s", +				   pfx_buf, new_buf, exist_buf, +				   bgp_origin_long_str[newattr->origin], +				   bgp_origin_long_str[existattr->origin]); +		return 0;  	} -    } -  /* 5. Origin check. */ -  if (newattr->origin < existattr->origin) -    { -      if (debug) -        zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s", -                   pfx_buf, new_buf, exist_buf, -                   bgp_origin_long_str[newattr->origin], -                   bgp_origin_long_str[existattr->origin]); -      return 1; -    } +	/* 6. MED check. */ +	internal_as_route = (aspath_count_hops(newattr->aspath) == 0 +			     && aspath_count_hops(existattr->aspath) == 0); +	confed_as_route = (aspath_count_confeds(newattr->aspath) > 0 +			   && aspath_count_confeds(existattr->aspath) > 0 +			   && aspath_count_hops(newattr->aspath) == 0 +			   && aspath_count_hops(existattr->aspath) == 0); + +	if (bgp_flag_check(bgp, BGP_FLAG_ALWAYS_COMPARE_MED) +	    || (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED) && confed_as_route) +	    || aspath_cmp_left(newattr->aspath, existattr->aspath) +	    || aspath_cmp_left_confed(newattr->aspath, existattr->aspath) +	    || internal_as_route) { +		new_med = bgp_med_value(new->attr, bgp); +		exist_med = bgp_med_value(exist->attr, bgp); + +		if (new_med < exist_med) { +			if (debug) +				zlog_debug( +					"%s: %s wins over %s due to MED %d < %d", +					pfx_buf, new_buf, exist_buf, new_med, +					exist_med); +			return 1; +		} -  if (newattr->origin > existattr->origin) -    { -      if (debug) -        zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s", -                   pfx_buf, new_buf, exist_buf, -                   bgp_origin_long_str[newattr->origin], -                   bgp_origin_long_str[existattr->origin]); -      return 0; -    } +		if (new_med > exist_med) { +			if (debug) +				zlog_debug( +					"%s: %s loses to %s due to MED %d > %d", +					pfx_buf, new_buf, exist_buf, new_med, +					exist_med); +			return 0; +		} +	} -  /* 6. MED check. */ -  internal_as_route = (aspath_count_hops (newattr->aspath) == 0 -		      && aspath_count_hops (existattr->aspath) == 0); -  confed_as_route = (aspath_count_confeds (newattr->aspath) > 0 -		    && aspath_count_confeds (existattr->aspath) > 0 -		    && aspath_count_hops (newattr->aspath) == 0 -		    && aspath_count_hops (existattr->aspath) == 0); -   -  if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED) -      || (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED) -	 && confed_as_route) -      || aspath_cmp_left (newattr->aspath, existattr->aspath) -      || aspath_cmp_left_confed (newattr->aspath, existattr->aspath) -      || internal_as_route) -    { -      new_med = bgp_med_value (new->attr, bgp); -      exist_med = bgp_med_value (exist->attr, bgp); - -      if (new_med < exist_med) -        { -          if (debug) -            zlog_debug("%s: %s wins over %s due to MED %d < %d", -                       pfx_buf, new_buf, exist_buf, new_med, exist_med); -	  return 1; -        } - -      if (new_med > exist_med) -        { -          if (debug) -            zlog_debug("%s: %s loses to %s due to MED %d > %d", -                       pfx_buf, new_buf, exist_buf, new_med, exist_med); -	  return 0; -        } -    } +	/* 7. Peer type check. */ +	new_sort = new->peer->sort; +	exist_sort = exist->peer->sort; + +	if (new_sort == BGP_PEER_EBGP +	    && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) { +		if (debug) +			zlog_debug( +				"%s: %s wins over %s due to eBGP peer > iBGP peer", +				pfx_buf, new_buf, exist_buf); +		return 1; +	} -  /* 7. Peer type check. */ -  new_sort = new->peer->sort; -  exist_sort = exist->peer->sort; +	if (exist_sort == BGP_PEER_EBGP +	    && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) { +		if (debug) +			zlog_debug( +				"%s: %s loses to %s due to iBGP peer < eBGP peer", +				pfx_buf, new_buf, exist_buf); +		return 0; +	} -  if (new_sort == BGP_PEER_EBGP -      && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) -    { -      if (debug) -        zlog_debug("%s: %s wins over %s due to eBGP peer > iBGP peer", -                   pfx_buf, new_buf, exist_buf); -      return 1; -    } +	/* 8. IGP metric check. */ +	newm = existm = 0; -  if (exist_sort == BGP_PEER_EBGP -      && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) -    { -      if (debug) -        zlog_debug("%s: %s loses to %s due to iBGP peer < eBGP peer", -                   pfx_buf, new_buf, exist_buf); -      return 0; -    } +	if (new->extra) +		newm = new->extra->igpmetric; +	if (exist->extra) +		existm = exist->extra->igpmetric; -  /* 8. IGP metric check. */ -  newm = existm = 0; +	if (newm < existm) { +		if (debug) +			zlog_debug( +				"%s: %s wins over %s due to IGP metric %d < %d", +				pfx_buf, new_buf, exist_buf, newm, existm); +		ret = 1; +	} -  if (new->extra) -    newm = new->extra->igpmetric; -  if (exist->extra) -    existm = exist->extra->igpmetric; +	if (newm > existm) { +		if (debug) +			zlog_debug( +				"%s: %s loses to %s due to IGP metric %d > %d", +				pfx_buf, new_buf, exist_buf, newm, existm); +		ret = 0; +	} -  if (newm < existm) -    { -      if (debug) -        zlog_debug("%s: %s wins over %s due to IGP metric %d < %d", -                   pfx_buf, new_buf, exist_buf, newm, existm); -      ret = 1; -    } +	/* 9. Same IGP metric. Compare the cluster list length as +	   representative of IGP hops metric. Rewrite the metric value +	   pair (newm, existm) with the cluster list length. Prefer the +	   path with smaller cluster list length.                       */ +	if (newm == existm) { +		if (peer_sort(new->peer) == BGP_PEER_IBGP +		    && peer_sort(exist->peer) == BGP_PEER_IBGP +		    && (mpath_cfg == NULL +			|| CHECK_FLAG( +				   mpath_cfg->ibgp_flags, +				   BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) { +			newm = BGP_CLUSTER_LIST_LENGTH(new->attr); +			existm = BGP_CLUSTER_LIST_LENGTH(exist->attr); + +			if (newm < existm) { +				if (debug) +					zlog_debug( +						"%s: %s wins over %s due to CLUSTER_LIST length %d < %d", +						pfx_buf, new_buf, exist_buf, +						newm, existm); +				ret = 1; +			} + +			if (newm > existm) { +				if (debug) +					zlog_debug( +						"%s: %s loses to %s due to CLUSTER_LIST length %d > %d", +						pfx_buf, new_buf, exist_buf, +						newm, existm); +				ret = 0; +			} +		} +	} -  if (newm > existm) -    { -      if (debug) -        zlog_debug("%s: %s loses to %s due to IGP metric %d > %d", -                   pfx_buf, new_buf, exist_buf, newm, existm); -      ret = 0; -    } +	/* 10. confed-external vs. confed-internal */ +	if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) { +		if (new_sort == BGP_PEER_CONFED +		    && exist_sort == BGP_PEER_IBGP) { +			if (debug) +				zlog_debug( +					"%s: %s wins over %s due to confed-external peer > confed-internal peer", +					pfx_buf, new_buf, exist_buf); +			return 1; +		} -  /* 9. Same IGP metric. Compare the cluster list length as -     representative of IGP hops metric. Rewrite the metric value -     pair (newm, existm) with the cluster list length. Prefer the -     path with smaller cluster list length.                       */ -  if (newm == existm) -    { -      if (peer_sort (new->peer) == BGP_PEER_IBGP -	  && peer_sort (exist->peer) == BGP_PEER_IBGP -	  && (mpath_cfg == NULL || -              CHECK_FLAG (mpath_cfg->ibgp_flags, -                          BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) -	{ -	  newm = BGP_CLUSTER_LIST_LENGTH(new->attr); -	  existm = BGP_CLUSTER_LIST_LENGTH(exist->attr); - -	  if (newm < existm) -            { -              if (debug) -                zlog_debug("%s: %s wins over %s due to CLUSTER_LIST length %d < %d", -                           pfx_buf, new_buf, exist_buf, newm, existm); -	      ret = 1; -            } - -	  if (newm > existm) -            { -              if (debug) -                zlog_debug("%s: %s loses to %s due to CLUSTER_LIST length %d > %d", -                           pfx_buf, new_buf, exist_buf, newm, existm); -	      ret = 0; -            } +		if (exist_sort == BGP_PEER_CONFED +		    && new_sort == BGP_PEER_IBGP) { +			if (debug) +				zlog_debug( +					"%s: %s loses to %s due to confed-internal peer < confed-external peer", +					pfx_buf, new_buf, exist_buf); +			return 0; +		}  	} -    } -  /* 10. confed-external vs. confed-internal */ -  if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) -    { -      if (new_sort == BGP_PEER_CONFED && exist_sort == BGP_PEER_IBGP) -        { -          if (debug) -            zlog_debug("%s: %s wins over %s due to confed-external peer > confed-internal peer", -                       pfx_buf, new_buf, exist_buf); -          return 1; -        } - -      if (exist_sort == BGP_PEER_CONFED && new_sort == BGP_PEER_IBGP) -        { -          if (debug) -            zlog_debug("%s: %s loses to %s due to confed-internal peer < confed-external peer", -                       pfx_buf, new_buf, exist_buf); -          return 0; -        } -    } - -  /* 11. Maximum path check. */ -  if (newm == existm) -    { -      if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) -        { - -	  /* -	   * For the two paths, all comparison steps till IGP metric -	   * have succeeded - including AS_PATH hop count. Since 'bgp -	   * bestpath as-path multipath-relax' knob is on, we don't need -	   * an exact match of AS_PATH. Thus, mark the paths are equal. -	   * That will trigger both these paths to get into the multipath -	   * array. -	   */ -	  *paths_eq = 1; - -          if (debug) -            zlog_debug("%s: %s and %s are equal via multipath-relax", -                       pfx_buf, new_buf, exist_buf); -        } -      else if (new->peer->sort == BGP_PEER_IBGP) -	{ -	  if (aspath_cmp (new->attr->aspath, exist->attr->aspath)) -            { -	      *paths_eq = 1; - -              if (debug) -                zlog_debug("%s: %s and %s are equal via matching aspaths", -                           pfx_buf, new_buf, exist_buf); -            } -	} -      else if (new->peer->as == exist->peer->as) -        { -	  *paths_eq = 1; - -          if (debug) -            zlog_debug("%s: %s and %s are equal via same remote-as", -                       pfx_buf, new_buf, exist_buf); -        } -    } -  else -    { -      /* -       * TODO: If unequal cost ibgp multipath is enabled we can -       * mark the paths as equal here instead of returning -       */ -      if (debug) -        { -          if (ret == 1) -            zlog_debug("%s: %s wins over %s after IGP metric comparison", -                       pfx_buf, new_buf, exist_buf); -          else -            zlog_debug("%s: %s loses to %s after IGP metric comparison", -                       pfx_buf, new_buf, exist_buf); -        } -      return ret; -    } +	/* 11. Maximum path check. */ +	if (newm == existm) { +		if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) { + +			/* +			 * For the two paths, all comparison steps till IGP +			 * metric +			 * have succeeded - including AS_PATH hop count. Since +			 * 'bgp +			 * bestpath as-path multipath-relax' knob is on, we +			 * don't need +			 * an exact match of AS_PATH. Thus, mark the paths are +			 * equal. +			 * That will trigger both these paths to get into the +			 * multipath +			 * array. +			 */ +			*paths_eq = 1; + +			if (debug) +				zlog_debug( +					"%s: %s and %s are equal via multipath-relax", +					pfx_buf, new_buf, exist_buf); +		} else if (new->peer->sort == BGP_PEER_IBGP) { +			if (aspath_cmp(new->attr->aspath, +				       exist->attr->aspath)) { +				*paths_eq = 1; + +				if (debug) +					zlog_debug( +						"%s: %s and %s are equal via matching aspaths", +						pfx_buf, new_buf, exist_buf); +			} +		} else if (new->peer->as == exist->peer->as) { +			*paths_eq = 1; + +			if (debug) +				zlog_debug( +					"%s: %s and %s are equal via same remote-as", +					pfx_buf, new_buf, exist_buf); +		} +	} else { +		/* +		 * TODO: If unequal cost ibgp multipath is enabled we can +		 * mark the paths as equal here instead of returning +		 */ +		if (debug) { +			if (ret == 1) +				zlog_debug( +					"%s: %s wins over %s after IGP metric comparison", +					pfx_buf, new_buf, exist_buf); +			else +				zlog_debug( +					"%s: %s loses to %s after IGP metric comparison", +					pfx_buf, new_buf, exist_buf); +		} +		return ret; +	} -  /* 12. If both paths are external, prefer the path that was received -     first (the oldest one).  This step minimizes route-flap, since a -     newer path won't displace an older one, even if it was the -     preferred route based on the additional decision criteria below.  */ -  if (! bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID) -      && new_sort == BGP_PEER_EBGP -      && exist_sort == BGP_PEER_EBGP) -    { -      if (CHECK_FLAG (new->flags, BGP_INFO_SELECTED)) -        { -          if (debug) -              zlog_debug("%s: %s wins over %s due to oldest external", -                         pfx_buf, new_buf, exist_buf); -	  return 1; -        } - -      if (CHECK_FLAG (exist->flags, BGP_INFO_SELECTED)) -        { -          if (debug) -              zlog_debug("%s: %s loses to %s due to oldest external", -                         pfx_buf, new_buf, exist_buf); -	  return 0; -        } -    } +	/* 12. If both paths are external, prefer the path that was received +	   first (the oldest one).  This step minimizes route-flap, since a +	   newer path won't displace an older one, even if it was the +	   preferred route based on the additional decision criteria below.  */ +	if (!bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID) +	    && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) { +		if (CHECK_FLAG(new->flags, BGP_INFO_SELECTED)) { +			if (debug) +				zlog_debug( +					"%s: %s wins over %s due to oldest external", +					pfx_buf, new_buf, exist_buf); +			return 1; +		} -  /* 13. Router-ID comparision. */ -  /* If one of the paths is "stale", the corresponding peer router-id will -   * be 0 and would always win over the other path. If originator id is -   * used for the comparision, it will decide which path is better. -   */ -  if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) -    new_id.s_addr = newattre->originator_id.s_addr; -  else -    new_id.s_addr = new->peer->remote_id.s_addr; -  if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) -    exist_id.s_addr = existattre->originator_id.s_addr; -  else -    exist_id.s_addr = exist->peer->remote_id.s_addr; +		if (CHECK_FLAG(exist->flags, BGP_INFO_SELECTED)) { +			if (debug) +				zlog_debug( +					"%s: %s loses to %s due to oldest external", +					pfx_buf, new_buf, exist_buf); +			return 0; +		} +	} -  if (ntohl (new_id.s_addr) < ntohl (exist_id.s_addr)) -    { -      if (debug) -        zlog_debug("%s: %s wins over %s due to Router-ID comparison", -                   pfx_buf, new_buf, exist_buf); -      return 1; -    } +	/* 13. Router-ID comparision. */ +	/* If one of the paths is "stale", the corresponding peer router-id will +	 * be 0 and would always win over the other path. If originator id is +	 * used for the comparision, it will decide which path is better. +	 */ +	if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) +		new_id.s_addr = newattre->originator_id.s_addr; +	else +		new_id.s_addr = new->peer->remote_id.s_addr; +	if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) +		exist_id.s_addr = existattre->originator_id.s_addr; +	else +		exist_id.s_addr = exist->peer->remote_id.s_addr; + +	if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) { +		if (debug) +			zlog_debug( +				"%s: %s wins over %s due to Router-ID comparison", +				pfx_buf, new_buf, exist_buf); +		return 1; +	} -  if (ntohl (new_id.s_addr) > ntohl (exist_id.s_addr)) -    { -      if (debug) -        zlog_debug("%s: %s loses to %s due to Router-ID comparison", -                   pfx_buf, new_buf, exist_buf); -      return 0; -    } +	if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) { +		if (debug) +			zlog_debug( +				"%s: %s loses to %s due to Router-ID comparison", +				pfx_buf, new_buf, exist_buf); +		return 0; +	} -  /* 14. Cluster length comparision. */ -  new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr); -  exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr); +	/* 14. Cluster length comparision. */ +	new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr); +	exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr); + +	if (new_cluster < exist_cluster) { +		if (debug) +			zlog_debug( +				"%s: %s wins over %s due to CLUSTER_LIST length %d < %d", +				pfx_buf, new_buf, exist_buf, new_cluster, +				exist_cluster); +		return 1; +	} -  if (new_cluster < exist_cluster) -    { -      if (debug) -        zlog_debug("%s: %s wins over %s due to CLUSTER_LIST length %d < %d", -                   pfx_buf, new_buf, exist_buf, new_cluster, exist_cluster); -      return 1; -    } +	if (new_cluster > exist_cluster) { +		if (debug) +			zlog_debug( +				"%s: %s loses to %s due to CLUSTER_LIST length %d > %d", +				pfx_buf, new_buf, exist_buf, new_cluster, +				exist_cluster); +		return 0; +	} -  if (new_cluster > exist_cluster) -    { -      if (debug) -        zlog_debug("%s: %s loses to %s due to CLUSTER_LIST length %d > %d", -                   pfx_buf, new_buf, exist_buf, new_cluster, exist_cluster); -      return 0; -    } +	/* 15. Neighbor address comparision. */ +	/* Do this only if neither path is "stale" as stale paths do not have +	 * valid peer information (as the connection may or may not be up). +	 */ +	if (CHECK_FLAG(exist->flags, BGP_INFO_STALE)) { +		if (debug) +			zlog_debug( +				"%s: %s wins over %s due to latter path being STALE", +				pfx_buf, new_buf, exist_buf); +		return 1; +	} -  /* 15. Neighbor address comparision. */ -  /* Do this only if neither path is "stale" as stale paths do not have -   * valid peer information (as the connection may or may not be up). -   */ -  if (CHECK_FLAG (exist->flags, BGP_INFO_STALE)) -    { -      if (debug) -        zlog_debug("%s: %s wins over %s due to latter path being STALE", -                   pfx_buf, new_buf, exist_buf); -      return 1; -    } +	if (CHECK_FLAG(new->flags, BGP_INFO_STALE)) { +		if (debug) +			zlog_debug( +				"%s: %s loses to %s due to former path being STALE", +				pfx_buf, new_buf, exist_buf); +		return 0; +	} -  if (CHECK_FLAG (new->flags, BGP_INFO_STALE)) -    { -      if (debug) -        zlog_debug("%s: %s loses to %s due to former path being STALE", -                   pfx_buf, new_buf, exist_buf); -      return 0; -    } +	/* locally configured routes to advertise do not have su_remote */ +	if (new->peer->su_remote == NULL) +		return 0; +	if (exist->peer->su_remote == NULL) +		return 1; -  /* locally configured routes to advertise do not have su_remote */ -  if (new->peer->su_remote == NULL) -    return 0; -  if (exist->peer->su_remote == NULL) -    return 1; -   -  ret = sockunion_cmp (new->peer->su_remote, exist->peer->su_remote); +	ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote); -  if (ret == 1) -    { -      if (debug) -        zlog_debug("%s: %s loses to %s due to Neighor IP comparison", -                   pfx_buf, new_buf, exist_buf); -      return 0; -    } +	if (ret == 1) { +		if (debug) +			zlog_debug( +				"%s: %s loses to %s due to Neighor IP comparison", +				pfx_buf, new_buf, exist_buf); +		return 0; +	} -  if (ret == -1) -    { -      if (debug) -        zlog_debug("%s: %s wins over %s due to Neighor IP comparison", -                   pfx_buf, new_buf, exist_buf); -      return 1; -    } +	if (ret == -1) { +		if (debug) +			zlog_debug( +				"%s: %s wins over %s due to Neighor IP comparison", +				pfx_buf, new_buf, exist_buf); +		return 1; +	} -  if (debug) -    zlog_debug("%s: %s wins over %s due to nothing left to compare", -               pfx_buf, new_buf, exist_buf); +	if (debug) +		zlog_debug("%s: %s wins over %s due to nothing left to compare", +			   pfx_buf, new_buf, exist_buf); -  return 1; +	return 1;  }  /* Compare two bgp route entity.  Return -1 if new is preferred, 1 if exist   * is preferred, or 0 if they are the same (usually will only occur if - * multipath is enabled  + * multipath is enabled   * This version is compatible with */ -int -bgp_info_cmp_compatible (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist, -                         afi_t afi, safi_t safi) -{ -  int paths_eq; -  int ret; -  ret = bgp_info_cmp (bgp, new, exist, &paths_eq, NULL, 0, __func__); - -  if (paths_eq) -    ret = 0; -  else  -    { -      if (ret == 1) -        ret = -1; -      else  -        ret = 1; -    } -  return ret; +int bgp_info_cmp_compatible(struct bgp *bgp, struct bgp_info *new, +			    struct bgp_info *exist, afi_t afi, safi_t safi) +{ +	int paths_eq; +	int ret; +	ret = bgp_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, __func__); + +	if (paths_eq) +		ret = 0; +	else { +		if (ret == 1) +			ret = -1; +		else +			ret = 1; +	} +	return ret;  } -static enum filter_type -bgp_input_filter (struct peer *peer, struct prefix *p, struct attr *attr, -		  afi_t afi, safi_t safi) +static enum filter_type bgp_input_filter(struct peer *peer, struct prefix *p, +					 struct attr *attr, afi_t afi, +					 safi_t safi)  { -  struct bgp_filter *filter; +	struct bgp_filter *filter; -  filter = &peer->filter[afi][safi]; +	filter = &peer->filter[afi][safi]; -#define FILTER_EXIST_WARN(F,f,filter) \ -  if (BGP_DEBUG (update, UPDATE_IN) \ -      && !(F ## _IN (filter))) \ -    zlog_warn ("%s: Could not find configured input %s-list %s!", \ -               peer->host, #f, F ## _IN_NAME(filter)); -   -  if (DISTRIBUTE_IN_NAME (filter)) { -    FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter); -       -    if (access_list_apply (DISTRIBUTE_IN (filter), p) == FILTER_DENY) -      return FILTER_DENY; -  } - -  if (PREFIX_LIST_IN_NAME (filter)) { -    FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter); -     -    if (prefix_list_apply (PREFIX_LIST_IN (filter), p) == PREFIX_DENY) -      return FILTER_DENY; -  } -   -  if (FILTER_LIST_IN_NAME (filter)) { -    FILTER_EXIST_WARN(FILTER_LIST, as, filter); -     -    if (as_list_apply (FILTER_LIST_IN (filter), attr->aspath)== AS_FILTER_DENY) -      return FILTER_DENY; -  } -   -  return FILTER_PERMIT; +#define FILTER_EXIST_WARN(F, f, filter)                                        \ +	if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter)))                 \ +		zlog_warn("%s: Could not find configured input %s-list %s!",   \ +			  peer->host, #f, F##_IN_NAME(filter)); + +	if (DISTRIBUTE_IN_NAME(filter)) { +		FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter); + +		if (access_list_apply(DISTRIBUTE_IN(filter), p) == FILTER_DENY) +			return FILTER_DENY; +	} + +	if (PREFIX_LIST_IN_NAME(filter)) { +		FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter); + +		if (prefix_list_apply(PREFIX_LIST_IN(filter), p) == PREFIX_DENY) +			return FILTER_DENY; +	} + +	if (FILTER_LIST_IN_NAME(filter)) { +		FILTER_EXIST_WARN(FILTER_LIST, as, filter); + +		if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath) +		    == AS_FILTER_DENY) +			return FILTER_DENY; +	} + +	return FILTER_PERMIT;  #undef FILTER_EXIST_WARN  } -static enum filter_type -bgp_output_filter (struct peer *peer, struct prefix *p, struct attr *attr, -		   afi_t afi, safi_t safi) +static enum filter_type bgp_output_filter(struct peer *peer, struct prefix *p, +					  struct attr *attr, afi_t afi, +					  safi_t safi)  { -  struct bgp_filter *filter; +	struct bgp_filter *filter; -  filter = &peer->filter[afi][safi]; +	filter = &peer->filter[afi][safi]; -#define FILTER_EXIST_WARN(F,f,filter) \ -  if (BGP_DEBUG (update, UPDATE_OUT) \ -      && !(F ## _OUT (filter))) \ -    zlog_warn ("%s: Could not find configured output %s-list %s!", \ -               peer->host, #f, F ## _OUT_NAME(filter)); +#define FILTER_EXIST_WARN(F, f, filter)                                        \ +	if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter)))               \ +		zlog_warn("%s: Could not find configured output %s-list %s!",  \ +			  peer->host, #f, F##_OUT_NAME(filter)); -  if (DISTRIBUTE_OUT_NAME (filter)) { -    FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter); -     -    if (access_list_apply (DISTRIBUTE_OUT (filter), p) == FILTER_DENY) -      return FILTER_DENY; -  } +	if (DISTRIBUTE_OUT_NAME(filter)) { +		FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter); -  if (PREFIX_LIST_OUT_NAME (filter)) { -    FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter); -     -    if (prefix_list_apply (PREFIX_LIST_OUT (filter), p) == PREFIX_DENY) -      return FILTER_DENY; -  } +		if (access_list_apply(DISTRIBUTE_OUT(filter), p) == FILTER_DENY) +			return FILTER_DENY; +	} + +	if (PREFIX_LIST_OUT_NAME(filter)) { +		FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter); -  if (FILTER_LIST_OUT_NAME (filter)) { -    FILTER_EXIST_WARN(FILTER_LIST, as, filter); -     -    if (as_list_apply (FILTER_LIST_OUT (filter), attr->aspath) == AS_FILTER_DENY) -      return FILTER_DENY; -  } +		if (prefix_list_apply(PREFIX_LIST_OUT(filter), p) +		    == PREFIX_DENY) +			return FILTER_DENY; +	} -  return FILTER_PERMIT; +	if (FILTER_LIST_OUT_NAME(filter)) { +		FILTER_EXIST_WARN(FILTER_LIST, as, filter); + +		if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath) +		    == AS_FILTER_DENY) +			return FILTER_DENY; +	} + +	return FILTER_PERMIT;  #undef FILTER_EXIST_WARN  }  /* If community attribute includes no_export then return 1. */ -static int -bgp_community_filter (struct peer *peer, struct attr *attr) -{ -  if (attr->community) -    { -      /* NO_ADVERTISE check. */ -      if (community_include (attr->community, COMMUNITY_NO_ADVERTISE)) -	return 1; - -      /* NO_EXPORT check. */ -      if (peer->sort == BGP_PEER_EBGP && -	  community_include (attr->community, COMMUNITY_NO_EXPORT)) -	return 1; - -      /* NO_EXPORT_SUBCONFED check. */ -      if (peer->sort == BGP_PEER_EBGP -	  || peer->sort == BGP_PEER_CONFED) -	if (community_include (attr->community, COMMUNITY_NO_EXPORT_SUBCONFED)) -	  return 1; -    } -  return 0; +static int bgp_community_filter(struct peer *peer, struct attr *attr) +{ +	if (attr->community) { +		/* NO_ADVERTISE check. */ +		if (community_include(attr->community, COMMUNITY_NO_ADVERTISE)) +			return 1; + +		/* NO_EXPORT check. */ +		if (peer->sort == BGP_PEER_EBGP +		    && community_include(attr->community, COMMUNITY_NO_EXPORT)) +			return 1; + +		/* NO_EXPORT_SUBCONFED check. */ +		if (peer->sort == BGP_PEER_EBGP +		    || peer->sort == BGP_PEER_CONFED) +			if (community_include(attr->community, +					      COMMUNITY_NO_EXPORT_SUBCONFED)) +				return 1; +	} +	return 0;  }  /* Route reflection loop check.  */ -static int -bgp_cluster_filter (struct peer *peer, struct attr *attr) +static int bgp_cluster_filter(struct peer *peer, struct attr *attr)  { -  struct in_addr cluster_id; +	struct in_addr cluster_id; -  if (attr->extra && attr->extra->cluster) -    { -      if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID) -	cluster_id = peer->bgp->cluster_id; -      else -	cluster_id = peer->bgp->router_id; -       -      if (cluster_loop_check (attr->extra->cluster, cluster_id)) -	return 1; -    } -  return 0; +	if (attr->extra && attr->extra->cluster) { +		if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID) +			cluster_id = peer->bgp->cluster_id; +		else +			cluster_id = peer->bgp->router_id; + +		if (cluster_loop_check(attr->extra->cluster, cluster_id)) +			return 1; +	} +	return 0;  } -static int -bgp_input_modifier (struct peer *peer, struct prefix *p, struct attr *attr, -		    afi_t afi, safi_t safi, const char *rmap_name) +static int bgp_input_modifier(struct peer *peer, struct prefix *p, +			      struct attr *attr, afi_t afi, safi_t safi, +			      const char *rmap_name)  { -  struct bgp_filter *filter; -  struct bgp_info info; -  route_map_result_t ret; -  struct route_map *rmap = NULL; +	struct bgp_filter *filter; +	struct bgp_info info; +	route_map_result_t ret; +	struct route_map *rmap = NULL; -  filter = &peer->filter[afi][safi]; +	filter = &peer->filter[afi][safi]; -  /* Apply default weight value. */ -  if (peer->weight[afi][safi]) -    (bgp_attr_extra_get (attr))->weight = peer->weight[afi][safi]; +	/* Apply default weight value. */ +	if (peer->weight[afi][safi]) +		(bgp_attr_extra_get(attr))->weight = peer->weight[afi][safi]; -  if (rmap_name) -    { -      rmap = route_map_lookup_by_name(rmap_name); +	if (rmap_name) { +		rmap = route_map_lookup_by_name(rmap_name); -      if (rmap == NULL) -	    return RMAP_DENY; -    } -  else -    { -      if (ROUTE_MAP_IN_NAME(filter)) -        { -          rmap = ROUTE_MAP_IN (filter); +		if (rmap == NULL) +			return RMAP_DENY; +	} else { +		if (ROUTE_MAP_IN_NAME(filter)) { +			rmap = ROUTE_MAP_IN(filter); -          if (rmap == NULL) -	        return RMAP_DENY; -        } -    } +			if (rmap == NULL) +				return RMAP_DENY; +		} +	} -  /* Route map apply. */ -  if (rmap) -    { -      /* Duplicate current value to new strucutre for modification. */ -      info.peer = peer; -      info.attr = attr; +	/* Route map apply. */ +	if (rmap) { +		/* Duplicate current value to new strucutre for modification. */ +		info.peer = peer; +		info.attr = attr; -      SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN);  +		SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN); -      /* Apply BGP route map to the attribute. */ -      ret = route_map_apply (rmap, p, RMAP_BGP, &info); +		/* Apply BGP route map to the attribute. */ +		ret = route_map_apply(rmap, p, RMAP_BGP, &info); -      peer->rmap_type = 0; +		peer->rmap_type = 0; -      if (ret == RMAP_DENYMATCH) -	{ -	  /* Free newly generated AS path and community by route-map. */ -	  bgp_attr_flush (attr); -	  return RMAP_DENY; +		if (ret == RMAP_DENYMATCH) { +			/* Free newly generated AS path and community by +			 * route-map. */ +			bgp_attr_flush(attr); +			return RMAP_DENY; +		}  	} -    } -  return RMAP_PERMIT; +	return RMAP_PERMIT;  } -static int -bgp_output_modifier (struct peer *peer, struct prefix *p, struct attr *attr, -		     afi_t afi, safi_t safi, const char *rmap_name) +static int bgp_output_modifier(struct peer *peer, struct prefix *p, +			       struct attr *attr, afi_t afi, safi_t safi, +			       const char *rmap_name)  { -  struct bgp_filter *filter; -  struct bgp_info info; -  route_map_result_t ret; -  struct route_map *rmap = NULL; +	struct bgp_filter *filter; +	struct bgp_info info; +	route_map_result_t ret; +	struct route_map *rmap = NULL; -  filter = &peer->filter[afi][safi]; +	filter = &peer->filter[afi][safi]; -  /* Apply default weight value. */ -  if (peer->weight[afi][safi]) -    (bgp_attr_extra_get (attr))->weight = peer->weight[afi][safi]; +	/* Apply default weight value. */ +	if (peer->weight[afi][safi]) +		(bgp_attr_extra_get(attr))->weight = peer->weight[afi][safi]; -  if (rmap_name) -    { -      rmap = route_map_lookup_by_name(rmap_name); +	if (rmap_name) { +		rmap = route_map_lookup_by_name(rmap_name); -      if (rmap == NULL) -	    return RMAP_DENY; -    } -  else -    { -      if (ROUTE_MAP_OUT_NAME(filter)) -        { -          rmap = ROUTE_MAP_OUT (filter); +		if (rmap == NULL) +			return RMAP_DENY; +	} else { +		if (ROUTE_MAP_OUT_NAME(filter)) { +			rmap = ROUTE_MAP_OUT(filter); -          if (rmap == NULL) -	        return RMAP_DENY; -        } -    } +			if (rmap == NULL) +				return RMAP_DENY; +		} +	} -  /* Route map apply. */ -  if (rmap) -    { -      /* Duplicate current value to new strucutre for modification. */ -      info.peer = peer; -      info.attr = attr; +	/* Route map apply. */ +	if (rmap) { +		/* Duplicate current value to new strucutre for modification. */ +		info.peer = peer; +		info.attr = attr; -      SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT); +		SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT); -      /* Apply BGP route map to the attribute. */ -      ret = route_map_apply (rmap, p, RMAP_BGP, &info); +		/* Apply BGP route map to the attribute. */ +		ret = route_map_apply(rmap, p, RMAP_BGP, &info); -      peer->rmap_type = 0; +		peer->rmap_type = 0; -      if (ret == RMAP_DENYMATCH) -	/* caller has multiple error paths with bgp_attr_flush() */ -	return RMAP_DENY; -    } -  return RMAP_PERMIT; +		if (ret == RMAP_DENYMATCH) +			/* caller has multiple error paths with bgp_attr_flush() +			 */ +			return RMAP_DENY; +	} +	return RMAP_PERMIT;  }  /* If this is an EBGP peer with remove-private-AS */ -static void -bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi, -                           struct peer *peer, struct attr *attr) -{ -  if (peer->sort == BGP_PEER_EBGP && -      (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE) || -       peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE) || -       peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL) || -       peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS))) -    { -      // Take action on the entire aspath -      if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE) || -          peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) -        { -          if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) -            attr->aspath = aspath_replace_private_asns (attr->aspath, bgp->as); - -          // The entire aspath consists of private ASNs so create an empty aspath -          else if (aspath_private_as_check (attr->aspath)) -            attr->aspath = aspath_empty_get (); - -          // There are some public and some private ASNs, remove the private ASNs -          else -            attr->aspath = aspath_remove_private_asns (attr->aspath); -        } - -      // 'all' was not specified so the entire aspath must be private ASNs -      // for us to do anything -      else if (aspath_private_as_check (attr->aspath)) -        { -          if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) -            attr->aspath = aspath_replace_private_asns (attr->aspath, bgp->as); -          else -            attr->aspath = aspath_empty_get (); -        } -    } +static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi, +				       struct peer *peer, struct attr *attr) +{ +	if (peer->sort == BGP_PEER_EBGP +	    && (peer_af_flag_check(peer, afi, safi, +				   PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE) +		|| peer_af_flag_check(peer, afi, safi, +				      PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE) +		|| peer_af_flag_check(peer, afi, safi, +				      PEER_FLAG_REMOVE_PRIVATE_AS_ALL) +		|| peer_af_flag_check(peer, afi, safi, +				      PEER_FLAG_REMOVE_PRIVATE_AS))) { +		// Take action on the entire aspath +		if (peer_af_flag_check(peer, afi, safi, +				       PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE) +		    || peer_af_flag_check(peer, afi, safi, +					  PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) { +			if (peer_af_flag_check( +				    peer, afi, safi, +				    PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) +				attr->aspath = aspath_replace_private_asns( +					attr->aspath, bgp->as); + +			// The entire aspath consists of private ASNs so create +			// an empty aspath +			else if (aspath_private_as_check(attr->aspath)) +				attr->aspath = aspath_empty_get(); + +			// There are some public and some private ASNs, remove +			// the private ASNs +			else +				attr->aspath = aspath_remove_private_asns( +					attr->aspath); +		} + +		// 'all' was not specified so the entire aspath must be private +		// ASNs +		// for us to do anything +		else if (aspath_private_as_check(attr->aspath)) { +			if (peer_af_flag_check( +				    peer, afi, safi, +				    PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) +				attr->aspath = aspath_replace_private_asns( +					attr->aspath, bgp->as); +			else +				attr->aspath = aspath_empty_get(); +		} +	}  }  /* If this is an EBGP peer with as-override */ -static void -bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi, -                     struct peer *peer, struct attr *attr) +static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi, +				 struct peer *peer, struct attr *attr) +{ +	if (peer->sort == BGP_PEER_EBGP +	    && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) { +		if (aspath_single_asn_check(attr->aspath, peer->as)) +			attr->aspath = aspath_replace_specific_asn( +				attr->aspath, peer->as, bgp->as); +	} +} + +static void subgroup_announce_reset_nhop(u_char family, struct attr *attr)  { -  if (peer->sort == BGP_PEER_EBGP && -      peer_af_flag_check (peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) -    { -      if (aspath_single_asn_check (attr->aspath, peer->as)) -        attr->aspath = aspath_replace_specific_asn (attr->aspath, peer->as, bgp->as); -    } +	if (family == AF_INET) +		attr->nexthop.s_addr = 0; +	if (family == AF_INET6) +		memset(&attr->extra->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);  } -static void -subgroup_announce_reset_nhop (u_char family, struct attr *attr) -{ -  if (family == AF_INET) -    attr->nexthop.s_addr = 0; -  if (family == AF_INET6) -    memset (&attr->extra->mp_nexthop_global, 0, IPV6_MAX_BYTELEN); -} - -int -subgroup_announce_check (struct bgp_info *ri, struct update_subgroup *subgrp, -			 struct prefix *p, struct attr *attr) -{ -  struct bgp_filter *filter; -  struct peer *from; -  struct peer *peer; -  struct peer *onlypeer; -  struct bgp *bgp; -  struct attr *riattr; -  struct peer_af *paf; -  char buf[PREFIX_STRLEN]; -  int ret; -  int transparent; -  int reflect; -  afi_t afi; -  safi_t safi; -  int samepeer_safe = 0;	/* for synthetic mplsvpns routes */ - -  if (DISABLE_BGP_ANNOUNCE) -    return 0; - -  afi = SUBGRP_AFI(subgrp); -  safi = SUBGRP_SAFI(subgrp); -  peer = SUBGRP_PEER(subgrp); -  onlypeer = NULL; -  if (CHECK_FLAG (peer->flags, PEER_FLAG_LONESOUL)) -    onlypeer = SUBGRP_PFIRST(subgrp)->peer; - -  from = ri->peer; -  filter = &peer->filter[afi][safi]; -  bgp = SUBGRP_INST(subgrp); -  riattr = bgp_info_mpath_count (ri) ? bgp_info_mpath_attr (ri) : ri->attr; +int subgroup_announce_check(struct bgp_info *ri, struct update_subgroup *subgrp, +			    struct prefix *p, struct attr *attr) +{ +	struct bgp_filter *filter; +	struct peer *from; +	struct peer *peer; +	struct peer *onlypeer; +	struct bgp *bgp; +	struct attr *riattr; +	struct peer_af *paf; +	char buf[PREFIX_STRLEN]; +	int ret; +	int transparent; +	int reflect; +	afi_t afi; +	safi_t safi; +	int samepeer_safe = 0; /* for synthetic mplsvpns routes */ + +	if (DISABLE_BGP_ANNOUNCE) +		return 0; + +	afi = SUBGRP_AFI(subgrp); +	safi = SUBGRP_SAFI(subgrp); +	peer = SUBGRP_PEER(subgrp); +	onlypeer = NULL; +	if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL)) +		onlypeer = SUBGRP_PFIRST(subgrp)->peer; + +	from = ri->peer; +	filter = &peer->filter[afi][safi]; +	bgp = SUBGRP_INST(subgrp); +	riattr = bgp_info_mpath_count(ri) ? bgp_info_mpath_attr(ri) : ri->attr;  #if ENABLE_BGP_VNC -  if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN) && -      ((ri->type == ZEBRA_ROUTE_BGP_DIRECT) || -       (ri->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) { - -    /* -     * direct and direct_ext type routes originate internally even -     * though they can have peer pointers that reference other systems -     */ -    prefix2str(p, buf, PREFIX_STRLEN); -    zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe", __func__, buf); -    samepeer_safe = 1; -  } +	if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN) +	    && ((ri->type == ZEBRA_ROUTE_BGP_DIRECT) +		|| (ri->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) { + +		/* +		 * direct and direct_ext type routes originate internally even +		 * though they can have peer pointers that reference other +		 * systems +		 */ +		prefix2str(p, buf, PREFIX_STRLEN); +		zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe", +			   __func__, buf); +		samepeer_safe = 1; +	}  #endif -  /* With addpath we may be asked to TX all kinds of paths so make sure -   * ri is valid */ -  if (!CHECK_FLAG (ri->flags, BGP_INFO_VALID) || -      CHECK_FLAG (ri->flags, BGP_INFO_HISTORY) || -      CHECK_FLAG (ri->flags, BGP_INFO_REMOVED)) -    { -      return 0; -    } +	/* With addpath we may be asked to TX all kinds of paths so make sure +	 * ri is valid */ +	if (!CHECK_FLAG(ri->flags, BGP_INFO_VALID) +	    || CHECK_FLAG(ri->flags, BGP_INFO_HISTORY) +	    || CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) { +		return 0; +	} -  /* If this is not the bestpath then check to see if there is an enabled addpath -   * feature that requires us to advertise it */ -  if (! CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) -    { -      if (! bgp_addpath_tx_path(peer, afi, safi, ri)) -        { -          return 0; -        } -    } +	/* If this is not the bestpath then check to see if there is an enabled +	 * addpath +	 * feature that requires us to advertise it */ +	if (!CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) { +		if (!bgp_addpath_tx_path(peer, afi, safi, ri)) { +			return 0; +		} +	} -  /* Aggregate-address suppress check. */ -  if (ri->extra && ri->extra->suppress) -    if (! UNSUPPRESS_MAP_NAME (filter)) -      { -	return 0; -      } +	/* Aggregate-address suppress check. */ +	if (ri->extra && ri->extra->suppress) +		if (!UNSUPPRESS_MAP_NAME(filter)) { +			return 0; +		} -  /* Do not send back route to sender. */ -  if (onlypeer && from == onlypeer) -    { -      return 0; -    } +	/* Do not send back route to sender. */ +	if (onlypeer && from == onlypeer) { +		return 0; +	} -  /* Do not send the default route in the BGP table if the neighbor is -   * configured for default-originate */ -  if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)) -    { -      if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY) -        return 0; -      else if (p->family == AF_INET6 && p->prefixlen == 0) -        return 0; -    } +	/* Do not send the default route in the BGP table if the neighbor is +	 * configured for default-originate */ +	if (CHECK_FLAG(peer->af_flags[afi][safi], +		       PEER_FLAG_DEFAULT_ORIGINATE)) { +		if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY) +			return 0; +		else if (p->family == AF_INET6 && p->prefixlen == 0) +			return 0; +	} -  /* Transparency check. */ -  if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT) -      && CHECK_FLAG (from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)) -    transparent = 1; -  else -    transparent = 0; +	/* Transparency check. */ +	if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT) +	    && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)) +		transparent = 1; +	else +		transparent = 0; + +	/* If community is not disabled check the no-export and local. */ +	if (!transparent && bgp_community_filter(peer, riattr)) { +		if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) +			zlog_debug( +				"subgrpannouncecheck: community filter check fail"); +		return 0; +	} -  /* If community is not disabled check the no-export and local. */ -  if (! transparent && bgp_community_filter (peer, riattr)) -    { -      if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) -	zlog_debug ("subgrpannouncecheck: community filter check fail"); -      return 0; -    } +	/* If the attribute has originator-id and it is same as remote +	   peer's id. */ +	if (onlypeer && riattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID) +	    && (IPV4_ADDR_SAME(&onlypeer->remote_id, +			       &riattr->extra->originator_id))) { +		if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) +			zlog_debug( +				"%s [Update:SEND] %s originator-id is same as " +				"remote router-id", +				onlypeer->host, +				prefix2str(p, buf, sizeof(buf))); +		return 0; +	} -  /* If the attribute has originator-id and it is same as remote -     peer's id. */ -  if (onlypeer && -      riattr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID) && -      (IPV4_ADDR_SAME (&onlypeer->remote_id, &riattr->extra->originator_id))) -	{ -          if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) -	    zlog_debug ("%s [Update:SEND] %s originator-id is same as " -		  "remote router-id", -		  onlypeer->host, prefix2str (p, buf, sizeof (buf))); -	  return 0; -	} - -  /* ORF prefix-list filter check */ -  if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV) -      && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV) -	  || CHECK_FLAG (peer->af_cap[afi][safi], -			 PEER_CAP_ORF_PREFIX_SM_OLD_RCV))) -    if (peer->orf_plist[afi][safi]) -      { -	if (prefix_list_apply (peer->orf_plist[afi][safi], p) == PREFIX_DENY) -	  { -            if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) -              zlog_debug ("%s [Update:SEND] %s is filtered via ORF", -                          peer->host, prefix2str (p, buf, sizeof (buf))); -	    return 0; -	  } -      } - -  /* Output filter check. */ -  if (bgp_output_filter (peer, p, riattr, afi, safi) == FILTER_DENY) -    { -      if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) -	zlog_debug ("%s [Update:SEND] %s is filtered", -	      peer->host, prefix2str (p, buf, sizeof (buf))); -      return 0; -    } +	/* ORF prefix-list filter check */ +	if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV) +	    && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV) +		|| CHECK_FLAG(peer->af_cap[afi][safi], +			      PEER_CAP_ORF_PREFIX_SM_OLD_RCV))) +		if (peer->orf_plist[afi][safi]) { +			if (prefix_list_apply(peer->orf_plist[afi][safi], p) +			    == PREFIX_DENY) { +				if (bgp_debug_update(NULL, p, +						     subgrp->update_group, 0)) +					zlog_debug( +						"%s [Update:SEND] %s is filtered via ORF", +						peer->host, +						prefix2str(p, buf, +							   sizeof(buf))); +				return 0; +			} +		} + +	/* Output filter check. */ +	if (bgp_output_filter(peer, p, riattr, afi, safi) == FILTER_DENY) { +		if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) +			zlog_debug("%s [Update:SEND] %s is filtered", +				   peer->host, prefix2str(p, buf, sizeof(buf))); +		return 0; +	}  #ifdef BGP_SEND_ASPATH_CHECK -  /* AS path loop check. */ -  if (onlypeer && aspath_loop_check (riattr->aspath, onlypeer->as)) -    { -      if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) -        zlog_debug ("%s [Update:SEND] suppress announcement to peer AS %u " -	      "that is part of AS path.", -	      onlypeer->host, onlypeer->as); -      return 0; -    } +	/* AS path loop check. */ +	if (onlypeer && aspath_loop_check(riattr->aspath, onlypeer->as)) { +		if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) +			zlog_debug( +				"%s [Update:SEND] suppress announcement to peer AS %u " +				"that is part of AS path.", +				onlypeer->host, onlypeer->as); +		return 0; +	}  #endif /* BGP_SEND_ASPATH_CHECK */ -  /* 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(riattr->aspath, bgp->confed_id)) -	{ -          if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) -	    zlog_debug ("%s [Update:SEND] suppress announcement to peer AS %u" -		  " is AS path.", -		  peer->host, -		  bgp->confed_id); -	  return 0; +	/* 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(riattr->aspath, bgp->confed_id)) { +			if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) +				zlog_debug( +					"%s [Update:SEND] suppress announcement to peer AS %u" +					" is AS path.", +					peer->host, bgp->confed_id); +			return 0; +		}  	} -    } -  /* Route-Reflect check. */ -  if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP) -    reflect = 1; -  else -    reflect = 0; +	/* Route-Reflect check. */ +	if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP) +		reflect = 1; +	else +		reflect = 0; + +	/* IBGP reflection check. */ +	if (reflect && !samepeer_safe) { +		/* A route from a Client peer. */ +		if (CHECK_FLAG(from->af_flags[afi][safi], +			       PEER_FLAG_REFLECTOR_CLIENT)) { +			/* Reflect to all the Non-Client peers and also to the +			   Client peers other than the originator.  Originator +			   check +			   is already done.  So there is noting to do. */ +			/* no bgp client-to-client reflection check. */ +			if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT)) +				if (CHECK_FLAG(peer->af_flags[afi][safi], +					       PEER_FLAG_REFLECTOR_CLIENT)) +					return 0; +		} else { +			/* A route from a Non-client peer. Reflect to all other +			   clients. */ +			if (!CHECK_FLAG(peer->af_flags[afi][safi], +					PEER_FLAG_REFLECTOR_CLIENT)) +				return 0; +		} +	} -  /* IBGP reflection check. */ -  if (reflect && !samepeer_safe) -    { -      /* A route from a Client peer. */ -      if (CHECK_FLAG (from->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) -	{ -	  /* Reflect to all the Non-Client peers and also to the -             Client peers other than the originator.  Originator check -             is already done.  So there is noting to do. */ -	  /* no bgp client-to-client reflection check. */ -	  if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT)) -	    if (CHECK_FLAG (peer->af_flags[afi][safi], -			    PEER_FLAG_REFLECTOR_CLIENT)) -	      return 0; -	} -      else -	{ -	  /* A route from a Non-client peer. Reflect to all other -	     clients. */ -	  if (! CHECK_FLAG (peer->af_flags[afi][safi], -			    PEER_FLAG_REFLECTOR_CLIENT)) -	    return 0; +	/* For modify attribute, copy it to temporary structure. */ +	bgp_attr_dup(attr, riattr); + +	/* If local-preference is not set. */ +	if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED) +	    && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) { +		attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF); +		attr->local_pref = bgp->default_local_pref;  	} -    } -  /* For modify attribute, copy it to temporary structure. */ -  bgp_attr_dup (attr, riattr); +	/* If originator-id is not set and the route is to be reflected, +	   set the originator id */ +	if (reflect +	    && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) { +		attr->extra = bgp_attr_extra_get(attr); +		IPV4_ADDR_COPY(&(attr->extra->originator_id), +			       &(from->remote_id)); +		SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID); +	} -  /* If local-preference is not set. */ -  if ((peer->sort == BGP_PEER_IBGP -       || peer->sort == BGP_PEER_CONFED) -      && (! (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))) -    { -      attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF); -      attr->local_pref = bgp->default_local_pref; -    } +	/* Remove MED if its an EBGP peer - will get overwritten by route-maps +	 */ +	if (peer->sort == BGP_PEER_EBGP +	    && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) { +		if (from != bgp->peer_self && !transparent +		    && !CHECK_FLAG(peer->af_flags[afi][safi], +				   PEER_FLAG_MED_UNCHANGED)) +			attr->flag &= +				~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)); +	} -  /* If originator-id is not set and the route is to be reflected, -     set the originator id */ -  if (reflect && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) -    { -      attr->extra = bgp_attr_extra_get(attr); -      IPV4_ADDR_COPY(&(attr->extra->originator_id), &(from->remote_id)); -      SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID); -    } +	/* Since the nexthop attribute can vary per peer, it is not explicitly +	 * set +	 * in announce check, only certain flags and length (or number of +	 * nexthops +	 * -- for IPv6/MP_REACH) are set here in order to guide the update +	 * formation +	 * code in setting the nexthop(s) on a per peer basis in +	 * reformat_peer(). +	 * Typically, the source nexthop in the attribute is preserved but in +	 * the +	 * scenarios where we know it will always be overwritten, we reset the +	 * nexthop to "0" in an attempt to achieve better Update packing. An +	 * example of this is when a prefix from each of 2 IBGP peers needs to +	 * be +	 * announced to an EBGP peer (and they have the same attributes barring +	 * their nexthop). +	 */ +	if (reflect) +		SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED); + +#define NEXTHOP_IS_V6                                                          \ +	((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN                          \ +	  && (p->family == AF_INET6 || peer_cap_enhe(peer)))                   \ +	 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN)                     \ +	     && attr->extra->mp_nexthop_len >= IPV6_MAX_BYTELEN)) + +	/* IPv6/MP starts with 1 nexthop. The link-local address is passed only +	 * if +	 * the peer (group) is configured to receive link-local nexthop +	 * unchanged +	 * and it is available in the prefix OR we're not reflecting the route +	 * and +	 * the peer (group) to whom we're going to announce is on a shared +	 * network +	 * and this is either a self-originated route or the peer is EBGP. +	 */ +	if (NEXTHOP_IS_V6) { +		attr->extra->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; +		if ((CHECK_FLAG(peer->af_flags[afi][safi], +				PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED) +		     && IN6_IS_ADDR_LINKLOCAL(&attr->extra->mp_nexthop_local)) +		    || (!reflect && peer->shared_network +			&& (from == bgp->peer_self +			    || peer->sort == BGP_PEER_EBGP))) { +			attr->extra->mp_nexthop_len = +				BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; +		} -  /* Remove MED if its an EBGP peer - will get overwritten by route-maps */ -  if (peer->sort == BGP_PEER_EBGP -      && attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) -    { -      if (from != bgp->peer_self && ! transparent -	  && ! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) -	attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)); -    } +		/* Clear off link-local nexthop in source, whenever it is not +		 * needed to +		 * ensure more prefixes share the same attribute for +		 * announcement. +		 */ +		if (!(CHECK_FLAG(peer->af_flags[afi][safi], +				 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED))) +			memset(&attr->extra->mp_nexthop_local, 0, +			       IPV6_MAX_BYTELEN); +	} -  /* Since the nexthop attribute can vary per peer, it is not explicitly set -   * in announce check, only certain flags and length (or number of nexthops -   * -- for IPv6/MP_REACH) are set here in order to guide the update formation -   * code in setting the nexthop(s) on a per peer basis in reformat_peer(). -   * Typically, the source nexthop in the attribute is preserved but in the -   * scenarios where we know it will always be overwritten, we reset the -   * nexthop to "0" in an attempt to achieve better Update packing. An -   * example of this is when a prefix from each of 2 IBGP peers needs to be -   * announced to an EBGP peer (and they have the same attributes barring -   * their nexthop). -   */ -  if (reflect) -    SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED); - -#define NEXTHOP_IS_V6 (\ -    (safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN &&\ -     (p->family == AF_INET6 || peer_cap_enhe(peer))) || \ -    ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) &&\ -     attr->extra->mp_nexthop_len >= IPV6_MAX_BYTELEN)) - -  /* IPv6/MP starts with 1 nexthop. The link-local address is passed only if -   * the peer (group) is configured to receive link-local nexthop unchanged -   * and it is available in the prefix OR we're not reflecting the route and -   * the peer (group) to whom we're going to announce is on a shared network -   * and this is either a self-originated route or the peer is EBGP. -   */ -  if (NEXTHOP_IS_V6) -    { -      attr->extra->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; -      if ((CHECK_FLAG (peer->af_flags[afi][safi], -                       PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED) && -           IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_local)) || -          (!reflect && peer->shared_network && -           (from == bgp->peer_self || peer->sort == BGP_PEER_EBGP))) -        { -          attr->extra->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; -        } - -      /* Clear off link-local nexthop in source, whenever it is not needed to -       * ensure more prefixes share the same attribute for announcement. -       */ -      if (!(CHECK_FLAG (peer->af_flags[afi][safi], -            PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED))) -        memset (&attr->extra->mp_nexthop_local, 0, IPV6_MAX_BYTELEN); -    } +	bgp_peer_remove_private_as(bgp, afi, safi, peer, attr); +	bgp_peer_as_override(bgp, afi, safi, peer, attr); + +	/* Route map & unsuppress-map apply. */ +	if (ROUTE_MAP_OUT_NAME(filter) || (ri->extra && ri->extra->suppress)) { +		struct bgp_info info; +		struct attr dummy_attr; +		struct attr_extra dummy_extra; + +		dummy_attr.extra = &dummy_extra; + +		info.peer = peer; +		info.attr = attr; +		/* don't confuse inbound and outbound setting */ +		RESET_FLAG(attr->rmap_change_flags); + +		/* +		 * The route reflector is not allowed to modify the attributes +		 * of the reflected IBGP routes unless explicitly allowed. +		 */ +		if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP) +		    && !bgp_flag_check(bgp, +				       BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) { +			bgp_attr_dup(&dummy_attr, attr); +			info.attr = &dummy_attr; +		} -  bgp_peer_remove_private_as(bgp, afi, safi, peer, attr); -  bgp_peer_as_override(bgp, afi, safi, peer, attr); +		SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT); -  /* Route map & unsuppress-map apply. */ -  if (ROUTE_MAP_OUT_NAME (filter) -      || (ri->extra && ri->extra->suppress) ) -    { -      struct bgp_info info; -      struct attr dummy_attr; -      struct attr_extra dummy_extra; - -      dummy_attr.extra = &dummy_extra; - -      info.peer = peer; -      info.attr = attr; -      /* don't confuse inbound and outbound setting */ -      RESET_FLAG(attr->rmap_change_flags); - -      /* -       * The route reflector is not allowed to modify the attributes -       * of the reflected IBGP routes unless explicitly allowed. -       */ -      if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP) -        && !bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) -        { -          bgp_attr_dup (&dummy_attr, attr); -          info.attr = &dummy_attr; -        } - -      SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT); - -      if (ri->extra && ri->extra->suppress) -	ret = route_map_apply (UNSUPPRESS_MAP (filter), p, RMAP_BGP, &info); -      else -	ret = route_map_apply (ROUTE_MAP_OUT (filter), p, RMAP_BGP, &info); - -      peer->rmap_type = 0; - -      if (ret == RMAP_DENYMATCH) -	{ -	  bgp_attr_flush (attr); -	  return 0; +		if (ri->extra && ri->extra->suppress) +			ret = route_map_apply(UNSUPPRESS_MAP(filter), p, +					      RMAP_BGP, &info); +		else +			ret = route_map_apply(ROUTE_MAP_OUT(filter), p, +					      RMAP_BGP, &info); + +		peer->rmap_type = 0; + +		if (ret == RMAP_DENYMATCH) { +			bgp_attr_flush(attr); +			return 0; +		}  	} -    } -  /* After route-map has been applied, we check to see if the nexthop to -   * be carried in the attribute (that is used for the announcement) can -   * be cleared off or not. We do this in all cases where we would be -   * setting the nexthop to "ourselves". For IPv6, we only need to consider -   * the global nexthop here; the link-local nexthop would have been cleared -   * already, and if not, it is required by the update formation code. -   * Also see earlier comments in this function. -   */ -  /* -   * If route-map has performed some operation on the nexthop or the peer -   * configuration says to pass it unchanged, we cannot reset the nexthop -   * here, so only attempt to do it if these aren't true. Note that the -   * route-map handler itself might have cleared the nexthop, if for example, -   * it is configured as 'peer-address'. -   */ -  if (!bgp_rmap_nhop_changed(attr->rmap_change_flags, -                             riattr->rmap_change_flags) && -      !transparent && -      !CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) -    { -      /* We can reset the nexthop, if setting (or forcing) it to 'self' */ -      if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF) || -          CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_FORCE_NEXTHOP_SELF)) -        { -          if (!reflect || -              CHECK_FLAG (peer->af_flags[afi][safi], -                          PEER_FLAG_FORCE_NEXTHOP_SELF)) -            subgroup_announce_reset_nhop ((peer_cap_enhe(peer) ? -                          AF_INET6 : p->family), attr); -        } -      else if (peer->sort == BGP_PEER_EBGP) -        { -          /* Can also reset the nexthop if announcing to EBGP, but only if -           * no peer in the subgroup is on a shared subnet. -           * Note: 3rd party nexthop currently implemented for IPv4 only. -           */ -          SUBGRP_FOREACH_PEER (subgrp, paf) -            { -              if (bgp_multiaccess_check_v4 (riattr->nexthop, paf->peer)) -                break; -            } -          if (!paf) -            subgroup_announce_reset_nhop ((peer_cap_enhe(peer) ? AF_INET6 : p->family), attr); -        } -      /* If IPv6/MP and nexthop does not have any override and happens to -       * be a link-local address, reset it so that we don't pass along the -       * source's link-local IPv6 address to recipients who may not be on -       * the same interface. -       */ -      if (p->family == AF_INET6 || peer_cap_enhe(peer)) -        { -          if (IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global)) -            subgroup_announce_reset_nhop (AF_INET6, attr); -        } -    } +	/* After route-map has been applied, we check to see if the nexthop to +	 * be carried in the attribute (that is used for the announcement) can +	 * be cleared off or not. We do this in all cases where we would be +	 * setting the nexthop to "ourselves". For IPv6, we only need to +	 * consider +	 * the global nexthop here; the link-local nexthop would have been +	 * cleared +	 * already, and if not, it is required by the update formation code. +	 * Also see earlier comments in this function. +	 */ +	/* +	 * If route-map has performed some operation on the nexthop or the peer +	 * configuration says to pass it unchanged, we cannot reset the nexthop +	 * here, so only attempt to do it if these aren't true. Note that the +	 * route-map handler itself might have cleared the nexthop, if for +	 * example, +	 * it is configured as 'peer-address'. +	 */ +	if (!bgp_rmap_nhop_changed(attr->rmap_change_flags, +				   riattr->rmap_change_flags) +	    && !transparent +	    && !CHECK_FLAG(peer->af_flags[afi][safi], +			   PEER_FLAG_NEXTHOP_UNCHANGED)) { +		/* We can reset the nexthop, if setting (or forcing) it to +		 * 'self' */ +		if (CHECK_FLAG(peer->af_flags[afi][safi], +			       PEER_FLAG_NEXTHOP_SELF) +		    || CHECK_FLAG(peer->af_flags[afi][safi], +				  PEER_FLAG_FORCE_NEXTHOP_SELF)) { +			if (!reflect +			    || CHECK_FLAG(peer->af_flags[afi][safi], +					  PEER_FLAG_FORCE_NEXTHOP_SELF)) +				subgroup_announce_reset_nhop( +					(peer_cap_enhe(peer) ? AF_INET6 +							     : p->family), +					attr); +		} else if (peer->sort == BGP_PEER_EBGP) { +			/* Can also reset the nexthop if announcing to EBGP, but +			 * only if +			 * no peer in the subgroup is on a shared subnet. +			 * Note: 3rd party nexthop currently implemented for +			 * IPv4 only. +			 */ +			SUBGRP_FOREACH_PEER(subgrp, paf) +			{ +				if (bgp_multiaccess_check_v4(riattr->nexthop, +							     paf->peer)) +					break; +			} +			if (!paf) +				subgroup_announce_reset_nhop( +					(peer_cap_enhe(peer) ? AF_INET6 +							     : p->family), +					attr); +		} +		/* If IPv6/MP and nexthop does not have any override and happens +		 * to +		 * be a link-local address, reset it so that we don't pass along +		 * the +		 * source's link-local IPv6 address to recipients who may not be +		 * on +		 * the same interface. +		 */ +		if (p->family == AF_INET6 || peer_cap_enhe(peer)) { +			if (IN6_IS_ADDR_LINKLOCAL( +				    &attr->extra->mp_nexthop_global)) +				subgroup_announce_reset_nhop(AF_INET6, attr); +		} +	} -  return 1; +	return 1;  } -struct bgp_info_pair -{ -  struct bgp_info *old; -  struct bgp_info *new; +struct bgp_info_pair { +	struct bgp_info *old; +	struct bgp_info *new;  }; -static void -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; -  struct bgp_info *ri; -  struct bgp_info *ri1; -  struct bgp_info *ri2; -  struct bgp_info *nextri = NULL; -  int paths_eq, do_mpath, debug; -  struct list mp_list; -  char pfx_buf[PREFIX2STR_BUFFER]; -  char path_buf[PATH_ADDPATH_STR_BUFFER]; - -  bgp_mp_list_init (&mp_list); -  do_mpath = (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1); - -  debug = bgp_debug_bestpath(&rn->p); - -  if (debug) -    prefix2str (&rn->p, pfx_buf, sizeof (pfx_buf)); - -  /* bgp deterministic-med */ -  new_select = NULL; -  if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED)) -    { +static void 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; +	struct bgp_info *ri; +	struct bgp_info *ri1; +	struct bgp_info *ri2; +	struct bgp_info *nextri = NULL; +	int paths_eq, do_mpath, debug; +	struct list mp_list; +	char pfx_buf[PREFIX2STR_BUFFER]; +	char path_buf[PATH_ADDPATH_STR_BUFFER]; + +	bgp_mp_list_init(&mp_list); +	do_mpath = +		(mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1); + +	debug = bgp_debug_bestpath(&rn->p); + +	if (debug) +		prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf)); + +	/* bgp deterministic-med */ +	new_select = NULL; +	if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) { + +		/* Clear BGP_INFO_DMED_SELECTED for all paths */ +		for (ri1 = rn->info; ri1; ri1 = ri1->next) +			bgp_info_unset_flag(rn, ri1, BGP_INFO_DMED_SELECTED); + +		for (ri1 = rn->info; ri1; ri1 = ri1->next) { +			if (CHECK_FLAG(ri1->flags, BGP_INFO_DMED_CHECK)) +				continue; +			if (BGP_INFO_HOLDDOWN(ri1)) +				continue; +			if (ri1->peer && ri1->peer != bgp->peer_self) +				if (ri1->peer->status != Established) +					continue; + +			new_select = ri1; +			if (ri1->next) { +				for (ri2 = ri1->next; ri2; ri2 = ri2->next) { +					if (CHECK_FLAG(ri2->flags, +						       BGP_INFO_DMED_CHECK)) +						continue; +					if (BGP_INFO_HOLDDOWN(ri2)) +						continue; +					if (ri2->peer +					    && ri2->peer != bgp->peer_self +					    && !CHECK_FLAG( +						       ri2->peer->sflags, +						       PEER_STATUS_NSF_WAIT)) +						if (ri2->peer->status +						    != Established) +							continue; + +					if (aspath_cmp_left(ri1->attr->aspath, +							    ri2->attr->aspath) +					    || aspath_cmp_left_confed( +						       ri1->attr->aspath, +						       ri2->attr->aspath)) { +						if (bgp_info_cmp(bgp, ri2, +								 new_select, +								 &paths_eq, +								 mpath_cfg, +								 debug, +								 pfx_buf)) { +							bgp_info_unset_flag( +								rn, new_select, +								BGP_INFO_DMED_SELECTED); +							new_select = 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); + +			if (debug) { +				bgp_info_path_with_addpath_rx_str(new_select, +								  path_buf); +				zlog_debug("%s: %s is the bestpath from AS %d", +					   pfx_buf, path_buf, +					   aspath_get_first_as( +						   new_select->attr->aspath)); +			} +		} +	} -      /* Clear BGP_INFO_DMED_SELECTED for all paths */ -      for (ri1 = rn->info; ri1; ri1 = ri1->next) -        bgp_info_unset_flag (rn, ri1, BGP_INFO_DMED_SELECTED); - -      for (ri1 = rn->info; ri1; ri1 = ri1->next) -        { -          if (CHECK_FLAG (ri1->flags, BGP_INFO_DMED_CHECK)) -            continue; -          if (BGP_INFO_HOLDDOWN (ri1)) -            continue; -          if (ri1->peer && ri1->peer != bgp->peer_self) -            if (ri1->peer->status != Established) -              continue; - -          new_select = ri1; -          if (ri1->next) -            { -              for (ri2 = ri1->next; ri2; ri2 = ri2->next) -                { -                  if (CHECK_FLAG (ri2->flags, BGP_INFO_DMED_CHECK)) -                    continue; -                  if (BGP_INFO_HOLDDOWN (ri2)) -                    continue; -                  if (ri2->peer && -                      ri2->peer != bgp->peer_self && -                      !CHECK_FLAG (ri2->peer->sflags, PEER_STATUS_NSF_WAIT)) -                    if (ri2->peer->status != Established) -                      continue; - -                  if (aspath_cmp_left (ri1->attr->aspath, ri2->attr->aspath) -                      || aspath_cmp_left_confed (ri1->attr->aspath, -                                                 ri2->attr->aspath)) -                    { -                      if (bgp_info_cmp (bgp, ri2, new_select, &paths_eq, -                                        mpath_cfg, debug, pfx_buf)) -                        { -                          bgp_info_unset_flag (rn, new_select, BGP_INFO_DMED_SELECTED); -                          new_select = 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); - -          if (debug) -            { -              bgp_info_path_with_addpath_rx_str (new_select, path_buf); -              zlog_debug("%s: %s is the bestpath from AS %d", -                         pfx_buf, path_buf, aspath_get_first_as(new_select->attr->aspath)); -            } -        } -    } +	/* Check old selected route and new selected route. */ +	old_select = NULL; +	new_select = NULL; +	for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1); +	     ri = nextri) { +		if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) +			old_select = ri; + +		if (BGP_INFO_HOLDDOWN(ri)) { +			/* reap REMOVED routes, if needs be +			 * selected route must stay for a while longer though +			 */ +			if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED) +			    && (ri != old_select)) +				bgp_info_reap(rn, ri); + +			continue; +		} -  /* Check old selected route and new selected route. */ -  old_select = NULL; -  new_select = NULL; -  for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1); ri = nextri) -    { -      if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) -	old_select = ri; - -      if (BGP_INFO_HOLDDOWN (ri)) -        { -          /* reap REMOVED routes, if needs be  -           * selected route must stay for a while longer though -           */ -          if (CHECK_FLAG (ri->flags, BGP_INFO_REMOVED) -              && (ri != old_select)) -              bgp_info_reap (rn, ri); -           -          continue; -        } - -      if (ri->peer && -          ri->peer != bgp->peer_self && -          !CHECK_FLAG (ri->peer->sflags, PEER_STATUS_NSF_WAIT)) -        if (ri->peer->status != Established) -          continue; - -      if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED) -          && (! CHECK_FLAG (ri->flags, BGP_INFO_DMED_SELECTED))) -	{ -	  bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_CHECK); -	  continue; -        } - -      bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_CHECK); - -      if (bgp_info_cmp (bgp, ri, new_select, &paths_eq, mpath_cfg, debug, pfx_buf)) -	{ -	  new_select = ri; +		if (ri->peer && ri->peer != bgp->peer_self +		    && !CHECK_FLAG(ri->peer->sflags, PEER_STATUS_NSF_WAIT)) +			if (ri->peer->status != Established) +				continue; + +		if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED) +		    && (!CHECK_FLAG(ri->flags, BGP_INFO_DMED_SELECTED))) { +			bgp_info_unset_flag(rn, ri, BGP_INFO_DMED_CHECK); +			continue; +		} + +		bgp_info_unset_flag(rn, ri, BGP_INFO_DMED_CHECK); + +		if (bgp_info_cmp(bgp, ri, new_select, &paths_eq, mpath_cfg, +				 debug, pfx_buf)) { +			new_select = ri; +		}  	} -    } -     -  /* Now that we know which path is the bestpath see if any of the other paths -   * qualify as multipaths -   */ -  if (debug) -    { -      if (new_select) -        bgp_info_path_with_addpath_rx_str (new_select, path_buf); -      else -        sprintf (path_buf, "NONE"); -      zlog_debug("%s: After path selection, newbest is %s oldbest was %s", -                 pfx_buf, path_buf, -                 old_select ? old_select->peer->host : "NONE"); -    } -  if (do_mpath && new_select) -    { -      for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1); ri = nextri) -        { - -          if (debug) -            bgp_info_path_with_addpath_rx_str (ri, path_buf); - -          if (ri == new_select) -            { -              if (debug) -                zlog_debug("%s: %s is the bestpath, add to the multipath list", -                           pfx_buf, path_buf); -              bgp_mp_list_add (&mp_list, ri); -              continue; -            } - -          if (BGP_INFO_HOLDDOWN (ri)) -            continue; - -          if (ri->peer && -              ri->peer != bgp->peer_self && -              !CHECK_FLAG (ri->peer->sflags, PEER_STATUS_NSF_WAIT)) -            if (ri->peer->status != Established) -              continue; - -          if (!bgp_info_nexthop_cmp (ri, new_select)) -            { -              if (debug) -                zlog_debug("%s: %s has the same nexthop as the bestpath, skip it", -                           pfx_buf, path_buf); -              continue; -            } - -          bgp_info_cmp (bgp, ri, new_select, &paths_eq, mpath_cfg, debug, pfx_buf); - -          if (paths_eq) -            { -              if (debug) -                zlog_debug("%s: %s is equivalent to the bestpath, add to the multipath list", -                           pfx_buf, path_buf); -	      bgp_mp_list_add (&mp_list, ri); -            } -        } -    } +	/* Now that we know which path is the bestpath see if any of the other +	 * paths +	 * qualify as multipaths +	 */ +	if (debug) { +		if (new_select) +			bgp_info_path_with_addpath_rx_str(new_select, path_buf); +		else +			sprintf(path_buf, "NONE"); +		zlog_debug( +			"%s: After path selection, newbest is %s oldbest was %s", +			pfx_buf, path_buf, +			old_select ? old_select->peer->host : "NONE"); +	} -  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); +	if (do_mpath && new_select) { +		for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1); +		     ri = nextri) { + +			if (debug) +				bgp_info_path_with_addpath_rx_str(ri, path_buf); + +			if (ri == new_select) { +				if (debug) +					zlog_debug( +						"%s: %s is the bestpath, add to the multipath list", +						pfx_buf, path_buf); +				bgp_mp_list_add(&mp_list, ri); +				continue; +			} + +			if (BGP_INFO_HOLDDOWN(ri)) +				continue; + +			if (ri->peer && ri->peer != bgp->peer_self +			    && !CHECK_FLAG(ri->peer->sflags, +					   PEER_STATUS_NSF_WAIT)) +				if (ri->peer->status != Established) +					continue; + +			if (!bgp_info_nexthop_cmp(ri, new_select)) { +				if (debug) +					zlog_debug( +						"%s: %s has the same nexthop as the bestpath, skip it", +						pfx_buf, path_buf); +				continue; +			} + +			bgp_info_cmp(bgp, ri, new_select, &paths_eq, mpath_cfg, +				     debug, pfx_buf); + +			if (paths_eq) { +				if (debug) +					zlog_debug( +						"%s: %s is equivalent to the bestpath, add to the multipath list", +						pfx_buf, path_buf); +				bgp_mp_list_add(&mp_list, ri); +			} +		} +	} -  result->old = old_select; -  result->new = new_select; +	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); -  return; +	result->old = old_select; +	result->new = new_select; + +	return;  }  /*   * A new route/change in bestpath of an existing route. Evaluate the path   * for advertisement to the subgroup.   */ -int -subgroup_process_announce_selected (struct update_subgroup *subgrp, -				    struct bgp_info *selected, -				    struct bgp_node *rn, -                                    u_int32_t addpath_tx_id) -{ -  struct prefix *p; -  struct peer *onlypeer; -  struct attr attr; -  struct attr_extra extra; -  afi_t afi; -  safi_t safi; - -  p = &rn->p; -  afi = SUBGRP_AFI(subgrp); -  safi = SUBGRP_SAFI(subgrp); -  onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? -	      (SUBGRP_PFIRST(subgrp))->peer : NULL); - -  /* First update is deferred until ORF or ROUTE-REFRESH is received */ -  if (onlypeer && CHECK_FLAG (onlypeer->af_sflags[afi][safi], -			      PEER_STATUS_ORF_WAIT_REFRESH)) -    return 0; - -  memset(&extra, 0, sizeof(struct attr_extra)); -  /* It's initialized in bgp_announce_check() */ -  attr.extra = &extra; - -  /* Announcement to the subgroup.  If the route is filtered withdraw it. */ -  if (selected) -    { -      if (subgroup_announce_check(selected, subgrp, p, &attr)) -        bgp_adj_out_set_subgroup(rn, subgrp, &attr, selected); -      else -        bgp_adj_out_unset_subgroup(rn, subgrp, 1, selected->addpath_tx_id); -    } +int subgroup_process_announce_selected(struct update_subgroup *subgrp, +				       struct bgp_info *selected, +				       struct bgp_node *rn, +				       u_int32_t addpath_tx_id) +{ +	struct prefix *p; +	struct peer *onlypeer; +	struct attr attr; +	struct attr_extra extra; +	afi_t afi; +	safi_t safi; -  /* If selected is NULL we must withdraw the path using addpath_tx_id */ -  else -    { -      bgp_adj_out_unset_subgroup(rn, subgrp, 1, addpath_tx_id); -    } +	p = &rn->p; +	afi = SUBGRP_AFI(subgrp); +	safi = SUBGRP_SAFI(subgrp); +	onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer +						 : NULL); + +	/* First update is deferred until ORF or ROUTE-REFRESH is received */ +	if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi], +				   PEER_STATUS_ORF_WAIT_REFRESH)) +		return 0; + +	memset(&extra, 0, sizeof(struct attr_extra)); +	/* It's initialized in bgp_announce_check() */ +	attr.extra = &extra; + +	/* Announcement to the subgroup.  If the route is filtered withdraw it. +	 */ +	if (selected) { +		if (subgroup_announce_check(selected, subgrp, p, &attr)) +			bgp_adj_out_set_subgroup(rn, subgrp, &attr, selected); +		else +			bgp_adj_out_unset_subgroup(rn, subgrp, 1, +						   selected->addpath_tx_id); +	} -  return 0; +	/* If selected is NULL we must withdraw the path using addpath_tx_id */ +	else { +		bgp_adj_out_unset_subgroup(rn, subgrp, 1, addpath_tx_id); +	} + +	return 0;  }  /*   * Clear IGP changed flag and attribute changed flag for a route (all paths).   * This is called at the end of route processing.   */ -static void -bgp_zebra_clear_route_change_flags (struct bgp_node *rn) +static void bgp_zebra_clear_route_change_flags(struct bgp_node *rn)  { -  struct bgp_info *ri; +	struct bgp_info *ri; -  for (ri = rn->info; ri; ri = ri->next) -    { -	if (BGP_INFO_HOLDDOWN (ri)) -          continue; -        UNSET_FLAG (ri->flags, BGP_INFO_IGP_CHANGED); -        UNSET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED); -    } +	for (ri = rn->info; ri; ri = ri->next) { +		if (BGP_INFO_HOLDDOWN(ri)) +			continue; +		UNSET_FLAG(ri->flags, BGP_INFO_IGP_CHANGED); +		UNSET_FLAG(ri->flags, BGP_INFO_ATTR_CHANGED); +	}  }  /* @@ -1841,1155 +1853,1147 @@ bgp_zebra_clear_route_change_flags (struct bgp_node *rn)   * if the route selection returns the same best route as earlier - to   * determine if we need to update zebra or not.   */ -static int -bgp_zebra_has_route_changed (struct bgp_node *rn, struct bgp_info *selected) -{ -  struct bgp_info *mpinfo; - -  /* If this is multipath, check all selected paths for any nexthop change or -   * attribute change. Some attribute changes (e.g., community) aren't of -   * relevance to the RIB, but we'll update zebra to ensure we handle the -   * case of BGP nexthop change. This is the behavior when the best path has -   * an attribute change anyway. -   */ -  if (CHECK_FLAG (selected->flags, BGP_INFO_IGP_CHANGED) || -      CHECK_FLAG (selected->flags, BGP_INFO_MULTIPATH_CHG)) -    return 1; - -  /* If this is multipath, check all selected paths for any nexthop change */ -  for (mpinfo = bgp_info_mpath_first (selected); mpinfo; -       mpinfo = bgp_info_mpath_next (mpinfo)) -    { -      if (CHECK_FLAG (mpinfo->flags, BGP_INFO_IGP_CHANGED) -          || CHECK_FLAG (mpinfo->flags, BGP_INFO_ATTR_CHANGED)) -        return 1; -    } +static int bgp_zebra_has_route_changed(struct bgp_node *rn, +				       struct bgp_info *selected) +{ +	struct bgp_info *mpinfo; + +	/* If this is multipath, check all selected paths for any nexthop change +	 * or +	 * attribute change. Some attribute changes (e.g., community) aren't of +	 * relevance to the RIB, but we'll update zebra to ensure we handle the +	 * case of BGP nexthop change. This is the behavior when the best path +	 * has +	 * an attribute change anyway. +	 */ +	if (CHECK_FLAG(selected->flags, BGP_INFO_IGP_CHANGED) +	    || CHECK_FLAG(selected->flags, BGP_INFO_MULTIPATH_CHG)) +		return 1; + +	/* If this is multipath, check all selected paths for any nexthop change +	 */ +	for (mpinfo = bgp_info_mpath_first(selected); mpinfo; +	     mpinfo = bgp_info_mpath_next(mpinfo)) { +		if (CHECK_FLAG(mpinfo->flags, BGP_INFO_IGP_CHANGED) +		    || CHECK_FLAG(mpinfo->flags, BGP_INFO_ATTR_CHANGED)) +			return 1; +	} -  /* Nothing has changed from the RIB's perspective. */ -  return 0; +	/* Nothing has changed from the RIB's perspective. */ +	return 0;  } -struct bgp_process_queue -{ -  struct bgp *bgp; -  struct bgp_node *rn; -  afi_t afi; -  safi_t safi; +struct bgp_process_queue { +	struct bgp *bgp; +	struct bgp_node *rn; +	afi_t afi; +	safi_t safi;  }; -static wq_item_status -bgp_process_main (struct work_queue *wq, void *data) -{ -  struct bgp_process_queue *pq = data; -  struct bgp *bgp = pq->bgp; -  struct bgp_node *rn = pq->rn; -  afi_t afi = pq->afi; -  safi_t safi = pq->safi; -  struct prefix *p = &rn->p; -  struct bgp_info *new_select; -  struct bgp_info *old_select; -  struct bgp_info_pair old_and_new; - -  /* Is it end of initial update? (after startup) */ -  if (!rn) -    { -      quagga_timestamp(3, bgp->update_delay_zebra_resume_time, -                       sizeof(bgp->update_delay_zebra_resume_time)); - -      bgp->main_zebra_update_hold = 0; -      for (afi = AFI_IP; afi < AFI_MAX; afi++) -        for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) -          { -            bgp_zebra_announce_table(bgp, afi, safi); -          } -      bgp->main_peers_update_hold = 0; - -      bgp_start_routeadv(bgp); -      return WQ_SUCCESS; -    } - -  /* Best path selection. */ -  bgp_best_selection (bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new); -  old_select = old_and_new.old; -  new_select = old_and_new.new; +static wq_item_status bgp_process_main(struct work_queue *wq, void *data) +{ +	struct bgp_process_queue *pq = data; +	struct bgp *bgp = pq->bgp; +	struct bgp_node *rn = pq->rn; +	afi_t afi = pq->afi; +	safi_t safi = pq->safi; +	struct prefix *p = &rn->p; +	struct bgp_info *new_select; +	struct bgp_info *old_select; +	struct bgp_info_pair old_and_new; + +	/* Is it end of initial update? (after startup) */ +	if (!rn) { +		quagga_timestamp(3, bgp->update_delay_zebra_resume_time, +				 sizeof(bgp->update_delay_zebra_resume_time)); + +		bgp->main_zebra_update_hold = 0; +		for (afi = AFI_IP; afi < AFI_MAX; afi++) +			for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { +				bgp_zebra_announce_table(bgp, afi, safi); +			} +		bgp->main_peers_update_hold = 0; + +		bgp_start_routeadv(bgp); +		return WQ_SUCCESS; +	} -  /* Nothing to do. */ -  if (old_select && old_select == new_select && -      !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR) && -      !CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED) && -      !bgp->addpath_tx_used[afi][safi]) -    { -      if (bgp_zebra_has_route_changed (rn, old_select)) -        { +	/* Best path selection. */ +	bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new); +	old_select = old_and_new.old; +	new_select = old_and_new.new; + +	/* Nothing to do. */ +	if (old_select && old_select == new_select +	    && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR) +	    && !CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED) +	    && !bgp->addpath_tx_used[afi][safi]) { +		if (bgp_zebra_has_route_changed(rn, old_select)) {  #if ENABLE_BGP_VNC -              vnc_import_bgp_add_route(bgp, p, old_select); -              vnc_import_bgp_exterior_add_route(bgp, p, old_select); +			vnc_import_bgp_add_route(bgp, p, old_select); +			vnc_import_bgp_exterior_add_route(bgp, p, old_select);  #endif -        bgp_zebra_announce (p, old_select, bgp, afi, safi); -        } -      UNSET_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG); -      bgp_zebra_clear_route_change_flags (rn); -      UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED); -      return WQ_SUCCESS; -    } +			bgp_zebra_announce(p, old_select, bgp, afi, safi); +		} +		UNSET_FLAG(old_select->flags, BGP_INFO_MULTIPATH_CHG); +		bgp_zebra_clear_route_change_flags(rn); +		UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED); +		return WQ_SUCCESS; +	} -  /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set */ -  UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR); +	/* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set +	 */ +	UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR); -  /* bestpath has changed; bump version */ -  if (old_select || new_select) -    { -      bgp_bump_version(rn); - -      if (!bgp->t_rmap_def_originate_eval) -        { -          bgp_lock (bgp); -          THREAD_TIMER_ON(bm->master, bgp->t_rmap_def_originate_eval, -                          update_group_refresh_default_originate_route_map, -                          bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER); -        } -    } +	/* bestpath has changed; bump version */ +	if (old_select || new_select) { +		bgp_bump_version(rn); -  if (old_select) -    bgp_info_unset_flag (rn, old_select, BGP_INFO_SELECTED); -  if (new_select) -    { -      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); -    } +		if (!bgp->t_rmap_def_originate_eval) { +			bgp_lock(bgp); +			THREAD_TIMER_ON( +				bm->master, bgp->t_rmap_def_originate_eval, +				update_group_refresh_default_originate_route_map, +				bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER); +		} +	} + +	if (old_select) +		bgp_info_unset_flag(rn, old_select, BGP_INFO_SELECTED); +	if (new_select) { +		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); +	}  #if ENABLE_BGP_VNC -  if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) { -    if (old_select != new_select) { -      if (old_select) { -        vnc_import_bgp_exterior_del_route(bgp, p, old_select); -        vnc_import_bgp_del_route(bgp, p, old_select); -      } -      if (new_select) { -        vnc_import_bgp_exterior_add_route(bgp, p, new_select); -        vnc_import_bgp_add_route(bgp, p, new_select); -      } -    } -  } +	if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) { +		if (old_select != new_select) { +			if (old_select) { +				vnc_import_bgp_exterior_del_route(bgp, p, +								  old_select); +				vnc_import_bgp_del_route(bgp, p, old_select); +			} +			if (new_select) { +				vnc_import_bgp_exterior_add_route(bgp, p, +								  new_select); +				vnc_import_bgp_add_route(bgp, p, new_select); +			} +		} +	}  #endif -  group_announce_route(bgp, afi, safi, rn, new_select); - -  /* FIB update. */ -  if ((safi == SAFI_UNICAST || safi == SAFI_MULTICAST) && -      (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW) && -      !bgp_option_check (BGP_OPT_NO_FIB)) -    { -      if (new_select  -	  && new_select->type == ZEBRA_ROUTE_BGP  -	  && (new_select->sub_type == BGP_ROUTE_NORMAL || -              new_select->sub_type == BGP_ROUTE_AGGREGATE)) -	bgp_zebra_announce (p, new_select, bgp, afi, safi); -      else -	{ -	  /* Withdraw the route from the kernel. */ -	  if (old_select  -	      && old_select->type == ZEBRA_ROUTE_BGP -	      && (old_select->sub_type == BGP_ROUTE_NORMAL || -                  old_select->sub_type == BGP_ROUTE_AGGREGATE)) -	    bgp_zebra_withdraw (p, old_select, safi); +	group_announce_route(bgp, afi, safi, rn, new_select); + +	/* FIB update. */ +	if ((safi == SAFI_UNICAST || safi == SAFI_MULTICAST) +	    && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW) +	    && !bgp_option_check(BGP_OPT_NO_FIB)) { +		if (new_select && new_select->type == ZEBRA_ROUTE_BGP +		    && (new_select->sub_type == BGP_ROUTE_NORMAL +			|| new_select->sub_type == BGP_ROUTE_AGGREGATE)) +			bgp_zebra_announce(p, new_select, bgp, afi, safi); +		else { +			/* Withdraw the route from the kernel. */ +			if (old_select && old_select->type == ZEBRA_ROUTE_BGP +			    && (old_select->sub_type == BGP_ROUTE_NORMAL +				|| old_select->sub_type == BGP_ROUTE_AGGREGATE)) +				bgp_zebra_withdraw(p, old_select, safi); +		}  	} -    } -  /* Clear any route change flags. */ -  bgp_zebra_clear_route_change_flags (rn); +	/* Clear any route change flags. */ +	bgp_zebra_clear_route_change_flags(rn); -  /* Reap old select bgp_info, if it has been removed */ -  if (old_select && CHECK_FLAG (old_select->flags, BGP_INFO_REMOVED)) -    bgp_info_reap (rn, old_select); -   -  UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED); -  return WQ_SUCCESS; +	/* Reap old select bgp_info, if it has been removed */ +	if (old_select && CHECK_FLAG(old_select->flags, BGP_INFO_REMOVED)) +		bgp_info_reap(rn, old_select); + +	UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED); +	return WQ_SUCCESS;  } -static void -bgp_processq_del (struct work_queue *wq, void *data) +static void bgp_processq_del(struct work_queue *wq, void *data)  { -  struct bgp_process_queue *pq = data; -  struct bgp_table *table; +	struct bgp_process_queue *pq = data; +	struct bgp_table *table; -  bgp_unlock (pq->bgp); -  if (pq->rn) -    { -      table = bgp_node_table (pq->rn); -      bgp_unlock_node (pq->rn); -      bgp_table_unlock (table); -    } -  XFREE (MTYPE_BGP_PROCESS_QUEUE, pq); +	bgp_unlock(pq->bgp); +	if (pq->rn) { +		table = bgp_node_table(pq->rn); +		bgp_unlock_node(pq->rn); +		bgp_table_unlock(table); +	} +	XFREE(MTYPE_BGP_PROCESS_QUEUE, pq);  } -void -bgp_process_queue_init (void) +void bgp_process_queue_init(void)  { -  if (!bm->process_main_queue) -    { -      bm->process_main_queue -	= work_queue_new (bm->master, "process_main_queue"); - -      if ( !bm->process_main_queue) -        { -          zlog_err ("%s: Failed to allocate work queue", __func__); -          exit (1); -        } -    } -   -  bm->process_main_queue->spec.workfunc = &bgp_process_main; -  bm->process_main_queue->spec.del_item_data = &bgp_processq_del; -  bm->process_main_queue->spec.max_retries = 0; -  bm->process_main_queue->spec.hold = 50; -  /* Use a higher yield value of 50ms for main queue processing */ -  bm->process_main_queue->spec.yield = 50 * 1000L; +	if (!bm->process_main_queue) { +		bm->process_main_queue = +			work_queue_new(bm->master, "process_main_queue"); + +		if (!bm->process_main_queue) { +			zlog_err("%s: Failed to allocate work queue", __func__); +			exit(1); +		} +	} + +	bm->process_main_queue->spec.workfunc = &bgp_process_main; +	bm->process_main_queue->spec.del_item_data = &bgp_processq_del; +	bm->process_main_queue->spec.max_retries = 0; +	bm->process_main_queue->spec.hold = 50; +	/* Use a higher yield value of 50ms for main queue processing */ +	bm->process_main_queue->spec.yield = 50 * 1000L;  } -void -bgp_process (struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi) +void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)  { -  struct bgp_process_queue *pqnode; -   -  /* already scheduled for processing? */ -  if (CHECK_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED)) -    return; +	struct bgp_process_queue *pqnode; + +	/* already scheduled for processing? */ +	if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED)) +		return; -  if (bm->process_main_queue == NULL) -    return; +	if (bm->process_main_queue == NULL) +		return; -  pqnode = XCALLOC (MTYPE_BGP_PROCESS_QUEUE,  -                    sizeof (struct bgp_process_queue)); -  if (!pqnode) -    return; +	pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE, +			 sizeof(struct bgp_process_queue)); +	if (!pqnode) +		return; -  /* all unlocked in bgp_processq_del */ -  bgp_table_lock (bgp_node_table (rn)); -  pqnode->rn = bgp_lock_node (rn); -  pqnode->bgp = bgp; -  bgp_lock (bgp); -  pqnode->afi = afi; -  pqnode->safi = safi; -  work_queue_add (bm->process_main_queue, pqnode); -  SET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED); -  return; +	/* all unlocked in bgp_processq_del */ +	bgp_table_lock(bgp_node_table(rn)); +	pqnode->rn = bgp_lock_node(rn); +	pqnode->bgp = bgp; +	bgp_lock(bgp); +	pqnode->afi = afi; +	pqnode->safi = safi; +	work_queue_add(bm->process_main_queue, pqnode); +	SET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED); +	return;  } -void -bgp_add_eoiu_mark (struct bgp *bgp) +void bgp_add_eoiu_mark(struct bgp *bgp)  { -  struct bgp_process_queue *pqnode; +	struct bgp_process_queue *pqnode; -  if (bm->process_main_queue == NULL) -    return; +	if (bm->process_main_queue == NULL) +		return; -  pqnode = XCALLOC (MTYPE_BGP_PROCESS_QUEUE, -                    sizeof (struct bgp_process_queue)); -  if (!pqnode) -    return; +	pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE, +			 sizeof(struct bgp_process_queue)); +	if (!pqnode) +		return; -  pqnode->rn = NULL; -  pqnode->bgp = bgp; -  bgp_lock (bgp); -  work_queue_add (bm->process_main_queue, pqnode); +	pqnode->rn = NULL; +	pqnode->bgp = bgp; +	bgp_lock(bgp); +	work_queue_add(bm->process_main_queue, pqnode);  } -static int -bgp_maximum_prefix_restart_timer (struct thread *thread) +static int bgp_maximum_prefix_restart_timer(struct thread *thread)  { -  struct peer *peer; +	struct peer *peer; -  peer = THREAD_ARG (thread); -  peer->t_pmax_restart = NULL; +	peer = THREAD_ARG(thread); +	peer->t_pmax_restart = NULL; -  if (bgp_debug_neighbor_events(peer)) -    zlog_debug ("%s Maximum-prefix restart timer expired, restore peering", -		peer->host); +	if (bgp_debug_neighbor_events(peer)) +		zlog_debug( +			"%s Maximum-prefix restart timer expired, restore peering", +			peer->host); -  peer_clear (peer, NULL); +	peer_clear(peer, NULL); -  return 0; +	return 0;  } -int -bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi, -                             safi_t safi, int always) +int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi, +				int always)  { -  iana_afi_t pkt_afi; -  safi_t pkt_safi; +	iana_afi_t pkt_afi; +	safi_t pkt_safi; -  if (!CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) -    return 0; +	if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) +		return 0; -  if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) -    { -      if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT) -         && ! always) -       return 0; - -      zlog_info ("%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, " -	         "limit %ld", afi_safi_print (afi, safi), peer->host, -	         peer->pcount[afi][safi], peer->pmax[afi][safi]); -      SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT); - -      if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)) -       return 0; - -      /* Convert AFI, SAFI to values for packet. */ -      pkt_afi = afi_int2iana (afi); -      pkt_safi = safi_int2iana (safi); -      { -       u_int8_t ndata[7]; - -       ndata[0] = (pkt_afi >>  8); -       ndata[1] = pkt_afi; -       ndata[2] = pkt_safi; -       ndata[3] = (peer->pmax[afi][safi] >> 24); -       ndata[4] = (peer->pmax[afi][safi] >> 16); -       ndata[5] = (peer->pmax[afi][safi] >> 8); -       ndata[6] = (peer->pmax[afi][safi]); - -       SET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW); -       bgp_notify_send_with_data (peer, BGP_NOTIFY_CEASE, -                                  BGP_NOTIFY_CEASE_MAX_PREFIX, ndata, 7); -      } - -      /* Dynamic peers will just close their connection. */ -      if (peer_dynamic_neighbor (peer)) -        return 1; - -      /* restart timer start */ -      if (peer->pmax_restart[afi][safi]) -	{ -	  peer->v_pmax_restart = peer->pmax_restart[afi][safi] * 60; - -          if (bgp_debug_neighbor_events(peer)) -	    zlog_debug ("%s Maximum-prefix restart timer started for %d secs", -			peer->host, peer->v_pmax_restart); - -	  BGP_TIMER_ON (peer->t_pmax_restart, bgp_maximum_prefix_restart_timer, -			peer->v_pmax_restart); -	} - -      return 1; -    } -  else -    UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT); +	if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) { +		if (CHECK_FLAG(peer->af_sflags[afi][safi], +			       PEER_STATUS_PREFIX_LIMIT) +		    && !always) +			return 0; -  if (peer->pcount[afi][safi] > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) -    { -      if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD) -         && ! always) -       return 0; - -      zlog_info ("%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld", -	         afi_safi_print (afi, safi), peer->host, peer->pcount[afi][safi], -	         peer->pmax[afi][safi]); -      SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD); -    } -  else -    UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD); -  return 0; +		zlog_info( +			"%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, " +			"limit %ld", +			afi_safi_print(afi, safi), peer->host, +			peer->pcount[afi][safi], peer->pmax[afi][safi]); +		SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT); + +		if (CHECK_FLAG(peer->af_flags[afi][safi], +			       PEER_FLAG_MAX_PREFIX_WARNING)) +			return 0; + +		/* Convert AFI, SAFI to values for packet. */ +		pkt_afi = afi_int2iana(afi); +		pkt_safi = safi_int2iana(safi); +		{ +			u_int8_t ndata[7]; + +			ndata[0] = (pkt_afi >> 8); +			ndata[1] = pkt_afi; +			ndata[2] = pkt_safi; +			ndata[3] = (peer->pmax[afi][safi] >> 24); +			ndata[4] = (peer->pmax[afi][safi] >> 16); +			ndata[5] = (peer->pmax[afi][safi] >> 8); +			ndata[6] = (peer->pmax[afi][safi]); + +			SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW); +			bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE, +						  BGP_NOTIFY_CEASE_MAX_PREFIX, +						  ndata, 7); +		} + +		/* Dynamic peers will just close their connection. */ +		if (peer_dynamic_neighbor(peer)) +			return 1; + +		/* restart timer start */ +		if (peer->pmax_restart[afi][safi]) { +			peer->v_pmax_restart = +				peer->pmax_restart[afi][safi] * 60; + +			if (bgp_debug_neighbor_events(peer)) +				zlog_debug( +					"%s Maximum-prefix restart timer started for %d secs", +					peer->host, peer->v_pmax_restart); + +			BGP_TIMER_ON(peer->t_pmax_restart, +				     bgp_maximum_prefix_restart_timer, +				     peer->v_pmax_restart); +		} + +		return 1; +	} else +		UNSET_FLAG(peer->af_sflags[afi][safi], +			   PEER_STATUS_PREFIX_LIMIT); + +	if (peer->pcount[afi][safi] +	    > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) { +		if (CHECK_FLAG(peer->af_sflags[afi][safi], +			       PEER_STATUS_PREFIX_THRESHOLD) +		    && !always) +			return 0; + +		zlog_info( +			"%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld", +			afi_safi_print(afi, safi), peer->host, +			peer->pcount[afi][safi], peer->pmax[afi][safi]); +		SET_FLAG(peer->af_sflags[afi][safi], +			 PEER_STATUS_PREFIX_THRESHOLD); +	} else +		UNSET_FLAG(peer->af_sflags[afi][safi], +			   PEER_STATUS_PREFIX_THRESHOLD); +	return 0;  }  /* Unconditionally remove the route from the RIB, without taking   * damping into consideration (eg, because the session went down)   */ -static void -bgp_rib_remove (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer, -		afi_t afi, safi_t safi) +static void bgp_rib_remove(struct bgp_node *rn, struct bgp_info *ri, +			   struct peer *peer, afi_t afi, safi_t safi)  { -  bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi); -   -  if (!CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) -    bgp_info_delete (rn, ri); /* keep historical info */ -     -  bgp_process (peer->bgp, rn, afi, safi); -} - -static void -bgp_rib_withdraw (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer, -		  afi_t afi, safi_t safi, struct prefix_rd *prd) -{ -  int status = BGP_DAMP_NONE; - -  /* apply dampening, if result is suppressed, we'll be retaining  -   * the bgp_info in the RIB for historical reference. -   */ -  if (CHECK_FLAG (peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) -      && peer->sort == BGP_PEER_EBGP) -    if ( (status = bgp_damp_withdraw (ri, rn, afi, safi, 0))  -         == BGP_DAMP_SUPPRESSED) -      { -        bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi); -        return; -      } -     -#if ENABLE_BGP_VNC -    if (safi == SAFI_MPLS_VPN) { -	struct bgp_node		*prn = NULL; -	struct bgp_table	*table = NULL; - -	prn = bgp_node_get(peer->bgp->rib[afi][safi], (struct prefix *) prd); -	if (prn->info) { -	    table = (struct bgp_table *)(prn->info); - -	    vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( -		peer->bgp, -		prd, -		table, -		&rn->p, -		ri); -	} -	bgp_unlock_node(prn); -    } -    if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) { -        if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) { +	bgp_aggregate_decrement(peer->bgp, &rn->p, ri, afi, safi); -	    vnc_import_bgp_del_route(peer->bgp, &rn->p, ri); -	    vnc_import_bgp_exterior_del_route(peer->bgp, &rn->p, ri); -	} -    } -#endif     -  bgp_rib_remove (rn, ri, peer, afi, safi); +	if (!CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)) +		bgp_info_delete(rn, ri); /* keep historical info */ + +	bgp_process(peer->bgp, rn, afi, safi);  } -static struct bgp_info * -info_make (int type, int sub_type, u_short instance, struct peer *peer, struct attr *attr, -	   struct bgp_node *rn) +static void bgp_rib_withdraw(struct bgp_node *rn, struct bgp_info *ri, +			     struct peer *peer, afi_t afi, safi_t safi, +			     struct prefix_rd *prd)  { -  struct bgp_info *new; +	int status = BGP_DAMP_NONE; -  /* Make new BGP info. */ -  new = XCALLOC (MTYPE_BGP_ROUTE, sizeof (struct bgp_info)); -  new->type = type; -  new->instance = instance; -  new->sub_type = sub_type; -  new->peer = peer; -  new->attr = attr; -  new->uptime = bgp_clock (); -  new->net = rn; -  new->addpath_tx_id = ++peer->bgp->addpath_tx_id; -  return new; -} +	/* apply dampening, if result is suppressed, we'll be retaining +	 * the bgp_info in the RIB for historical reference. +	 */ +	if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) +	    && peer->sort == BGP_PEER_EBGP) +		if ((status = bgp_damp_withdraw(ri, rn, afi, safi, 0)) +		    == BGP_DAMP_SUPPRESSED) { +			bgp_aggregate_decrement(peer->bgp, &rn->p, ri, afi, +						safi); +			return; +		} -static void -overlay_index_update(struct attr *attr, struct eth_segment_id *eth_s_id, union gw_addr *gw_ip) -{ -  struct attr_extra *extra; +#if ENABLE_BGP_VNC +	if (safi == SAFI_MPLS_VPN) { +		struct bgp_node *prn = NULL; +		struct bgp_table *table = NULL; -  if(!attr) -    return; -  extra = bgp_attr_extra_get(attr); +		prn = bgp_node_get(peer->bgp->rib[afi][safi], +				   (struct prefix *)prd); +		if (prn->info) { +			table = (struct bgp_table *)(prn->info); -  if(eth_s_id == NULL) -    { -      memset(&(extra->evpn_overlay.eth_s_id),0, sizeof(struct eth_segment_id)); -    } -  else -    { -      memcpy(&(extra->evpn_overlay.eth_s_id), eth_s_id, sizeof(struct eth_segment_id)); -    } -  if(gw_ip == NULL) -    { -      memset(&(extra->evpn_overlay.gw_ip), 0, sizeof(union gw_addr)); -    } -  else -    { -      memcpy(&(extra->evpn_overlay.gw_ip),gw_ip, sizeof(union gw_addr)); -    } +			vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( +				peer->bgp, prd, table, &rn->p, ri); +		} +		bgp_unlock_node(prn); +	} +	if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) { +		if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) { + +			vnc_import_bgp_del_route(peer->bgp, &rn->p, ri); +			vnc_import_bgp_exterior_del_route(peer->bgp, &rn->p, +							  ri); +		} +	} +#endif +	bgp_rib_remove(rn, ri, peer, afi, safi);  } -static bool -overlay_index_equal(afi_t afi, struct bgp_info *info, struct eth_segment_id *eth_s_id, union gw_addr *gw_ip) +static struct bgp_info *info_make(int type, int sub_type, u_short instance, +				  struct peer *peer, struct attr *attr, +				  struct bgp_node *rn)  { -  struct eth_segment_id *info_eth_s_id, *info_eth_s_id_remote; -  union gw_addr *info_gw_ip, *info_gw_ip_remote; -  char temp[16]; +	struct bgp_info *new; -  if(afi != AFI_L2VPN) -    return true; -  if (!info->attr || !info->attr->extra) -    { -      memset(&temp, 0, 16); -      info_eth_s_id = (struct eth_segment_id *)&temp; -      info_gw_ip = (union gw_addr *)&temp; -      if(eth_s_id == NULL && gw_ip == NULL) -        return true; -    } -  else  -    { -      info_eth_s_id = &(info->attr->extra->evpn_overlay.eth_s_id); -      info_gw_ip = &(info->attr->extra->evpn_overlay.gw_ip); -    } -  if(gw_ip == NULL) -    info_gw_ip_remote = (union gw_addr *)&temp; -  else -    info_gw_ip_remote = gw_ip; -  if(eth_s_id == NULL) -    info_eth_s_id_remote =  (struct eth_segment_id *)&temp; -  else -    info_eth_s_id_remote =  eth_s_id; -  if(!memcmp(info_gw_ip, info_gw_ip_remote, sizeof(union gw_addr))) -    return false; -  return !memcmp(info_eth_s_id, info_eth_s_id_remote, sizeof(struct eth_segment_id)); +	/* Make new BGP info. */ +	new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_info)); +	new->type = type; +	new->instance = instance; +	new->sub_type = sub_type; +	new->peer = peer; +	new->attr = attr; +	new->uptime = bgp_clock(); +	new->net = rn; +	new->addpath_tx_id = ++peer->bgp->addpath_tx_id; +	return new;  } -/* Check if received nexthop is valid or not. */ -static int -bgp_update_martian_nexthop (struct bgp *bgp, afi_t afi, safi_t safi, struct attr *attr) +static void overlay_index_update(struct attr *attr, +				 struct eth_segment_id *eth_s_id, +				 union gw_addr *gw_ip)  { -  struct attr_extra *attre = attr->extra; -  int ret = 0; +	struct attr_extra *extra; -  /* Only validated for unicast and multicast currently. */ -  if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST) -    return 0; +	if (!attr) +		return; +	extra = bgp_attr_extra_get(attr); + +	if (eth_s_id == NULL) { +		memset(&(extra->evpn_overlay.eth_s_id), 0, +		       sizeof(struct eth_segment_id)); +	} else { +		memcpy(&(extra->evpn_overlay.eth_s_id), eth_s_id, +		       sizeof(struct eth_segment_id)); +	} +	if (gw_ip == NULL) { +		memset(&(extra->evpn_overlay.gw_ip), 0, sizeof(union gw_addr)); +	} else { +		memcpy(&(extra->evpn_overlay.gw_ip), gw_ip, +		       sizeof(union gw_addr)); +	} +} -  /* If NEXT_HOP is present, validate it. */ -  if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)) -    { -      if (attr->nexthop.s_addr == 0 || -          IPV4_CLASS_DE (ntohl (attr->nexthop.s_addr)) || -          bgp_nexthop_self (bgp, attr)) -        ret = 1; -    } +static bool overlay_index_equal(afi_t afi, struct bgp_info *info, +				struct eth_segment_id *eth_s_id, +				union gw_addr *gw_ip) +{ +	struct eth_segment_id *info_eth_s_id, *info_eth_s_id_remote; +	union gw_addr *info_gw_ip, *info_gw_ip_remote; +	char temp[16]; + +	if (afi != AFI_L2VPN) +		return true; +	if (!info->attr || !info->attr->extra) { +		memset(&temp, 0, 16); +		info_eth_s_id = (struct eth_segment_id *)&temp; +		info_gw_ip = (union gw_addr *)&temp; +		if (eth_s_id == NULL && gw_ip == NULL) +			return true; +	} else { +		info_eth_s_id = &(info->attr->extra->evpn_overlay.eth_s_id); +		info_gw_ip = &(info->attr->extra->evpn_overlay.gw_ip); +	} +	if (gw_ip == NULL) +		info_gw_ip_remote = (union gw_addr *)&temp; +	else +		info_gw_ip_remote = gw_ip; +	if (eth_s_id == NULL) +		info_eth_s_id_remote = (struct eth_segment_id *)&temp; +	else +		info_eth_s_id_remote = eth_s_id; +	if (!memcmp(info_gw_ip, info_gw_ip_remote, sizeof(union gw_addr))) +		return false; +	return !memcmp(info_eth_s_id, info_eth_s_id_remote, +		       sizeof(struct eth_segment_id)); +} -  /* If MP_NEXTHOP is present, validate it. */ -  /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop; -   * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if -   * it is not an IPv6 link-local address. -   */ -  if (attre && attre->mp_nexthop_len) -    { -      switch (attre->mp_nexthop_len) -        { -        case BGP_ATTR_NHLEN_IPV4: -        case BGP_ATTR_NHLEN_VPNV4: -          ret = (attre->mp_nexthop_global_in.s_addr == 0 || -                 IPV4_CLASS_DE (ntohl (attre->mp_nexthop_global_in.s_addr))); -          break; - -        case BGP_ATTR_NHLEN_IPV6_GLOBAL: -        case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL: -        case BGP_ATTR_NHLEN_VPNV6_GLOBAL: -          ret = (IN6_IS_ADDR_UNSPECIFIED(&attre->mp_nexthop_global) || -                 IN6_IS_ADDR_LOOPBACK(&attre->mp_nexthop_global)    || -                 IN6_IS_ADDR_MULTICAST(&attre->mp_nexthop_global)); -          break; - -        default: -          ret = 1; -          break; -        } -    } +/* Check if received nexthop is valid or not. */ +static int bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi, +				      struct attr *attr) +{ +	struct attr_extra *attre = attr->extra; +	int ret = 0; + +	/* Only validated for unicast and multicast currently. */ +	if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST) +		return 0; + +	/* If NEXT_HOP is present, validate it. */ +	if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) { +		if (attr->nexthop.s_addr == 0 +		    || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr)) +		    || bgp_nexthop_self(bgp, attr)) +			ret = 1; +	} + +	/* If MP_NEXTHOP is present, validate it. */ +	/* Note: For IPv6 nexthops, we only validate the global (1st) nexthop; +	 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if +	 * it is not an IPv6 link-local address. +	 */ +	if (attre && attre->mp_nexthop_len) { +		switch (attre->mp_nexthop_len) { +		case BGP_ATTR_NHLEN_IPV4: +		case BGP_ATTR_NHLEN_VPNV4: +			ret = (attre->mp_nexthop_global_in.s_addr == 0 +			       || IPV4_CLASS_DE(ntohl( +					  attre->mp_nexthop_global_in.s_addr))); +			break; + +		case BGP_ATTR_NHLEN_IPV6_GLOBAL: +		case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL: +		case BGP_ATTR_NHLEN_VPNV6_GLOBAL: +			ret = (IN6_IS_ADDR_UNSPECIFIED( +				       &attre->mp_nexthop_global) +			       || IN6_IS_ADDR_LOOPBACK( +					  &attre->mp_nexthop_global) +			       || IN6_IS_ADDR_MULTICAST( +					  &attre->mp_nexthop_global)); +			break; + +		default: +			ret = 1; +			break; +		} +	} -  return ret; -} - -int -bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id, -            struct attr *attr, afi_t afi, safi_t safi, int type, -            int sub_type, struct prefix_rd *prd, u_char *tag, -            int soft_reconfig, struct bgp_route_evpn* evpn) -{ -  int ret; -  int aspath_loop_count = 0; -  struct bgp_node *rn; -  struct bgp *bgp; -  struct attr new_attr; -  struct attr_extra new_extra; -  struct attr *attr_new; -  struct bgp_info *ri; -  struct bgp_info *new; -  const char *reason; -  char pfx_buf[BGP_PRD_PATH_STRLEN]; -  int connected = 0; -  int do_loop_check = 1; +	return ret; +} + +int bgp_update(struct peer *peer, struct prefix *p, u_int32_t addpath_id, +	       struct attr *attr, afi_t afi, safi_t safi, int type, +	       int sub_type, struct prefix_rd *prd, u_char *tag, +	       int soft_reconfig, struct bgp_route_evpn *evpn) +{ +	int ret; +	int aspath_loop_count = 0; +	struct bgp_node *rn; +	struct bgp *bgp; +	struct attr new_attr; +	struct attr_extra new_extra; +	struct attr *attr_new; +	struct bgp_info *ri; +	struct bgp_info *new; +	const char *reason; +	char pfx_buf[BGP_PRD_PATH_STRLEN]; +	int connected = 0; +	int do_loop_check = 1;  #if ENABLE_BGP_VNC -  int vnc_implicit_withdraw = 0; +	int vnc_implicit_withdraw = 0;  #endif -  memset (&new_attr, 0, sizeof(struct attr)); -  memset (&new_extra, 0, sizeof(struct attr_extra)); +	memset(&new_attr, 0, sizeof(struct attr)); +	memset(&new_extra, 0, sizeof(struct attr_extra)); -  bgp = peer->bgp; -  rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd); -   -  /* When peer's soft reconfiguration enabled.  Record input packet in -     Adj-RIBs-In.  */ -  if (! soft_reconfig && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) -      && peer != bgp->peer_self) -    bgp_adj_in_set (rn, peer, attr, addpath_id); - -  /* Check previously received route. */ -  for (ri = rn->info; ri; ri = ri->next) -    if (ri->peer == peer && ri->type == type && ri->sub_type == sub_type && -        ri->addpath_rx_id == addpath_id) -      break; - -  /* AS path local-as loop check. */ -  if (peer->change_local_as) -    { -      if (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)) -	aspath_loop_count = 1; +	bgp = peer->bgp; +	rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd); -      if (aspath_loop_check (attr->aspath, peer->change_local_as) > aspath_loop_count)  -	{ -	  reason = "as-path contains our own AS;"; -	  goto filtered; -	} -    } +	/* When peer's soft reconfiguration enabled.  Record input packet in +	   Adj-RIBs-In.  */ +	if (!soft_reconfig +	    && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) +	    && peer != bgp->peer_self) +		bgp_adj_in_set(rn, peer, attr, addpath_id); -  /* If the peer is configured for "allowas-in origin" and the last ASN in the -   * as-path is our ASN then we do not need to call aspath_loop_check -   */ -  if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) -      if (aspath_get_last_as(attr->aspath) == bgp->as) -        do_loop_check = 0; +	/* Check previously received route. */ +	for (ri = rn->info; ri; ri = ri->next) +		if (ri->peer == peer && ri->type == type +		    && ri->sub_type == sub_type +		    && ri->addpath_rx_id == addpath_id) +			break; + +	/* AS path local-as loop check. */ +	if (peer->change_local_as) { +		if (!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)) +			aspath_loop_count = 1; + +		if (aspath_loop_check(attr->aspath, peer->change_local_as) +		    > aspath_loop_count) { +			reason = "as-path contains our own AS;"; +			goto filtered; +		} +	} -  /* AS path loop check. */ -  if (do_loop_check) -    { -      if (aspath_loop_check (attr->aspath, bgp->as) > peer->allowas_in[afi][safi] -          || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) -              && aspath_loop_check(attr->aspath, bgp->confed_id) > peer->allowas_in[afi][safi])) -        { -          reason = "as-path contains our own AS;"; -          goto filtered; -        } -    } +	/* If the peer is configured for "allowas-in origin" and the last ASN in +	 * the +	 * as-path is our ASN then we do not need to call aspath_loop_check +	 */ +	if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) +		if (aspath_get_last_as(attr->aspath) == bgp->as) +			do_loop_check = 0; + +	/* AS path loop check. */ +	if (do_loop_check) { +		if (aspath_loop_check(attr->aspath, bgp->as) +			    > peer->allowas_in[afi][safi] +		    || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) +			&& aspath_loop_check(attr->aspath, bgp->confed_id) +				   > peer->allowas_in[afi][safi])) { +			reason = "as-path contains our own AS;"; +			goto filtered; +		} +	} -  /* Route reflector originator ID check.  */ -  if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID) -      && IPV4_ADDR_SAME (&bgp->router_id, &attr->extra->originator_id)) -    { -      reason = "originator is us;"; -      goto filtered; -    } +	/* Route reflector originator ID check.  */ +	if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID) +	    && IPV4_ADDR_SAME(&bgp->router_id, &attr->extra->originator_id)) { +		reason = "originator is us;"; +		goto filtered; +	} -  /* Route reflector cluster ID check.  */ -  if (bgp_cluster_filter (peer, attr)) -    { -      reason = "reflected from the same cluster;"; -      goto  filtered; -    } +	/* Route reflector cluster ID check.  */ +	if (bgp_cluster_filter(peer, attr)) { +		reason = "reflected from the same cluster;"; +		goto filtered; +	} -  /* Apply incoming filter.  */ -  if (bgp_input_filter (peer, p, attr, afi, safi) == FILTER_DENY) -    { -      reason = "filter;"; -      goto filtered; -    } +	/* Apply incoming filter.  */ +	if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) { +		reason = "filter;"; +		goto filtered; +	} -  new_attr.extra = &new_extra; -  bgp_attr_dup (&new_attr, attr); +	new_attr.extra = &new_extra; +	bgp_attr_dup(&new_attr, attr); + +	/* Apply incoming route-map. +	 * NB: new_attr may now contain newly allocated values from route-map +	 * "set" +	 * commands, so we need bgp_attr_flush in the error paths, until we +	 * intern +	 * the attr (which takes over the memory references) */ +	if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL) +	    == RMAP_DENY) { +		reason = "route-map;"; +		bgp_attr_flush(&new_attr); +		goto filtered; +	} -  /* Apply incoming route-map. -   * NB: new_attr may now contain newly allocated values from route-map "set" -   * commands, so we need bgp_attr_flush in the error paths, until we intern -   * the attr (which takes over the memory references) */ -  if (bgp_input_modifier (peer, p, &new_attr, afi, safi, NULL) == RMAP_DENY) -    { -      reason = "route-map;"; -      bgp_attr_flush (&new_attr); -      goto filtered; -    } +	/* next hop check.  */ +	if (bgp_update_martian_nexthop(bgp, afi, safi, &new_attr)) { +		reason = "martian or self next-hop;"; +		bgp_attr_flush(&new_attr); +		goto filtered; +	} -  /* next hop check.  */ -  if (bgp_update_martian_nexthop (bgp, afi, safi, &new_attr)) -    { -       reason = "martian or self next-hop;"; -       bgp_attr_flush (&new_attr); -       goto filtered; -    } +	attr_new = bgp_attr_intern(&new_attr); + +	/* If the update is implicit withdraw. */ +	if (ri) { +		ri->uptime = bgp_clock(); + +		/* Same attribute comes in. */ +		if (!CHECK_FLAG(ri->flags, BGP_INFO_REMOVED) +		    && attrhash_cmp(ri->attr, attr_new) +		    && (overlay_index_equal( +			       afi, ri, evpn == NULL ? NULL : &evpn->eth_s_id, +			       evpn == NULL ? NULL : &evpn->gw_ip))) { +			if (CHECK_FLAG(bgp->af_flags[afi][safi], +				       BGP_CONFIG_DAMPENING) +			    && peer->sort == BGP_PEER_EBGP +			    && CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)) { +				if (bgp_debug_update(peer, p, NULL, 1)) +					zlog_debug("%s rcvd %s", peer->host, +						   bgp_debug_rdpfxpath2str( +							   prd, p, +							   addpath_id ? 1 : 0, +							   addpath_id, pfx_buf, +							   sizeof(pfx_buf))); + +				if (bgp_damp_update(ri, rn, afi, safi) +				    != BGP_DAMP_SUPPRESSED) { +					bgp_aggregate_increment(bgp, p, ri, afi, +								safi); +					bgp_process(bgp, rn, afi, safi); +				} +			} else /* Duplicate - odd */ +			{ +				if (bgp_debug_update(peer, p, NULL, 1)) { +					if (!peer->rcvd_attr_printed) { +						zlog_debug( +							"%s rcvd UPDATE w/ attr: %s", +							peer->host, +							peer->rcvd_attr_str); +						peer->rcvd_attr_printed = 1; +					} + +					zlog_debug( +						"%s rcvd %s...duplicate ignored", +						peer->host, +						bgp_debug_rdpfxpath2str( +							prd, p, +							addpath_id ? 1 : 0, +							addpath_id, pfx_buf, +							sizeof(pfx_buf))); +				} + +				/* graceful restart STALE flag unset. */ +				if (CHECK_FLAG(ri->flags, BGP_INFO_STALE)) { +					bgp_info_unset_flag(rn, ri, +							    BGP_INFO_STALE); +					bgp_process(bgp, rn, afi, safi); +				} +			} + +			bgp_unlock_node(rn); +			bgp_attr_unintern(&attr_new); + +			return 0; +		} -  attr_new = bgp_attr_intern (&new_attr); +		/* Withdraw/Announce before we fully processed the withdraw */ +		if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) { +			if (bgp_debug_update(peer, p, NULL, 1)) +				zlog_debug( +					"%s rcvd %s, flapped quicker than processing", +					peer->host, +					bgp_debug_rdpfxpath2str( +						prd, p, addpath_id ? 1 : 0, +						addpath_id, pfx_buf, +						sizeof(pfx_buf))); +			bgp_info_restore(rn, ri); +		} -  /* If the update is implicit withdraw. */ -  if (ri) -    { -      ri->uptime = bgp_clock (); - -      /* Same attribute comes in. */ -      if (!CHECK_FLAG (ri->flags, BGP_INFO_REMOVED)  -          && attrhash_cmp (ri->attr, attr_new) -          && (overlay_index_equal(afi, ri, evpn==NULL?NULL:&evpn->eth_s_id, -                                  evpn==NULL?NULL:&evpn->gw_ip))) -	{ -	  if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) -	      && peer->sort == BGP_PEER_EBGP -	      && CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) -	    { -	      if (bgp_debug_update(peer, p, NULL, 1)) -                zlog_debug ("%s rcvd %s", peer->host, -                            bgp_debug_rdpfxpath2str (prd, p, addpath_id ? 1 : 0, -                                      addpath_id, pfx_buf, sizeof (pfx_buf))); - -	      if (bgp_damp_update (ri, rn, afi, safi) != BGP_DAMP_SUPPRESSED) -	        { -                  bgp_aggregate_increment (bgp, p, ri, afi, safi); -                  bgp_process (bgp, rn, afi, safi); -                } -	    } -          else /* Duplicate - odd */ -	    { -	      if (bgp_debug_update(peer, p, NULL, 1)) -                { -                if (!peer->rcvd_attr_printed) -                  { -                    zlog_debug ("%s rcvd UPDATE w/ attr: %s", peer->host, peer->rcvd_attr_str); -                    peer->rcvd_attr_printed = 1; -                  } - -		  zlog_debug ("%s rcvd %s...duplicate ignored", -		              peer->host, -                              bgp_debug_rdpfxpath2str (prd, p, addpath_id ? -                                1 : 0, addpath_id, pfx_buf, sizeof (pfx_buf))); -                } - -	      /* graceful restart STALE flag unset. */ -	      if (CHECK_FLAG (ri->flags, BGP_INFO_STALE)) -		{ -		  bgp_info_unset_flag (rn, ri, BGP_INFO_STALE); -		  bgp_process (bgp, rn, afi, safi); -		} -	    } - -	  bgp_unlock_node (rn); -	  bgp_attr_unintern (&attr_new); - -	  return 0; -	} - -      /* Withdraw/Announce before we fully processed the withdraw */ -      if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) -        { -          if (bgp_debug_update(peer, p, NULL, 1)) -            zlog_debug ("%s rcvd %s, flapped quicker than processing", -                        peer->host, -                        bgp_debug_rdpfxpath2str (prd, p, addpath_id ? 1 : 0, -                                  addpath_id, pfx_buf, sizeof (pfx_buf))); -          bgp_info_restore (rn, ri); -        } - -      /* Received Logging. */ -      if (bgp_debug_update(peer, p, NULL, 1)) -	  zlog_debug ("%s rcvd %s", peer->host, -                      bgp_debug_rdpfxpath2str (prd, p, addpath_id ? 1 : 0, -                                        addpath_id, pfx_buf, sizeof (pfx_buf))); - -      /* graceful restart STALE flag unset. */ -      if (CHECK_FLAG (ri->flags, BGP_INFO_STALE)) -	bgp_info_unset_flag (rn, ri, BGP_INFO_STALE); - -      /* The attribute is changed. */ -      bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED); -       -      /* implicit withdraw, decrement aggregate and pcount here. -       * only if update is accepted, they'll increment below. -       */ -      bgp_aggregate_decrement (bgp, p, ri, afi, safi); -       -      /* Update bgp route dampening information.  */ -      if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) -	  && peer->sort == BGP_PEER_EBGP) -	{ -	  /* This is implicit withdraw so we should update dampening -	     information.  */ -	  if (! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) -	    bgp_damp_withdraw (ri, rn, afi, safi, 1);   -	} +		/* Received Logging. */ +		if (bgp_debug_update(peer, p, NULL, 1)) +			zlog_debug("%s rcvd %s", peer->host, +				   bgp_debug_rdpfxpath2str(prd, p, +							   addpath_id ? 1 : 0, +							   addpath_id, pfx_buf, +							   sizeof(pfx_buf))); + +		/* graceful restart STALE flag unset. */ +		if (CHECK_FLAG(ri->flags, BGP_INFO_STALE)) +			bgp_info_unset_flag(rn, ri, BGP_INFO_STALE); + +		/* The attribute is changed. */ +		bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED); + +		/* implicit withdraw, decrement aggregate and pcount here. +		 * only if update is accepted, they'll increment below. +		 */ +		bgp_aggregate_decrement(bgp, p, ri, afi, safi); + +		/* Update bgp route dampening information.  */ +		if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) +		    && peer->sort == BGP_PEER_EBGP) { +			/* This is implicit withdraw so we should update +			   dampening +			   information.  */ +			if (!CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)) +				bgp_damp_withdraw(ri, rn, afi, safi, 1); +		}  #if ENABLE_BGP_VNC -    if (safi == SAFI_MPLS_VPN) { -	struct bgp_node		*prn = NULL; -	struct bgp_table	*table = NULL; - -	prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *) prd); -	if (prn->info) { -	    table = (struct bgp_table *)(prn->info); - -	    vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( -		bgp, -		prd, -		table, -		p, -		ri); -	} -	bgp_unlock_node(prn); -    } -    if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) { -        if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) { -	    /* -	     * Implicit withdraw case. -	     */ -	    ++vnc_implicit_withdraw; -	    vnc_import_bgp_del_route(bgp, p, ri); -	    vnc_import_bgp_exterior_del_route(bgp, p, ri); -	} -    } +		if (safi == SAFI_MPLS_VPN) { +			struct bgp_node *prn = NULL; +			struct bgp_table *table = NULL; + +			prn = bgp_node_get(bgp->rib[afi][safi], +					   (struct prefix *)prd); +			if (prn->info) { +				table = (struct bgp_table *)(prn->info); + +				vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( +					bgp, prd, table, p, ri); +			} +			bgp_unlock_node(prn); +		} +		if ((afi == AFI_IP || afi == AFI_IP6) +		    && (safi == SAFI_UNICAST)) { +			if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) { +				/* +				 * Implicit withdraw case. +				 */ +				++vnc_implicit_withdraw; +				vnc_import_bgp_del_route(bgp, p, ri); +				vnc_import_bgp_exterior_del_route(bgp, p, ri); +			} +		}  #endif -	 -      /* Update to new attribute.  */ -      bgp_attr_unintern (&ri->attr); -      ri->attr = attr_new; -      /* Update MPLS tag.  */ -      if (safi == SAFI_MPLS_VPN || safi == SAFI_EVPN) -        memcpy ((bgp_info_extra_get (ri))->tag, tag, 3); +		/* Update to new attribute.  */ +		bgp_attr_unintern(&ri->attr); +		ri->attr = attr_new; + +		/* Update MPLS tag.  */ +		if (safi == SAFI_MPLS_VPN || safi == SAFI_EVPN) +			memcpy((bgp_info_extra_get(ri))->tag, tag, 3);  #if ENABLE_BGP_VNC -      if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST))  -        { -          if (vnc_implicit_withdraw)  -            { -              /* -               * Add back the route with its new attributes (e.g., nexthop). -               * The route is still selected, until the route selection -               * queued by bgp_process actually runs. We have to make this -               * update to the VNC side immediately to avoid racing against -               * configuration changes (e.g., route-map changes) which -               * trigger re-importation of the entire RIB. -               */ -              vnc_import_bgp_add_route(bgp, p, ri); -              vnc_import_bgp_exterior_add_route(bgp, p, ri); -            } -        } +		if ((afi == AFI_IP || afi == AFI_IP6) +		    && (safi == SAFI_UNICAST)) { +			if (vnc_implicit_withdraw) { +				/* +				 * Add back the route with its new attributes +				 * (e.g., nexthop). +				 * The route is still selected, until the route +				 * selection +				 * queued by bgp_process actually runs. We have +				 * to make this +				 * update to the VNC side immediately to avoid +				 * racing against +				 * configuration changes (e.g., route-map +				 * changes) which +				 * trigger re-importation of the entire RIB. +				 */ +				vnc_import_bgp_add_route(bgp, p, ri); +				vnc_import_bgp_exterior_add_route(bgp, p, ri); +			} +		}  #endif -      /* Update Overlay Index */ -      if(afi == AFI_L2VPN) -        { -          overlay_index_update(ri->attr, evpn==NULL?NULL:&evpn->eth_s_id, -                               evpn==NULL?NULL:&evpn->gw_ip); -        } - -      /* Update bgp route dampening information.  */ -      if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) -	  && peer->sort == BGP_PEER_EBGP) -	{ -	  /* Now we do normal update dampening.  */ -	  ret = bgp_damp_update (ri, rn, afi, safi); -	  if (ret == BGP_DAMP_SUPPRESSED) -	    { -	      bgp_unlock_node (rn); -	      return 0; -	    } -	} - -      /* Nexthop reachability check. */ -      if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST) -	{ -	  if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 && -	      ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) -	      && ! bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) -	    connected = 1; -	  else -	    connected = 0; - -	  if (bgp_find_or_add_nexthop (bgp, afi, ri, NULL, connected)) -	    bgp_info_set_flag (rn, ri, BGP_INFO_VALID); -	  else -	    { -	      if (BGP_DEBUG(nht, NHT)) -		{ -		  char buf1[INET6_ADDRSTRLEN]; -		  inet_ntop(AF_INET, (const void *)&attr_new->nexthop, buf1, INET6_ADDRSTRLEN); -		  zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1); +		/* Update Overlay Index */ +		if (afi == AFI_L2VPN) { +			overlay_index_update( +				ri->attr, evpn == NULL ? NULL : &evpn->eth_s_id, +				evpn == NULL ? NULL : &evpn->gw_ip);  		} -	      bgp_info_unset_flag (rn, ri, BGP_INFO_VALID); -	    } -	} -      else -	bgp_info_set_flag (rn, ri, BGP_INFO_VALID); + +		/* Update bgp route dampening information.  */ +		if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) +		    && peer->sort == BGP_PEER_EBGP) { +			/* Now we do normal update dampening.  */ +			ret = bgp_damp_update(ri, rn, afi, safi); +			if (ret == BGP_DAMP_SUPPRESSED) { +				bgp_unlock_node(rn); +				return 0; +			} +		} + +		/* Nexthop reachability check. */ +		if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST) { +			if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 +			    && !CHECK_FLAG(peer->flags, +					   PEER_FLAG_DISABLE_CONNECTED_CHECK) +			    && !bgp_flag_check( +				       bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) +				connected = 1; +			else +				connected = 0; + +			if (bgp_find_or_add_nexthop(bgp, afi, ri, NULL, +						    connected)) +				bgp_info_set_flag(rn, ri, BGP_INFO_VALID); +			else { +				if (BGP_DEBUG(nht, NHT)) { +					char buf1[INET6_ADDRSTRLEN]; +					inet_ntop(AF_INET, +						  (const void *)&attr_new +							  ->nexthop, +						  buf1, INET6_ADDRSTRLEN); +					zlog_debug("%s(%s): NH unresolved", +						   __FUNCTION__, buf1); +				} +				bgp_info_unset_flag(rn, ri, BGP_INFO_VALID); +			} +		} else +			bgp_info_set_flag(rn, ri, BGP_INFO_VALID);  #if ENABLE_BGP_VNC -      if (safi == SAFI_MPLS_VPN)  -        { -          struct bgp_node		*prn = NULL; -          struct bgp_table	*table = NULL; - -          prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *) prd); -          if (prn->info)  -            { -              table = (struct bgp_table *)(prn->info); - -              vnc_import_bgp_add_vnc_host_route_mode_resolve_nve( -		bgp, -                    prd, -                    table, -                    p, -                    ri); -            } -          bgp_unlock_node(prn); -        } +		if (safi == SAFI_MPLS_VPN) { +			struct bgp_node *prn = NULL; +			struct bgp_table *table = NULL; + +			prn = bgp_node_get(bgp->rib[afi][safi], +					   (struct prefix *)prd); +			if (prn->info) { +				table = (struct bgp_table *)(prn->info); + +				vnc_import_bgp_add_vnc_host_route_mode_resolve_nve( +					bgp, prd, table, p, ri); +			} +			bgp_unlock_node(prn); +		}  #endif -      /* Process change. */ -      bgp_aggregate_increment (bgp, p, ri, afi, safi); +		/* Process change. */ +		bgp_aggregate_increment(bgp, p, ri, afi, safi); -      bgp_process (bgp, rn, afi, safi); -      bgp_unlock_node (rn); +		bgp_process(bgp, rn, afi, safi); +		bgp_unlock_node(rn);  #if ENABLE_BGP_VNC -  if (SAFI_MPLS_VPN == safi) -    { -      uint32_t    label = decode_label(tag); +		if (SAFI_MPLS_VPN == safi) { +			uint32_t label = decode_label(tag); -      rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type, sub_type, -        &label); -    } -  if (SAFI_ENCAP == safi) -    { -      rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type, sub_type, -        NULL); -    } +			rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, +					   type, sub_type, &label); +		} +		if (SAFI_ENCAP == safi) { +			rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, +					   type, sub_type, NULL); +		}  #endif -      return 0; -    } // End of implicit withdraw +		return 0; +	} // End of implicit withdraw -  /* Received Logging. */ -  if (bgp_debug_update(peer, p, NULL, 1)) -    { -      if (!peer->rcvd_attr_printed) -        { -          zlog_debug ("%s rcvd UPDATE w/ attr: %s", peer->host, peer->rcvd_attr_str); -          peer->rcvd_attr_printed = 1; -        } - -      zlog_debug ("%s rcvd %s", peer->host, -                  bgp_debug_rdpfxpath2str (prd, p, addpath_id ? 1 : 0, -                                 addpath_id, pfx_buf, sizeof (pfx_buf))); -    } +	/* Received Logging. */ +	if (bgp_debug_update(peer, p, NULL, 1)) { +		if (!peer->rcvd_attr_printed) { +			zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host, +				   peer->rcvd_attr_str); +			peer->rcvd_attr_printed = 1; +		} -  /* Make new BGP info. */ -  new = info_make(type, sub_type, 0, peer, attr_new, rn); +		zlog_debug("%s rcvd %s", peer->host, +			   bgp_debug_rdpfxpath2str(prd, p, addpath_id ? 1 : 0, +						   addpath_id, pfx_buf, +						   sizeof(pfx_buf))); +	} -  /* Update MPLS tag. */ -  if (safi == SAFI_MPLS_VPN || safi == SAFI_EVPN) -    memcpy ((bgp_info_extra_get (new))->tag, tag, 3); +	/* Make new BGP info. */ +	new = info_make(type, sub_type, 0, peer, attr_new, rn); -  /* Update Overlay Index */ -  if(afi == AFI_L2VPN) -    { -      overlay_index_update(new->attr, evpn==NULL?NULL:&evpn->eth_s_id, -                           evpn==NULL?NULL:&evpn->gw_ip); -    } -  /* Nexthop reachability check. */ -  if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST) -    { -      if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 && -	  ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) -	  && ! bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) -	connected = 1; -      else -	connected = 0; - -      if (bgp_find_or_add_nexthop (bgp, afi, new, NULL, connected)) -	bgp_info_set_flag (rn, new, BGP_INFO_VALID); -      else -	{ -	  if (BGP_DEBUG(nht, NHT)) -	    { -	      char buf1[INET6_ADDRSTRLEN]; -	      inet_ntop(AF_INET, (const void *)&attr_new->nexthop, buf1, INET6_ADDRSTRLEN); -	      zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1); -	    } -	  bgp_info_unset_flag (rn, new, BGP_INFO_VALID); +	/* Update MPLS tag. */ +	if (safi == SAFI_MPLS_VPN || safi == SAFI_EVPN) +		memcpy((bgp_info_extra_get(new))->tag, tag, 3); + +	/* Update Overlay Index */ +	if (afi == AFI_L2VPN) { +		overlay_index_update(new->attr, +				     evpn == NULL ? NULL : &evpn->eth_s_id, +				     evpn == NULL ? NULL : &evpn->gw_ip);  	} -    } -  else -    bgp_info_set_flag (rn, new, BGP_INFO_VALID); +	/* Nexthop reachability check. */ +	if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST) { +		if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 +		    && !CHECK_FLAG(peer->flags, +				   PEER_FLAG_DISABLE_CONNECTED_CHECK) +		    && !bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) +			connected = 1; +		else +			connected = 0; + +		if (bgp_find_or_add_nexthop(bgp, afi, new, NULL, connected)) +			bgp_info_set_flag(rn, new, BGP_INFO_VALID); +		else { +			if (BGP_DEBUG(nht, NHT)) { +				char buf1[INET6_ADDRSTRLEN]; +				inet_ntop(AF_INET, +					  (const void *)&attr_new->nexthop, +					  buf1, INET6_ADDRSTRLEN); +				zlog_debug("%s(%s): NH unresolved", +					   __FUNCTION__, buf1); +			} +			bgp_info_unset_flag(rn, new, BGP_INFO_VALID); +		} +	} else +		bgp_info_set_flag(rn, new, BGP_INFO_VALID); -  /* Addpath ID */ -  new->addpath_rx_id = addpath_id; +	/* Addpath ID */ +	new->addpath_rx_id = addpath_id; -  /* Increment prefix */ -  bgp_aggregate_increment (bgp, p, new, afi, safi); -   -  /* Register new BGP information. */ -  bgp_info_add (rn, new); -   -  /* route_node_get lock */ -  bgp_unlock_node (rn); +	/* Increment prefix */ +	bgp_aggregate_increment(bgp, p, new, afi, safi); + +	/* Register new BGP information. */ +	bgp_info_add(rn, new); + +	/* route_node_get lock */ +	bgp_unlock_node(rn);  #if ENABLE_BGP_VNC -  if (safi == SAFI_MPLS_VPN)  -    { -      struct bgp_node		*prn = NULL; -      struct bgp_table	*table = NULL; -     -      prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *) prd); -      if (prn->info)  -        { -          table = (struct bgp_table *)(prn->info); -       -          vnc_import_bgp_add_vnc_host_route_mode_resolve_nve( -                             bgp, -                             prd, -                             table, -                             p, -                             new); -        } -      bgp_unlock_node(prn); -    } +	if (safi == SAFI_MPLS_VPN) { +		struct bgp_node *prn = NULL; +		struct bgp_table *table = NULL; + +		prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd); +		if (prn->info) { +			table = (struct bgp_table *)(prn->info); + +			vnc_import_bgp_add_vnc_host_route_mode_resolve_nve( +				bgp, prd, table, p, new); +		} +		bgp_unlock_node(prn); +	}  #endif -  /* If maximum prefix count is configured and current prefix -     count exeed it. */ -  if (bgp_maximum_prefix_overflow (peer, afi, safi, 0)) -    return -1; +	/* If maximum prefix count is configured and current prefix +	   count exeed it. */ +	if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) +		return -1; -  /* Process change. */ -  bgp_process (bgp, rn, afi, safi); +	/* Process change. */ +	bgp_process(bgp, rn, afi, safi);  #if ENABLE_BGP_VNC -  if (SAFI_MPLS_VPN == safi) -    { -      uint32_t    label = decode_label(tag); +	if (SAFI_MPLS_VPN == safi) { +		uint32_t label = decode_label(tag); -      rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type, sub_type, -        &label); -    } -  if (SAFI_ENCAP == safi) -    { -      rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type, sub_type, -        NULL); -    } +		rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type, +				   sub_type, &label); +	} +	if (SAFI_ENCAP == safi) { +		rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type, +				   sub_type, NULL); +	}  #endif -  return 0; +	return 0; -  /* This BGP update is filtered.  Log the reason then update BGP -     entry.  */ - filtered: -  if (bgp_debug_update(peer, p, NULL, 1)) -    { -      if (!peer->rcvd_attr_printed) -        { -          zlog_debug ("%s rcvd UPDATE w/ attr: %s", peer->host, peer->rcvd_attr_str); -          peer->rcvd_attr_printed = 1; -        } - -      zlog_debug ("%s rcvd UPDATE about %s -- DENIED due to: %s", -                  peer->host, -                  bgp_debug_rdpfxpath2str (prd, p, addpath_id ? 1 : 0, -                             addpath_id, pfx_buf, sizeof (pfx_buf)), reason); -    } +/* This BGP update is filtered.  Log the reason then update BGP +   entry.  */ +filtered: +	if (bgp_debug_update(peer, p, NULL, 1)) { +		if (!peer->rcvd_attr_printed) { +			zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host, +				   peer->rcvd_attr_str); +			peer->rcvd_attr_printed = 1; +		} -  if (ri) -    bgp_rib_remove (rn, ri, peer, afi, safi); +		zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s", +			   peer->host, +			   bgp_debug_rdpfxpath2str(prd, p, addpath_id ? 1 : 0, +						   addpath_id, pfx_buf, +						   sizeof(pfx_buf)), +			   reason); +	} + +	if (ri) +		bgp_rib_remove(rn, ri, peer, afi, safi); -  bgp_unlock_node (rn); +	bgp_unlock_node(rn);  #if ENABLE_BGP_VNC -  /* -   * Filtered update is treated as an implicit withdrawal (see bgp_rib_remove() -   * a few lines above) -   */ -  if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) -    { -      rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type, 0); -    } +	/* +	 * Filtered update is treated as an implicit withdrawal (see +	 * bgp_rib_remove() +	 * a few lines above) +	 */ +	if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) { +		rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type, +				     0); +	}  #endif -  return 0; +	return 0;  } -int -bgp_withdraw (struct peer *peer, struct prefix *p, u_int32_t addpath_id, -              struct attr *attr, afi_t afi, safi_t safi, int type, int sub_type, -	      struct prefix_rd *prd, u_char *tag, struct bgp_route_evpn *evpn) +int bgp_withdraw(struct peer *peer, struct prefix *p, u_int32_t addpath_id, +		 struct attr *attr, afi_t afi, safi_t safi, int type, +		 int sub_type, struct prefix_rd *prd, u_char *tag, +		 struct bgp_route_evpn *evpn)  { -  struct bgp *bgp; -  char pfx_buf[BGP_PRD_PATH_STRLEN]; -  struct bgp_node *rn; -  struct bgp_info *ri; +	struct bgp *bgp; +	char pfx_buf[BGP_PRD_PATH_STRLEN]; +	struct bgp_node *rn; +	struct bgp_info *ri;  #if ENABLE_BGP_VNC -  if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) -    { -      rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type, 0); -    } +	if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) { +		rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type, +				     0); +	}  #endif -  bgp = peer->bgp; - -  /* Lookup node. */ -  rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd); - -  /* If peer is soft reconfiguration enabled.  Record input packet for -   * further calculation. -   * -   * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all -   * routes that are filtered.  This tanks out Quagga RS pretty badly due to -   * the iteration over all RS clients. -   * Since we need to remove the entry from adj_in anyway, do that first and -   * if there was no entry, we don't need to do anything more. -   */ -  if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) -      && peer != bgp->peer_self) -    if (!bgp_adj_in_unset (rn, peer, addpath_id)) -      { -        if (bgp_debug_update (peer, p, NULL, 1)) -          zlog_debug ("%s withdrawing route %s not in adj-in", -                      peer->host, -                      bgp_debug_rdpfxpath2str (prd, p, addpath_id ? 1 : 0, -                                       addpath_id, pfx_buf, sizeof (pfx_buf))); -        bgp_unlock_node (rn); -        return 0; -      } - -  /* Lookup withdrawn route. */ -  for (ri = rn->info; ri; ri = ri->next) -    if (ri->peer == peer && ri->type == type && ri->sub_type == sub_type && -        ri->addpath_rx_id == addpath_id) -      break; - -  /* Logging. */ -  if (bgp_debug_update(peer, p, NULL, 1)) -    { -      zlog_debug ("%s rcvd UPDATE about %s -- withdrawn", -                  peer->host, -                  bgp_debug_rdpfxpath2str (prd, p, addpath_id ? 1 : 0, -                                   addpath_id, pfx_buf, sizeof (pfx_buf))); -    } +	bgp = peer->bgp; + +	/* Lookup node. */ +	rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd); + +	/* If peer is soft reconfiguration enabled.  Record input packet for +	 * further calculation. +	 * +	 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all +	 * routes that are filtered.  This tanks out Quagga RS pretty badly due +	 * to +	 * the iteration over all RS clients. +	 * Since we need to remove the entry from adj_in anyway, do that first +	 * and +	 * if there was no entry, we don't need to do anything more. +	 */ +	if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) +	    && peer != bgp->peer_self) +		if (!bgp_adj_in_unset(rn, peer, addpath_id)) { +			if (bgp_debug_update(peer, p, NULL, 1)) +				zlog_debug( +					"%s withdrawing route %s not in adj-in", +					peer->host, +					bgp_debug_rdpfxpath2str( +						prd, p, addpath_id ? 1 : 0, +						addpath_id, pfx_buf, +						sizeof(pfx_buf))); +			bgp_unlock_node(rn); +			return 0; +		} -  /* Withdraw specified route from routing table. */ -  if (ri && ! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) -    bgp_rib_withdraw (rn, ri, peer, afi, safi, prd); -  else if (bgp_debug_update(peer, p, NULL, 1)) -    zlog_debug ("%s Can't find the route %s", -                peer->host, -                bgp_debug_rdpfxpath2str (prd, p, addpath_id ? 1 : 0, -                                    addpath_id, pfx_buf, sizeof (pfx_buf))); +	/* Lookup withdrawn route. */ +	for (ri = rn->info; ri; ri = ri->next) +		if (ri->peer == peer && ri->type == type +		    && ri->sub_type == sub_type +		    && ri->addpath_rx_id == addpath_id) +			break; + +	/* Logging. */ +	if (bgp_debug_update(peer, p, NULL, 1)) { +		zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host, +			   bgp_debug_rdpfxpath2str(prd, p, addpath_id ? 1 : 0, +						   addpath_id, pfx_buf, +						   sizeof(pfx_buf))); +	} + +	/* Withdraw specified route from routing table. */ +	if (ri && !CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)) +		bgp_rib_withdraw(rn, ri, peer, afi, safi, prd); +	else if (bgp_debug_update(peer, p, NULL, 1)) +		zlog_debug("%s Can't find the route %s", peer->host, +			   bgp_debug_rdpfxpath2str(prd, p, addpath_id ? 1 : 0, +						   addpath_id, pfx_buf, +						   sizeof(pfx_buf))); -  /* Unlock bgp_node_get() lock. */ -  bgp_unlock_node (rn); +	/* Unlock bgp_node_get() lock. */ +	bgp_unlock_node(rn); -  return 0; +	return 0;  } -void -bgp_default_originate (struct peer *peer, afi_t afi, safi_t safi, int withdraw) +void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi, +			   int withdraw)  { -  struct update_subgroup *subgrp; -  subgrp = peer_subgroup(peer, afi, safi); -  subgroup_default_originate(subgrp, withdraw); +	struct update_subgroup *subgrp; +	subgrp = peer_subgroup(peer, afi, safi); +	subgroup_default_originate(subgrp, withdraw);  }  /*   * bgp_stop_announce_route_timer   */ -void -bgp_stop_announce_route_timer (struct peer_af *paf) +void bgp_stop_announce_route_timer(struct peer_af *paf)  { -  if (!paf->t_announce_route) -    return; -  -  THREAD_TIMER_OFF (paf->t_announce_route); +	if (!paf->t_announce_route) +		return; + +	THREAD_TIMER_OFF(paf->t_announce_route);  }  /* @@ -2998,26 +3002,25 @@ bgp_stop_announce_route_timer (struct peer_af *paf)   * Callback that is invoked when the route announcement timer for a   * peer_af expires.   */ -static int -bgp_announce_route_timer_expired (struct thread *t) +static int bgp_announce_route_timer_expired(struct thread *t)  { -  struct peer_af *paf; -  struct peer *peer; +	struct peer_af *paf; +	struct peer *peer; -  paf = THREAD_ARG (t); -  peer = paf->peer; +	paf = THREAD_ARG(t); +	peer = paf->peer; -  assert (paf->t_announce_route); -  paf->t_announce_route = NULL; +	assert(paf->t_announce_route); +	paf->t_announce_route = NULL; -  if (peer->status != Established) -    return 0; +	if (peer->status != Established) +		return 0; -  if (!peer->afc_nego[paf->afi][paf->safi]) -    return 0; +	if (!peer->afc_nego[paf->afi][paf->safi]) +		return 0; -  peer_af_announce_route (paf, 1); -  return 0; +	peer_af_announce_route(paf, 1); +	return 0;  }  /* @@ -3025,35 +3028,34 @@ bgp_announce_route_timer_expired (struct thread *t)   *   * *Triggers* announcement of routes of a given AFI/SAFI to a peer.   */ -void -bgp_announce_route (struct peer *peer, afi_t afi, safi_t safi) -{ -  struct peer_af *paf; -  struct update_subgroup *subgrp; - -  paf = peer_af_find (peer, afi, safi); -  if (!paf) -    return; -  subgrp = PAF_SUBGRP(paf); - -  /* -   * Ignore if subgroup doesn't exist (implies AF is not negotiated) -   * or a refresh has already been triggered. -   */ -  if (!subgrp || paf->t_announce_route) -    return; - -  /* -   * Start a timer to stagger/delay the announce. This serves -   * two purposes - announcement can potentially be combined for -   * multiple peers and the announcement doesn't happen in the -   * vty context. -   */ -  THREAD_TIMER_MSEC_ON (bm->master, paf->t_announce_route, -			bgp_announce_route_timer_expired, paf, -                        (subgrp->peer_count == 1) ? -			BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS : -			BGP_ANNOUNCE_ROUTE_DELAY_MS); +void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi) +{ +	struct peer_af *paf; +	struct update_subgroup *subgrp; + +	paf = peer_af_find(peer, afi, safi); +	if (!paf) +		return; +	subgrp = PAF_SUBGRP(paf); + +	/* +	 * Ignore if subgroup doesn't exist (implies AF is not negotiated) +	 * or a refresh has already been triggered. +	 */ +	if (!subgrp || paf->t_announce_route) +		return; + +	/* +	 * Start a timer to stagger/delay the announce. This serves +	 * two purposes - announcement can potentially be combined for +	 * multiple peers and the announcement doesn't happen in the +	 * vty context. +	 */ +	THREAD_TIMER_MSEC_ON(bm->master, paf->t_announce_route, +			     bgp_announce_route_timer_expired, paf, +			     (subgrp->peer_count == 1) +				     ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS +				     : BGP_ANNOUNCE_ROUTE_DELAY_MS);  }  /* @@ -3065,1385 +3067,1345 @@ bgp_announce_route (struct peer *peer, afi_t afi, safi_t safi)   * The operation will result in splitting the peer from its existing   * subgroups and putting it in new subgroups.   */ -void -bgp_announce_route_all (struct peer *peer) +void bgp_announce_route_all(struct peer *peer)  { -  afi_t afi; -  safi_t safi; -   -  for (afi = AFI_IP; afi < AFI_MAX; afi++) -    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) -      bgp_announce_route (peer, afi, safi); +	afi_t afi; +	safi_t safi; + +	for (afi = AFI_IP; afi < AFI_MAX; afi++) +		for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) +			bgp_announce_route(peer, afi, safi);  } -static void -bgp_soft_reconfig_table (struct peer *peer, afi_t afi, safi_t safi, -			 struct bgp_table *table, struct prefix_rd *prd) +static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi, +				    struct bgp_table *table, +				    struct prefix_rd *prd)  { -  int ret; -  struct bgp_node *rn; -  struct bgp_adj_in *ain; +	int ret; +	struct bgp_node *rn; +	struct bgp_adj_in *ain; -  if (! table) -    table = peer->bgp->rib[afi][safi]; +	if (!table) +		table = peer->bgp->rib[afi][safi]; -  for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) -    for (ain = rn->adj_in; ain; ain = ain->next) -      { -	if (ain->peer == peer) -	  { -	    struct bgp_info *ri = rn->info; -	    u_char *tag = (ri && ri->extra) ? ri->extra->tag : NULL; +	for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) +		for (ain = rn->adj_in; ain; ain = ain->next) { +			if (ain->peer == peer) { +				struct bgp_info *ri = rn->info; +				u_char *tag = (ri && ri->extra) ? ri->extra->tag +								: NULL; -	    ret = bgp_update (peer, &rn->p, ain->addpath_rx_id, ain->attr, -                              afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, -			      prd, tag, 1, NULL); +				ret = bgp_update( +					peer, &rn->p, ain->addpath_rx_id, +					ain->attr, afi, safi, ZEBRA_ROUTE_BGP, +					BGP_ROUTE_NORMAL, prd, tag, 1, NULL); -	    if (ret < 0) -	      { -		bgp_unlock_node (rn); -		return; -	      } -	  } -      } +				if (ret < 0) { +					bgp_unlock_node(rn); +					return; +				} +			} +		}  } -void -bgp_soft_reconfig_in (struct peer *peer, afi_t afi, safi_t safi) +void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)  { -  struct bgp_node *rn; -  struct bgp_table *table; +	struct bgp_node *rn; +	struct bgp_table *table; -  if (peer->status != Established) -    return; +	if (peer->status != Established) +		return; -  if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP) && (safi != SAFI_EVPN)) -    bgp_soft_reconfig_table (peer, afi, safi, NULL, NULL); -  else -    for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn; -	 rn = bgp_route_next (rn)) -      if ((table = rn->info) != NULL) -        { -          struct prefix_rd prd; -          prd.family = AF_UNSPEC; -          prd.prefixlen = 64; -          memcpy(&prd.val, rn->p.u.val, 8); +	if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP) +	    && (safi != SAFI_EVPN)) +		bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL); +	else +		for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn; +		     rn = bgp_route_next(rn)) +			if ((table = rn->info) != NULL) { +				struct prefix_rd prd; +				prd.family = AF_UNSPEC; +				prd.prefixlen = 64; +				memcpy(&prd.val, rn->p.u.val, 8); -          bgp_soft_reconfig_table (peer, afi, safi, table, &prd); -        } +				bgp_soft_reconfig_table(peer, afi, safi, table, +							&prd); +			}  } -struct bgp_clear_node_queue -{ -  struct bgp_node *rn; +struct bgp_clear_node_queue { +	struct bgp_node *rn;  }; -static wq_item_status -bgp_clear_route_node (struct work_queue *wq, void *data) +static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)  { -  struct bgp_clear_node_queue *cnq = data; -  struct bgp_node *rn = cnq->rn; -  struct peer *peer = wq->spec.data; -  struct bgp_info *ri; -  afi_t afi = bgp_node_table (rn)->afi; -  safi_t safi = bgp_node_table (rn)->safi; -   -  assert (rn && peer); -   -  /* It is possible that we have multiple paths for a prefix from a peer -   * if that peer is using AddPath. -   */ -  for (ri = rn->info; ri; ri = ri->next) -    if (ri->peer == peer) -      { -        /* graceful restart STALE flag set. */ -        if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT) -            && peer->nsf[afi][safi] -            && ! CHECK_FLAG (ri->flags, BGP_INFO_STALE) -            && ! CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE)) -          bgp_info_set_flag (rn, ri, BGP_INFO_STALE); -        else -          bgp_rib_remove (rn, ri, peer, afi, safi); -      } -  return WQ_SUCCESS; -} - -static void -bgp_clear_node_queue_del (struct work_queue *wq, void *data) -{ -  struct bgp_clear_node_queue *cnq = data; -  struct bgp_node *rn = cnq->rn; -  struct bgp_table *table = bgp_node_table (rn); -   -  bgp_unlock_node (rn);  -  bgp_table_unlock (table); -  XFREE (MTYPE_BGP_CLEAR_NODE_QUEUE, cnq); +	struct bgp_clear_node_queue *cnq = data; +	struct bgp_node *rn = cnq->rn; +	struct peer *peer = wq->spec.data; +	struct bgp_info *ri; +	afi_t afi = bgp_node_table(rn)->afi; +	safi_t safi = bgp_node_table(rn)->safi; + +	assert(rn && peer); + +	/* It is possible that we have multiple paths for a prefix from a peer +	 * if that peer is using AddPath. +	 */ +	for (ri = rn->info; ri; ri = ri->next) +		if (ri->peer == peer) { +			/* graceful restart STALE flag set. */ +			if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT) +			    && peer->nsf[afi][safi] +			    && !CHECK_FLAG(ri->flags, BGP_INFO_STALE) +			    && !CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE)) +				bgp_info_set_flag(rn, ri, BGP_INFO_STALE); +			else +				bgp_rib_remove(rn, ri, peer, afi, safi); +		} +	return WQ_SUCCESS;  } -static void -bgp_clear_node_complete (struct work_queue *wq) +static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)  { -  struct peer *peer = wq->spec.data; -   -  /* Tickle FSM to start moving again */ -  BGP_EVENT_ADD (peer, Clearing_Completed); +	struct bgp_clear_node_queue *cnq = data; +	struct bgp_node *rn = cnq->rn; +	struct bgp_table *table = bgp_node_table(rn); -  peer_unlock (peer); /* bgp_clear_route */ +	bgp_unlock_node(rn); +	bgp_table_unlock(table); +	XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);  } -static void -bgp_clear_node_queue_init (struct peer *peer) +static void bgp_clear_node_complete(struct work_queue *wq)  { -  char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")]; -   -  snprintf (wname, sizeof(wname), "clear %s", peer->host); -#undef CLEAR_QUEUE_NAME_LEN +	struct peer *peer = wq->spec.data; -  if ( (peer->clear_node_queue = work_queue_new (bm->master, wname)) == NULL) -    { -      zlog_err ("%s: Failed to allocate work queue", __func__); -      exit (1); -    } -  peer->clear_node_queue->spec.hold = 10; -  peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node; -  peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del; -  peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete; -  peer->clear_node_queue->spec.max_retries = 0; -   -  /* we only 'lock' this peer reference when the queue is actually active */ -  peer->clear_node_queue->spec.data = peer; +	/* Tickle FSM to start moving again */ +	BGP_EVENT_ADD(peer, Clearing_Completed); + +	peer_unlock(peer); /* bgp_clear_route */  } -static void -bgp_clear_route_table (struct peer *peer, afi_t afi, safi_t safi, -                       struct bgp_table *table) +static void bgp_clear_node_queue_init(struct peer *peer)  { -  struct bgp_node *rn; -  int force = bm->process_main_queue ? 0 : 1; -   -  if (! table) -    table = peer->bgp->rib[afi][safi]; -   -  /* If still no table => afi/safi isn't configured at all or smth. */ -  if (! table) -    return; -   -  for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) -    { -      struct bgp_info *ri, *next; -      struct bgp_adj_in *ain; -      struct bgp_adj_in *ain_next; - -      /* XXX:TODO: This is suboptimal, every non-empty route_node is -       * queued for every clearing peer, regardless of whether it is -       * relevant to the peer at hand. -       * -       * Overview: There are 3 different indices which need to be -       * scrubbed, potentially, when a peer is removed: -       * -       * 1 peer's routes visible via the RIB (ie accepted routes) -       * 2 peer's routes visible by the (optional) peer's adj-in index -       * 3 other routes visible by the peer's adj-out index -       * -       * 3 there is no hurry in scrubbing, once the struct peer is -       * removed from bgp->peer, we could just GC such deleted peer's -       * adj-outs at our leisure. -       * -       * 1 and 2 must be 'scrubbed' in some way, at least made -       * invisible via RIB index before peer session is allowed to be -       * brought back up. So one needs to know when such a 'search' is -       * complete. -       * -       * Ideally: -       * -       * - there'd be a single global queue or a single RIB walker -       * - rather than tracking which route_nodes still need to be -       *   examined on a peer basis, we'd track which peers still -       *   aren't cleared -       * -       * Given that our per-peer prefix-counts now should be reliable, -       * this may actually be achievable. It doesn't seem to be a huge -       * problem at this time, -       * -       * It is possible that we have multiple paths for a prefix from a peer -       * if that peer is using AddPath. -       */ -      ain = rn->adj_in; -      while (ain) -        { -          ain_next = ain->next; - -          if (ain->peer == peer) -            { -              bgp_adj_in_remove (rn, ain); -              bgp_unlock_node (rn); -            } - -          ain = ain_next; -        } - -      for (ri = rn->info; ri; ri = next) -	{ -	  next = ri->next; -	  if (ri->peer != peer) -	    continue; - -	  if (force) -	    bgp_info_reap (rn, ri); -	  else -	    { -	      struct bgp_clear_node_queue *cnq; - -	      /* both unlocked in bgp_clear_node_queue_del */ -	      bgp_table_lock (bgp_node_table (rn)); -	      bgp_lock_node (rn); -	      cnq = XCALLOC (MTYPE_BGP_CLEAR_NODE_QUEUE, -			     sizeof (struct bgp_clear_node_queue)); -	      cnq->rn = rn; -	      work_queue_add (peer->clear_node_queue, cnq); -	      break; -	    } +	char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")]; + +	snprintf(wname, sizeof(wname), "clear %s", peer->host); +#undef CLEAR_QUEUE_NAME_LEN + +	if ((peer->clear_node_queue = work_queue_new(bm->master, wname)) +	    == NULL) { +		zlog_err("%s: Failed to allocate work queue", __func__); +		exit(1);  	} -    } -  return; +	peer->clear_node_queue->spec.hold = 10; +	peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node; +	peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del; +	peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete; +	peer->clear_node_queue->spec.max_retries = 0; + +	/* we only 'lock' this peer reference when the queue is actually active +	 */ +	peer->clear_node_queue->spec.data = peer;  } -void -bgp_clear_route (struct peer *peer, afi_t afi, safi_t safi) +static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi, +				  struct bgp_table *table)  { -  struct bgp_node *rn; -  struct bgp_table *table; +	struct bgp_node *rn; +	int force = bm->process_main_queue ? 0 : 1; -  if (peer->clear_node_queue == NULL) -    bgp_clear_node_queue_init (peer); -   -  /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to -   * Idle until it receives a Clearing_Completed event. This protects -   * against peers which flap faster than we can we clear, which could -   * lead to: -   * -   * a) race with routes from the new session being installed before -   *    clear_route_node visits the node (to delete the route of that -   *    peer) -   * b) resource exhaustion, clear_route_node likely leads to an entry -   *    on the process_main queue. Fast-flapping could cause that queue -   *    to grow and grow. -   */ - -  /* lock peer in assumption that clear-node-queue will get nodes; if so, -   * the unlock will happen upon work-queue completion; other wise, the -   * unlock happens at the end of this function. -   */ -  if (!peer->clear_node_queue->thread) -    peer_lock (peer); - -  if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN) -    bgp_clear_route_table (peer, afi, safi, NULL); -  else -    for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn; -         rn = bgp_route_next (rn)) -      if ((table = rn->info) != NULL) -        bgp_clear_route_table (peer, afi, safi, table); +	if (!table) +		table = peer->bgp->rib[afi][safi]; + +	/* If still no table => afi/safi isn't configured at all or smth. */ +	if (!table) +		return; -  /* unlock if no nodes got added to the clear-node-queue. */ -  if (!peer->clear_node_queue->thread) -    peer_unlock (peer); +	for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { +		struct bgp_info *ri, *next; +		struct bgp_adj_in *ain; +		struct bgp_adj_in *ain_next; + +		/* XXX:TODO: This is suboptimal, every non-empty route_node is +		 * queued for every clearing peer, regardless of whether it is +		 * relevant to the peer at hand. +		 * +		 * Overview: There are 3 different indices which need to be +		 * scrubbed, potentially, when a peer is removed: +		 * +		 * 1 peer's routes visible via the RIB (ie accepted routes) +		 * 2 peer's routes visible by the (optional) peer's adj-in index +		 * 3 other routes visible by the peer's adj-out index +		 * +		 * 3 there is no hurry in scrubbing, once the struct peer is +		 * removed from bgp->peer, we could just GC such deleted peer's +		 * adj-outs at our leisure. +		 * +		 * 1 and 2 must be 'scrubbed' in some way, at least made +		 * invisible via RIB index before peer session is allowed to be +		 * brought back up. So one needs to know when such a 'search' is +		 * complete. +		 * +		 * Ideally: +		 * +		 * - there'd be a single global queue or a single RIB walker +		 * - rather than tracking which route_nodes still need to be +		 *   examined on a peer basis, we'd track which peers still +		 *   aren't cleared +		 * +		 * Given that our per-peer prefix-counts now should be reliable, +		 * this may actually be achievable. It doesn't seem to be a huge +		 * problem at this time, +		 * +		 * It is possible that we have multiple paths for a prefix from +		 * a peer +		 * if that peer is using AddPath. +		 */ +		ain = rn->adj_in; +		while (ain) { +			ain_next = ain->next; + +			if (ain->peer == peer) { +				bgp_adj_in_remove(rn, ain); +				bgp_unlock_node(rn); +			} + +			ain = ain_next; +		} +		for (ri = rn->info; ri; ri = next) { +			next = ri->next; +			if (ri->peer != peer) +				continue; + +			if (force) +				bgp_info_reap(rn, ri); +			else { +				struct bgp_clear_node_queue *cnq; + +				/* both unlocked in bgp_clear_node_queue_del */ +				bgp_table_lock(bgp_node_table(rn)); +				bgp_lock_node(rn); +				cnq = XCALLOC( +					MTYPE_BGP_CLEAR_NODE_QUEUE, +					sizeof(struct bgp_clear_node_queue)); +				cnq->rn = rn; +				work_queue_add(peer->clear_node_queue, cnq); +				break; +			} +		} +	} +	return; +} + +void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi) +{ +	struct bgp_node *rn; +	struct bgp_table *table; + +	if (peer->clear_node_queue == NULL) +		bgp_clear_node_queue_init(peer); + +	/* bgp_fsm.c keeps sessions in state Clearing, not transitioning to +	 * Idle until it receives a Clearing_Completed event. This protects +	 * against peers which flap faster than we can we clear, which could +	 * lead to: +	 * +	 * a) race with routes from the new session being installed before +	 *    clear_route_node visits the node (to delete the route of that +	 *    peer) +	 * b) resource exhaustion, clear_route_node likely leads to an entry +	 *    on the process_main queue. Fast-flapping could cause that queue +	 *    to grow and grow. +	 */ + +	/* lock peer in assumption that clear-node-queue will get nodes; if so, +	 * the unlock will happen upon work-queue completion; other wise, the +	 * unlock happens at the end of this function. +	 */ +	if (!peer->clear_node_queue->thread) +		peer_lock(peer); + +	if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN) +		bgp_clear_route_table(peer, afi, safi, NULL); +	else +		for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn; +		     rn = bgp_route_next(rn)) +			if ((table = rn->info) != NULL) +				bgp_clear_route_table(peer, afi, safi, table); + +	/* unlock if no nodes got added to the clear-node-queue. */ +	if (!peer->clear_node_queue->thread) +		peer_unlock(peer);  } -   -void -bgp_clear_route_all (struct peer *peer) + +void bgp_clear_route_all(struct peer *peer)  { -  afi_t afi; -  safi_t safi; +	afi_t afi; +	safi_t safi; -  for (afi = AFI_IP; afi < AFI_MAX; afi++) -    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) -      bgp_clear_route (peer, afi, safi); +	for (afi = AFI_IP; afi < AFI_MAX; afi++) +		for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) +			bgp_clear_route(peer, afi, safi);  #if ENABLE_BGP_VNC -  rfapiProcessPeerDown(peer); +	rfapiProcessPeerDown(peer);  #endif  } -void -bgp_clear_adj_in (struct peer *peer, afi_t afi, safi_t safi) +void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)  { -  struct bgp_table *table; -  struct bgp_node *rn; -  struct bgp_adj_in *ain; -  struct bgp_adj_in *ain_next; +	struct bgp_table *table; +	struct bgp_node *rn; +	struct bgp_adj_in *ain; +	struct bgp_adj_in *ain_next; -  table = peer->bgp->rib[afi][safi]; +	table = peer->bgp->rib[afi][safi]; -  /* It is possible that we have multiple paths for a prefix from a peer -   * if that peer is using AddPath. -   */ -  for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) -    { -      ain = rn->adj_in; +	/* It is possible that we have multiple paths for a prefix from a peer +	 * if that peer is using AddPath. +	 */ +	for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { +		ain = rn->adj_in; -      while (ain) -        { -          ain_next = ain->next; +		while (ain) { +			ain_next = ain->next; -          if (ain->peer == peer) -            { -              bgp_adj_in_remove (rn, ain); -              bgp_unlock_node (rn); -	    } +			if (ain->peer == peer) { +				bgp_adj_in_remove(rn, ain); +				bgp_unlock_node(rn); +			} -          ain = ain_next; -        } -    } +			ain = ain_next; +		} +	}  } -void -bgp_clear_stale_route (struct peer *peer, afi_t afi, safi_t safi) -{ -  struct bgp_node *rn; -  struct bgp_info *ri; -  struct bgp_table *table; - -  if ( safi == SAFI_MPLS_VPN) -    { -      for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn; rn = bgp_route_next (rn)) -        { -          struct bgp_node *rm; -          struct bgp_info *ri; - -          /* look for neighbor in tables */ -          if ((table = rn->info) != NULL) -            { -              for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm)) -                for (ri = rm->info; ri; ri = ri->next) -                  if (ri->peer == peer) -                    { -                      if (CHECK_FLAG (ri->flags, BGP_INFO_STALE)) -                        bgp_rib_remove (rm, ri, peer, afi, safi); -                      break; -                    } -            } -        } -    } -  else -    { -      for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn; rn = bgp_route_next (rn)) -        for (ri = rn->info; ri; ri = ri->next) -          if (ri->peer == peer) -            { -              if (CHECK_FLAG (ri->flags, BGP_INFO_STALE)) -                bgp_rib_remove (rn, ri, peer, afi, safi); -              break; -            } -    } +void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi) +{ +	struct bgp_node *rn; +	struct bgp_info *ri; +	struct bgp_table *table; + +	if (safi == SAFI_MPLS_VPN) { +		for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn; +		     rn = bgp_route_next(rn)) { +			struct bgp_node *rm; +			struct bgp_info *ri; + +			/* look for neighbor in tables */ +			if ((table = rn->info) != NULL) { +				for (rm = bgp_table_top(table); rm; +				     rm = bgp_route_next(rm)) +					for (ri = rm->info; ri; ri = ri->next) +						if (ri->peer == peer) { +							if (CHECK_FLAG( +								    ri->flags, +								    BGP_INFO_STALE)) +								bgp_rib_remove( +									rm, ri, +									peer, +									afi, +									safi); +							break; +						} +			} +		} +	} else { +		for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn; +		     rn = bgp_route_next(rn)) +			for (ri = rn->info; ri; ri = ri->next) +				if (ri->peer == peer) { +					if (CHECK_FLAG(ri->flags, +						       BGP_INFO_STALE)) +						bgp_rib_remove(rn, ri, peer, +							       afi, safi); +					break; +				} +	}  } -static void -bgp_cleanup_table(struct bgp_table *table, safi_t safi) +static void bgp_cleanup_table(struct bgp_table *table, safi_t safi)  { -  struct bgp_node *rn; -  struct bgp_info *ri; -  struct bgp_info *next; +	struct bgp_node *rn; +	struct bgp_info *ri; +	struct bgp_info *next; -  for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) -    for (ri = rn->info; ri; ri = next) -      { -        next = ri->next; -        if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) -            && ri->type == ZEBRA_ROUTE_BGP -            && (ri->sub_type == BGP_ROUTE_NORMAL || -                ri->sub_type == BGP_ROUTE_AGGREGATE)) -          { +	for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) +		for (ri = rn->info; ri; ri = next) { +			next = ri->next; +			if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED) +			    && ri->type == ZEBRA_ROUTE_BGP +			    && (ri->sub_type == BGP_ROUTE_NORMAL +				|| ri->sub_type == BGP_ROUTE_AGGREGATE)) {  #if ENABLE_BGP_VNC -            if (table->owner && table->owner->bgp) -              vnc_import_bgp_del_route(table->owner->bgp, &rn->p, ri); +				if (table->owner && table->owner->bgp) +					vnc_import_bgp_del_route( +						table->owner->bgp, &rn->p, ri);  #endif -            bgp_zebra_withdraw (&rn->p, ri, safi); -            bgp_info_reap (rn, ri); -          } -      } +				bgp_zebra_withdraw(&rn->p, ri, safi); +				bgp_info_reap(rn, ri); +			} +		}  }  /* Delete all kernel routes. */ -void -bgp_cleanup_routes (struct bgp *bgp) -{ -  afi_t afi; -  struct bgp_node *rn; - -  for (afi = AFI_IP; afi < AFI_MAX; ++afi) -    { -      if (afi == AFI_L2VPN) -        continue; -      bgp_cleanup_table(bgp->rib[afi][SAFI_UNICAST], SAFI_UNICAST); -      /* -       * VPN and ENCAP and EVPN tables are two-level (RD is top level) -       */ -      if (afi != AFI_L2VPN) -        { -          safi_t safi; -          safi = SAFI_MPLS_VPN; -          for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; -               rn = bgp_route_next (rn)) -            { -              if (rn->info) -                { -                  bgp_cleanup_table((struct bgp_table *)(rn->info), safi); -                  bgp_table_finish ((struct bgp_table **)&(rn->info)); -                  rn->info = NULL; -                  bgp_unlock_node(rn); -                } -            } -          safi = SAFI_ENCAP; -          for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; -               rn = bgp_route_next (rn)) -            { -              if (rn->info) -                { -                  bgp_cleanup_table((struct bgp_table *)(rn->info), safi); -                  bgp_table_finish ((struct bgp_table **)&(rn->info)); -                  rn->info = NULL; -                  bgp_unlock_node(rn); -                } -            } +void bgp_cleanup_routes(struct bgp *bgp) +{ +	afi_t afi; +	struct bgp_node *rn; + +	for (afi = AFI_IP; afi < AFI_MAX; ++afi) { +		if (afi == AFI_L2VPN) +			continue; +		bgp_cleanup_table(bgp->rib[afi][SAFI_UNICAST], SAFI_UNICAST); +		/* +		 * VPN and ENCAP and EVPN tables are two-level (RD is top level) +		 */ +		if (afi != AFI_L2VPN) { +			safi_t safi; +			safi = SAFI_MPLS_VPN; +			for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; +			     rn = bgp_route_next(rn)) { +				if (rn->info) { +					bgp_cleanup_table( +						(struct bgp_table *)(rn->info), +						safi); +					bgp_table_finish((struct bgp_table **)&( +						rn->info)); +					rn->info = NULL; +					bgp_unlock_node(rn); +				} +			} +			safi = SAFI_ENCAP; +			for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; +			     rn = bgp_route_next(rn)) { +				if (rn->info) { +					bgp_cleanup_table( +						(struct bgp_table *)(rn->info), +						safi); +					bgp_table_finish((struct bgp_table **)&( +						rn->info)); +					rn->info = NULL; +					bgp_unlock_node(rn); +				} +			} +		} +	} +	for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn; +	     rn = bgp_route_next(rn)) { +		if (rn->info) { +			bgp_cleanup_table((struct bgp_table *)(rn->info), +					  SAFI_EVPN); +			bgp_table_finish((struct bgp_table **)&(rn->info)); +			rn->info = NULL; +			bgp_unlock_node(rn); +		}  	} -    } -  for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn; -       rn = bgp_route_next (rn)) -    { -      if (rn->info) -        { -          bgp_cleanup_table((struct bgp_table *)(rn->info), SAFI_EVPN); -          bgp_table_finish ((struct bgp_table **)&(rn->info)); -          rn->info = NULL; -          bgp_unlock_node(rn); -        } -    }  } -void -bgp_reset (void) +void bgp_reset(void)  { -  vty_reset (); -  bgp_zclient_reset (); -  access_list_reset (); -  prefix_list_reset (); +	vty_reset(); +	bgp_zclient_reset(); +	access_list_reset(); +	prefix_list_reset();  } -static int -bgp_addpath_encode_rx (struct peer *peer, afi_t afi, safi_t safi) +static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)  { -  return (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) && -          CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_RCV)); +	return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) +		&& CHECK_FLAG(peer->af_cap[afi][safi], +			      PEER_CAP_ADDPATH_AF_TX_RCV));  }  /* Parse NLRI stream.  Withdraw NLRI is recognized by NULL attr     value. */ -int -bgp_nlri_parse_ip (struct peer *peer, struct attr *attr, -                   struct bgp_nlri *packet) -{ -  u_char *pnt; -  u_char *lim; -  struct prefix p; -  int psize; -  int ret; -  afi_t afi; -  safi_t safi; -  int addpath_encoded; -  u_int32_t addpath_id; - -  /* Check peer status. */ -  if (peer->status != Established) -    return 0; -   -  pnt = packet->nlri; -  lim = pnt + packet->length; -  afi = packet->afi; -  safi = packet->safi; -  addpath_id = 0; -  addpath_encoded = bgp_addpath_encode_rx (peer, afi, safi); - -  /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for -     syntactic validity.  If the field is syntactically incorrect, -     then the Error Subcode is set to Invalid Network Field. */ -  for (; pnt < lim; pnt += psize) -    { -      /* Clear prefix structure. */ -      memset (&p, 0, sizeof (struct prefix)); - -      if (addpath_encoded) -        { - -          /* When packet overflow occurs return immediately. */ -          if (pnt + BGP_ADDPATH_ID_LEN > lim) -            return -1; - -          addpath_id = ntohl(*((uint32_t*) pnt)); -          pnt += BGP_ADDPATH_ID_LEN; -        } - -      /* Fetch prefix length. */ -      p.prefixlen = *pnt++; -      /* afi/safi validity already verified by caller, bgp_update_receive */ -      p.family = afi2family (afi); - -      /* Prefix length check. */ -      if (p.prefixlen > prefix_blen (&p) * 8) -        { -          zlog_err("%s [Error] Update packet error (wrong perfix length %d for afi %u)", -                   peer->host, p.prefixlen, packet->afi); -          return -1; -        } - -      /* Packet size overflow check. */ -      psize = PSIZE (p.prefixlen); - -      /* When packet overflow occur return immediately. */ -      if (pnt + psize > lim) -        { -          zlog_err("%s [Error] Update packet error (prefix length %d overflows packet)", -                   peer->host, p.prefixlen); -          return -1; -        } - -      /* Defensive coding, double-check the psize fits in a struct prefix */ -      if (psize > (ssize_t) sizeof(p.u)) -        { -          zlog_err("%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)", -                   peer->host, p.prefixlen, sizeof(p.u)); -          return -1; -        } - -      /* Fetch prefix from NLRI packet. */ -      memcpy (&p.u.prefix, pnt, psize); - -      /* Check address. */ -      if (afi == AFI_IP && safi == SAFI_UNICAST) -	{ -	  if (IN_CLASSD (ntohl (p.u.prefix4.s_addr))) -	    { -	      /* From RFC4271 Section 6.3: -	       * -	       * If a prefix in the NLRI field is semantically incorrect -	       * (e.g., an unexpected multicast IP address), an error SHOULD -	       * be logged locally, and the prefix SHOULD be ignored. -	        */ -	      zlog_err ("%s: IPv4 unicast NLRI is multicast address %s, ignoring", -	                peer->host, inet_ntoa (p.u.prefix4)); -	      continue; -	    } -	} - -      /* Check address. */ -      if (afi == AFI_IP6 && safi == SAFI_UNICAST) -	{ -	  if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6)) -	    { -	      char buf[BUFSIZ]; - -	      zlog_err ("%s: IPv6 unicast NLRI is link-local address %s, ignoring", -	                peer->host, inet_ntop (AF_INET6, &p.u.prefix6, buf, BUFSIZ)); - -	      continue; -	    } -	  if (IN6_IS_ADDR_MULTICAST (&p.u.prefix6)) -	    { -	      char buf[BUFSIZ]; - -	      zlog_err ("%s: IPv6 unicast NLRI is multicast address %s, ignoring", -	                peer->host, inet_ntop (AF_INET6, &p.u.prefix6, buf, BUFSIZ)); - -	      continue; -	    } -	} - -      /* Normal process. */ -      if (attr) -	ret = bgp_update (peer, &p, addpath_id, attr, afi, safi, -			  ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL, 0, NULL); -      else -	ret = bgp_withdraw (peer, &p, addpath_id, attr, afi, safi, -			    ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL, NULL); - -      /* Address family configuration mismatch or maximum-prefix count -         overflow. */ -      if (ret < 0) -	return -1; -    } +int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr, +		      struct bgp_nlri *packet) +{ +	u_char *pnt; +	u_char *lim; +	struct prefix p; +	int psize; +	int ret; +	afi_t afi; +	safi_t safi; +	int addpath_encoded; +	u_int32_t addpath_id; + +	/* Check peer status. */ +	if (peer->status != Established) +		return 0; + +	pnt = packet->nlri; +	lim = pnt + packet->length; +	afi = packet->afi; +	safi = packet->safi; +	addpath_id = 0; +	addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi); + +	/* RFC4771 6.3 The NLRI field in the UPDATE message is checked for +	   syntactic validity.  If the field is syntactically incorrect, +	   then the Error Subcode is set to Invalid Network Field. */ +	for (; pnt < lim; pnt += psize) { +		/* Clear prefix structure. */ +		memset(&p, 0, sizeof(struct prefix)); + +		if (addpath_encoded) { + +			/* When packet overflow occurs return immediately. */ +			if (pnt + BGP_ADDPATH_ID_LEN > lim) +				return -1; + +			addpath_id = ntohl(*((uint32_t *)pnt)); +			pnt += BGP_ADDPATH_ID_LEN; +		} -  /* Packet length consistency check. */ -  if (pnt != lim) -    { -      zlog_err ("%s [Error] Update packet error (prefix length mismatch with total length)", -                peer->host); -      return -1; -    } +		/* Fetch prefix length. */ +		p.prefixlen = *pnt++; +		/* afi/safi validity already verified by caller, +		 * bgp_update_receive */ +		p.family = afi2family(afi); + +		/* Prefix length check. */ +		if (p.prefixlen > prefix_blen(&p) * 8) { +			zlog_err( +				"%s [Error] Update packet error (wrong perfix length %d for afi %u)", +				peer->host, p.prefixlen, packet->afi); +			return -1; +		} -  return 0; -} +		/* Packet size overflow check. */ +		psize = PSIZE(p.prefixlen); -static struct bgp_static * -bgp_static_new (void) -{ -  return XCALLOC (MTYPE_BGP_STATIC, sizeof (struct bgp_static)); +		/* When packet overflow occur return immediately. */ +		if (pnt + psize > lim) { +			zlog_err( +				"%s [Error] Update packet error (prefix length %d overflows packet)", +				peer->host, p.prefixlen); +			return -1; +		} + +		/* Defensive coding, double-check the psize fits in a struct +		 * prefix */ +		if (psize > (ssize_t)sizeof(p.u)) { +			zlog_err( +				"%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)", +				peer->host, p.prefixlen, sizeof(p.u)); +			return -1; +		} + +		/* Fetch prefix from NLRI packet. */ +		memcpy(&p.u.prefix, pnt, psize); + +		/* Check address. */ +		if (afi == AFI_IP && safi == SAFI_UNICAST) { +			if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) { +				/* From RFC4271 Section 6.3: +				 * +				 * If a prefix in the NLRI field is semantically +				 * incorrect +				 * (e.g., an unexpected multicast IP address), +				 * an error SHOULD +				 * be logged locally, and the prefix SHOULD be +				 * ignored. +				  */ +				zlog_err( +					"%s: IPv4 unicast NLRI is multicast address %s, ignoring", +					peer->host, inet_ntoa(p.u.prefix4)); +				continue; +			} +		} + +		/* Check address. */ +		if (afi == AFI_IP6 && safi == SAFI_UNICAST) { +			if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) { +				char buf[BUFSIZ]; + +				zlog_err( +					"%s: IPv6 unicast NLRI is link-local address %s, ignoring", +					peer->host, +					inet_ntop(AF_INET6, &p.u.prefix6, buf, +						  BUFSIZ)); + +				continue; +			} +			if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) { +				char buf[BUFSIZ]; + +				zlog_err( +					"%s: IPv6 unicast NLRI is multicast address %s, ignoring", +					peer->host, +					inet_ntop(AF_INET6, &p.u.prefix6, buf, +						  BUFSIZ)); + +				continue; +			} +		} + +		/* Normal process. */ +		if (attr) +			ret = bgp_update(peer, &p, addpath_id, attr, afi, safi, +					 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, +					 NULL, NULL, 0, NULL); +		else +			ret = bgp_withdraw(peer, &p, addpath_id, attr, afi, +					   safi, ZEBRA_ROUTE_BGP, +					   BGP_ROUTE_NORMAL, NULL, NULL, NULL); + +		/* Address family configuration mismatch or maximum-prefix count +		   overflow. */ +		if (ret < 0) +			return -1; +	} + +	/* Packet length consistency check. */ +	if (pnt != lim) { +		zlog_err( +			"%s [Error] Update packet error (prefix length mismatch with total length)", +			peer->host); +		return -1; +	} + +	return 0;  } -static void -bgp_static_free (struct bgp_static *bgp_static) +static struct bgp_static *bgp_static_new(void)  { -  if (bgp_static->rmap.name) -    XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name); -  if(bgp_static->eth_s_id) -    XFREE(MTYPE_ATTR, bgp_static->eth_s_id); -  XFREE (MTYPE_BGP_STATIC, bgp_static); +	return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));  } -static void -bgp_static_update_main (struct bgp *bgp, struct prefix *p, -			struct bgp_static *bgp_static, afi_t afi, safi_t safi) +static void bgp_static_free(struct bgp_static *bgp_static)  { -  struct bgp_node *rn; -  struct bgp_info *ri; -  struct bgp_info *new; -  struct bgp_info info; -  struct attr attr; -  struct attr *attr_new; -  int ret; +	if (bgp_static->rmap.name) +		XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name); +	if (bgp_static->eth_s_id) +		XFREE(MTYPE_ATTR, bgp_static->eth_s_id); +	XFREE(MTYPE_BGP_STATIC, bgp_static); +} + +static void bgp_static_update_main(struct bgp *bgp, struct prefix *p, +				   struct bgp_static *bgp_static, afi_t afi, +				   safi_t safi) +{ +	struct bgp_node *rn; +	struct bgp_info *ri; +	struct bgp_info *new; +	struct bgp_info info; +	struct attr attr; +	struct attr *attr_new; +	int ret;  #if ENABLE_BGP_VNC -  int vnc_implicit_withdraw = 0; +	int vnc_implicit_withdraw = 0;  #endif -  assert (bgp_static); -  if (!bgp_static) -    return; +	assert(bgp_static); +	if (!bgp_static) +		return; -  rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, NULL); +	rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL); -  bgp_attr_default_set (&attr, BGP_ORIGIN_IGP); -   -  attr.nexthop = bgp_static->igpnexthop; -  attr.med = bgp_static->igpmetric; -  attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); +	bgp_attr_default_set(&attr, BGP_ORIGIN_IGP); -  if (bgp_static->atomic) -    attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE); +	attr.nexthop = bgp_static->igpnexthop; +	attr.med = bgp_static->igpmetric; +	attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC); -  /* Apply route-map. */ -  if (bgp_static->rmap.name) -    { -      struct attr attr_tmp = attr; -      info.peer = bgp->peer_self; -      info.attr = &attr_tmp; +	if (bgp_static->atomic) +		attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE); -      SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK); +	/* Apply route-map. */ +	if (bgp_static->rmap.name) { +		struct attr attr_tmp = attr; +		info.peer = bgp->peer_self; +		info.attr = &attr_tmp; -      ret = route_map_apply (bgp_static->rmap.map, p, RMAP_BGP, &info); +		SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK); -      bgp->peer_self->rmap_type = 0; +		ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP, &info); -      if (ret == RMAP_DENYMATCH) -	{     -	  /* Free uninterned attribute. */ -	  bgp_attr_flush (&attr_tmp); +		bgp->peer_self->rmap_type = 0; -	  /* Unintern original. */ -	  aspath_unintern (&attr.aspath); -	  bgp_attr_extra_free (&attr); -	  bgp_static_withdraw (bgp, p, afi, safi); -	  return; -	} -      attr_new = bgp_attr_intern (&attr_tmp); -    } -  else -    attr_new = bgp_attr_intern (&attr); +		if (ret == RMAP_DENYMATCH) { +			/* Free uninterned attribute. */ +			bgp_attr_flush(&attr_tmp); -  for (ri = rn->info; ri; ri = ri->next) -    if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP -	&& ri->sub_type == BGP_ROUTE_STATIC) -      break; +			/* Unintern original. */ +			aspath_unintern(&attr.aspath); +			bgp_attr_extra_free(&attr); +			bgp_static_withdraw(bgp, p, afi, safi); +			return; +		} +		attr_new = bgp_attr_intern(&attr_tmp); +	} else +		attr_new = bgp_attr_intern(&attr); -  if (ri) -    { -      if (attrhash_cmp (ri->attr, attr_new) && -	  !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED) && -	  !bgp_flag_check(bgp, BGP_FLAG_FORCE_STATIC_PROCESS)) -	{ -	  bgp_unlock_node (rn); -	  bgp_attr_unintern (&attr_new); -	  aspath_unintern (&attr.aspath); -	  bgp_attr_extra_free (&attr); -	  return; -	} -      else -	{ -	  /* The attribute is changed. */ -	  bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED); - -	  /* Rewrite BGP route information. */ -	  if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) -	    bgp_info_restore(rn, ri); -	  else -	    bgp_aggregate_decrement (bgp, p, ri, afi, safi); +	for (ri = rn->info; ri; ri = ri->next) +		if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP +		    && ri->sub_type == BGP_ROUTE_STATIC) +			break; + +	if (ri) { +		if (attrhash_cmp(ri->attr, attr_new) +		    && !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED) +		    && !bgp_flag_check(bgp, BGP_FLAG_FORCE_STATIC_PROCESS)) { +			bgp_unlock_node(rn); +			bgp_attr_unintern(&attr_new); +			aspath_unintern(&attr.aspath); +			bgp_attr_extra_free(&attr); +			return; +		} else { +			/* The attribute is changed. */ +			bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED); + +			/* Rewrite BGP route information. */ +			if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) +				bgp_info_restore(rn, ri); +			else +				bgp_aggregate_decrement(bgp, p, ri, afi, safi);  #if ENABLE_BGP_VNC -          if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST))  -            { -              if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED))  -                { -                  /* -                   * Implicit withdraw case. -                   * We have to do this before ri is changed -                   */ -                  ++vnc_implicit_withdraw; -                  vnc_import_bgp_del_route(bgp, p, ri); -                  vnc_import_bgp_exterior_del_route(bgp, p, ri); -                } -            } +			if ((afi == AFI_IP || afi == AFI_IP6) +			    && (safi == SAFI_UNICAST)) { +				if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) { +					/* +					 * Implicit withdraw case. +					 * We have to do this before ri is +					 * changed +					 */ +					++vnc_implicit_withdraw; +					vnc_import_bgp_del_route(bgp, p, ri); +					vnc_import_bgp_exterior_del_route( +						bgp, p, ri); +				} +			}  #endif -	  bgp_attr_unintern (&ri->attr); -	  ri->attr = attr_new; -	  ri->uptime = bgp_clock (); +			bgp_attr_unintern(&ri->attr); +			ri->attr = attr_new; +			ri->uptime = bgp_clock();  #if ENABLE_BGP_VNC -          if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST))  -            { -              if (vnc_implicit_withdraw)  -                { -                  vnc_import_bgp_add_route(bgp, p, ri); -                  vnc_import_bgp_exterior_add_route(bgp, p, ri); -                } -            } +			if ((afi == AFI_IP || afi == AFI_IP6) +			    && (safi == SAFI_UNICAST)) { +				if (vnc_implicit_withdraw) { +					vnc_import_bgp_add_route(bgp, p, ri); +					vnc_import_bgp_exterior_add_route( +						bgp, p, ri); +				} +			}  #endif -	  /* Nexthop reachability check. */ -	  if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK)) -	    { -	      if (bgp_find_or_add_nexthop (bgp, afi, ri, NULL, 0)) -		bgp_info_set_flag (rn, ri, BGP_INFO_VALID); -	      else -		{ -		  if (BGP_DEBUG(nht, NHT)) -		    { -		      char buf1[INET6_ADDRSTRLEN]; -		      inet_ntop(p->family, &p->u.prefix, buf1, -				INET6_ADDRSTRLEN); -		      zlog_debug("%s(%s): Route not in table, not advertising", -				 __FUNCTION__, buf1); -		    } -		  bgp_info_unset_flag (rn, ri, BGP_INFO_VALID); -		} -	    } -	  else -	    { -	      /* Delete the NHT structure if any, if we're toggling between -	       * enabling/disabling import check. We deregister the route -	       * from NHT to avoid overloading NHT and the process interaction -	       */ -	      bgp_unlink_nexthop(ri); -	      bgp_info_set_flag (rn, ri, BGP_INFO_VALID); -	    } -	  /* Process change. */ -	  bgp_aggregate_increment (bgp, p, ri, afi, safi); -	  bgp_process (bgp, rn, afi, safi); -	  bgp_unlock_node (rn); -	  aspath_unintern (&attr.aspath); -	  bgp_attr_extra_free (&attr); -	  return; +			/* Nexthop reachability check. */ +			if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)) { +				if (bgp_find_or_add_nexthop(bgp, afi, ri, NULL, +							    0)) +					bgp_info_set_flag(rn, ri, +							  BGP_INFO_VALID); +				else { +					if (BGP_DEBUG(nht, NHT)) { +						char buf1[INET6_ADDRSTRLEN]; +						inet_ntop(p->family, +							  &p->u.prefix, buf1, +							  INET6_ADDRSTRLEN); +						zlog_debug( +							"%s(%s): Route not in table, not advertising", +							__FUNCTION__, buf1); +					} +					bgp_info_unset_flag(rn, ri, +							    BGP_INFO_VALID); +				} +			} else { +				/* Delete the NHT structure if any, if we're +				 * toggling between +				 * enabling/disabling import check. We +				 * deregister the route +				 * from NHT to avoid overloading NHT and the +				 * process interaction +				 */ +				bgp_unlink_nexthop(ri); +				bgp_info_set_flag(rn, ri, BGP_INFO_VALID); +			} +			/* Process change. */ +			bgp_aggregate_increment(bgp, p, ri, afi, safi); +			bgp_process(bgp, rn, afi, safi); +			bgp_unlock_node(rn); +			aspath_unintern(&attr.aspath); +			bgp_attr_extra_free(&attr); +			return; +		}  	} -    } -  /* Make new BGP info. */ -  new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self, attr_new, -		  rn); -  /* Nexthop reachability check. */ -  if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK)) -    { -      if (bgp_find_or_add_nexthop (bgp, afi, new, NULL, 0)) -	bgp_info_set_flag (rn, new, BGP_INFO_VALID); -      else -	{ -	  if (BGP_DEBUG(nht, NHT)) -	    { -	      char buf1[INET6_ADDRSTRLEN]; -	      inet_ntop(p->family, &p->u.prefix, buf1, -			INET6_ADDRSTRLEN); -	      zlog_debug("%s(%s): Route not in table, not advertising", -			 __FUNCTION__, buf1); -	    } -	  bgp_info_unset_flag (rn, new, BGP_INFO_VALID); +	/* Make new BGP info. */ +	new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self, +			attr_new, rn); +	/* Nexthop reachability check. */ +	if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)) { +		if (bgp_find_or_add_nexthop(bgp, afi, new, NULL, 0)) +			bgp_info_set_flag(rn, new, BGP_INFO_VALID); +		else { +			if (BGP_DEBUG(nht, NHT)) { +				char buf1[INET6_ADDRSTRLEN]; +				inet_ntop(p->family, &p->u.prefix, buf1, +					  INET6_ADDRSTRLEN); +				zlog_debug( +					"%s(%s): Route not in table, not advertising", +					__FUNCTION__, buf1); +			} +			bgp_info_unset_flag(rn, new, BGP_INFO_VALID); +		} +	} else { +		/* Delete the NHT structure if any, if we're toggling between +		 * enabling/disabling import check. We deregister the route +		 * from NHT to avoid overloading NHT and the process interaction +		 */ +		bgp_unlink_nexthop(new); + +		bgp_info_set_flag(rn, new, BGP_INFO_VALID);  	} -    } -  else -    { -      /* Delete the NHT structure if any, if we're toggling between -       * enabling/disabling import check. We deregister the route -       * from NHT to avoid overloading NHT and the process interaction -       */ -      bgp_unlink_nexthop(new); -      bgp_info_set_flag (rn, new, BGP_INFO_VALID); -    } +	/* Aggregate address increment. */ +	bgp_aggregate_increment(bgp, p, new, afi, safi); -  /* Aggregate address increment. */ -  bgp_aggregate_increment (bgp, p, new, afi, safi); -   -  /* Register new BGP information. */ -  bgp_info_add (rn, new); -   -  /* route_node_get lock */ -  bgp_unlock_node (rn); -   -  /* Process change. */ -  bgp_process (bgp, rn, afi, safi); +	/* Register new BGP information. */ +	bgp_info_add(rn, new); + +	/* route_node_get lock */ +	bgp_unlock_node(rn); -  /* Unintern original. */ -  aspath_unintern (&attr.aspath); -  bgp_attr_extra_free (&attr); +	/* Process change. */ +	bgp_process(bgp, rn, afi, safi); + +	/* Unintern original. */ +	aspath_unintern(&attr.aspath); +	bgp_attr_extra_free(&attr);  } -void -bgp_static_update (struct bgp *bgp, struct prefix *p, -                  struct bgp_static *bgp_static, afi_t afi, safi_t safi) +void bgp_static_update(struct bgp *bgp, struct prefix *p, +		       struct bgp_static *bgp_static, afi_t afi, safi_t safi)  { -  bgp_static_update_main (bgp, p, bgp_static, afi, safi); +	bgp_static_update_main(bgp, p, bgp_static, afi, safi);  } -void -bgp_static_withdraw (struct bgp *bgp, struct prefix *p, afi_t afi, -		     safi_t safi) +void bgp_static_withdraw(struct bgp *bgp, struct prefix *p, afi_t afi, +			 safi_t safi)  { -  struct bgp_node *rn; -  struct bgp_info *ri; - -  rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, NULL); +	struct bgp_node *rn; +	struct bgp_info *ri; -  /* Check selected route and self inserted route. */ -  for (ri = rn->info; ri; ri = ri->next) -    if (ri->peer == bgp->peer_self  -	&& ri->type == ZEBRA_ROUTE_BGP -	&& ri->sub_type == BGP_ROUTE_STATIC) -      break; +	rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL); -  /* Withdraw static BGP route from routing table. */ -  if (ri) -    { -      bgp_aggregate_decrement (bgp, p, ri, afi, safi); -      bgp_unlink_nexthop(ri); -      bgp_info_delete (rn, ri); -      bgp_process (bgp, rn, afi, safi); -    } +	/* Check selected route and self inserted route. */ +	for (ri = rn->info; ri; ri = ri->next) +		if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP +		    && ri->sub_type == BGP_ROUTE_STATIC) +			break; + +	/* Withdraw static BGP route from routing table. */ +	if (ri) { +		bgp_aggregate_decrement(bgp, p, ri, afi, safi); +		bgp_unlink_nexthop(ri); +		bgp_info_delete(rn, ri); +		bgp_process(bgp, rn, afi, safi); +	} -  /* Unlock bgp_node_lookup. */ -  bgp_unlock_node (rn); +	/* Unlock bgp_node_lookup. */ +	bgp_unlock_node(rn);  }  /*   * Used for SAFI_MPLS_VPN and SAFI_ENCAP   */ -static void -bgp_static_withdraw_safi (struct bgp *bgp, struct prefix *p, afi_t afi, -                          safi_t safi, struct prefix_rd *prd, u_char *tag) +static void bgp_static_withdraw_safi(struct bgp *bgp, struct prefix *p, +				     afi_t afi, safi_t safi, +				     struct prefix_rd *prd, u_char *tag)  { -  struct bgp_node *rn; -  struct bgp_info *ri; +	struct bgp_node *rn; +	struct bgp_info *ri; -  rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd); +	rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd); -  /* Check selected route and self inserted route. */ -  for (ri = rn->info; ri; ri = ri->next) -    if (ri->peer == bgp->peer_self  -	&& ri->type == ZEBRA_ROUTE_BGP -	&& ri->sub_type == BGP_ROUTE_STATIC) -      break; +	/* Check selected route and self inserted route. */ +	for (ri = rn->info; ri; ri = ri->next) +		if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP +		    && ri->sub_type == BGP_ROUTE_STATIC) +			break; -  /* Withdraw static BGP route from routing table. */ -  if (ri) -    { +	/* Withdraw static BGP route from routing table. */ +	if (ri) {  #if ENABLE_BGP_VNC -	rfapiProcessWithdraw( -	    ri->peer, -	    NULL, -	    p, -	    prd, -	    ri->attr, -	    afi, -	    safi, -	    ri->type, -	    1);		/* Kill, since it is an administrative change */ +		rfapiProcessWithdraw( +			ri->peer, NULL, p, prd, ri->attr, afi, safi, ri->type, +			1); /* Kill, since it is an administrative change */  #endif -      bgp_aggregate_decrement (bgp, p, ri, afi, safi); -      bgp_info_delete (rn, ri); -      bgp_process (bgp, rn, afi, safi); -    } +		bgp_aggregate_decrement(bgp, p, ri, afi, safi); +		bgp_info_delete(rn, ri); +		bgp_process(bgp, rn, afi, safi); +	} -  /* Unlock bgp_node_lookup. */ -  bgp_unlock_node (rn); +	/* Unlock bgp_node_lookup. */ +	bgp_unlock_node(rn);  } -static void -bgp_static_update_safi (struct bgp *bgp, struct prefix *p, -                        struct bgp_static *bgp_static, afi_t afi, safi_t safi) +static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p, +				   struct bgp_static *bgp_static, afi_t afi, +				   safi_t safi)  { -  struct bgp_node *rn; -  struct bgp_info *new; -  struct attr *attr_new; -  struct attr attr = { 0 }; -  struct bgp_info *ri; +	struct bgp_node *rn; +	struct bgp_info *new; +	struct attr *attr_new; +	struct attr attr = {0}; +	struct bgp_info *ri;  #if ENABLE_BGP_VNC -  u_int32_t        label = 0; +	u_int32_t label = 0;  #endif -  union gw_addr add; +	union gw_addr add; -  assert (bgp_static); +	assert(bgp_static); -  rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, &bgp_static->prd); +	rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, +			      &bgp_static->prd); -  bgp_attr_default_set (&attr, BGP_ORIGIN_IGP); +	bgp_attr_default_set(&attr, BGP_ORIGIN_IGP); -  attr.nexthop = bgp_static->igpnexthop; -  attr.med = bgp_static->igpmetric; -  attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); - -  if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) -    { -      if (afi == AFI_IP) -        { -          bgp_attr_extra_get (&attr)->mp_nexthop_global_in = bgp_static->igpnexthop; -          bgp_attr_extra_get (&attr)->mp_nexthop_len = IPV4_MAX_BYTELEN; -        } -    } -  if(afi == AFI_L2VPN) -    { -      if (bgp_static->gatewayIp.family == AF_INET) -        add.ipv4.s_addr = bgp_static->gatewayIp.u.prefix4.s_addr; -      else if (bgp_static->gatewayIp.family == AF_INET6) -        memcpy( &(add.ipv6), &(bgp_static->gatewayIp.u.prefix6), sizeof (struct in6_addr)); -      overlay_index_update(&attr, bgp_static->eth_s_id, &add); -      if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) -        { -          struct bgp_encap_type_vxlan bet; -          memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan)); -          bet.vnid = p->u.prefix_evpn.eth_tag; -          bgp_encap_type_vxlan_to_tlv(&bet, &attr); -        } -      if (bgp_static->router_mac) -        { -          bgp_add_routermac_ecom (&attr, bgp_static->router_mac); -        } -    } -  /* Apply route-map. */ -  if (bgp_static->rmap.name) -    { -      struct attr attr_tmp = attr; -      struct bgp_info info; -      int ret; +	attr.nexthop = bgp_static->igpnexthop; +	attr.med = bgp_static->igpmetric; +	attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC); -      info.peer = bgp->peer_self; -      info.attr = &attr_tmp; +	if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN) +	    || (safi == SAFI_ENCAP)) { +		if (afi == AFI_IP) { +			bgp_attr_extra_get(&attr)->mp_nexthop_global_in = +				bgp_static->igpnexthop; +			bgp_attr_extra_get(&attr)->mp_nexthop_len = +				IPV4_MAX_BYTELEN; +		} +	} +	if (afi == AFI_L2VPN) { +		if (bgp_static->gatewayIp.family == AF_INET) +			add.ipv4.s_addr = +				bgp_static->gatewayIp.u.prefix4.s_addr; +		else if (bgp_static->gatewayIp.family == AF_INET6) +			memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6), +			       sizeof(struct in6_addr)); +		overlay_index_update(&attr, bgp_static->eth_s_id, &add); +		if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) { +			struct bgp_encap_type_vxlan bet; +			memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan)); +			bet.vnid = p->u.prefix_evpn.eth_tag; +			bgp_encap_type_vxlan_to_tlv(&bet, &attr); +		} +		if (bgp_static->router_mac) { +			bgp_add_routermac_ecom(&attr, bgp_static->router_mac); +		} +	} +	/* Apply route-map. */ +	if (bgp_static->rmap.name) { +		struct attr attr_tmp = attr; +		struct bgp_info info; +		int ret; -      SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK); +		info.peer = bgp->peer_self; +		info.attr = &attr_tmp; -      ret = route_map_apply (bgp_static->rmap.map, p, RMAP_BGP, &info); +		SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK); -      bgp->peer_self->rmap_type = 0; +		ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP, &info); -      if (ret == RMAP_DENYMATCH) -        { -          /* Free uninterned attribute. */ -          bgp_attr_flush (&attr_tmp); +		bgp->peer_self->rmap_type = 0; -          /* Unintern original. */ -          aspath_unintern (&attr.aspath); -          bgp_attr_extra_free (&attr); -          bgp_static_withdraw_safi (bgp, p, afi, safi, &bgp_static->prd, -                                    bgp_static->tag); -          return; -        } +		if (ret == RMAP_DENYMATCH) { +			/* Free uninterned attribute. */ +			bgp_attr_flush(&attr_tmp); -      attr_new = bgp_attr_intern (&attr_tmp); -    } -  else -    { -      attr_new = bgp_attr_intern (&attr); -    } +			/* Unintern original. */ +			aspath_unintern(&attr.aspath); +			bgp_attr_extra_free(&attr); +			bgp_static_withdraw_safi(bgp, p, afi, safi, +						 &bgp_static->prd, +						 bgp_static->tag); +			return; +		} -  for (ri = rn->info; ri; ri = ri->next) -    if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP -        && ri->sub_type == BGP_ROUTE_STATIC) -      break; +		attr_new = bgp_attr_intern(&attr_tmp); +	} else { +		attr_new = bgp_attr_intern(&attr); +	} -  if (ri) -    { -      union gw_addr add; -      memset(&add, 0, sizeof(union gw_addr)); -      if (attrhash_cmp (ri->attr, attr_new) && -          overlay_index_equal(afi, ri, bgp_static->eth_s_id, &add) && -          !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) -        { -          bgp_unlock_node (rn); -          bgp_attr_unintern (&attr_new); -          aspath_unintern (&attr.aspath); -          bgp_attr_extra_free (&attr); -          return; -        } -      else -        { -          /* The attribute is changed. */ -          bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED); - -          /* Rewrite BGP route information. */ -          if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) -            bgp_info_restore(rn, ri); -          else -            bgp_aggregate_decrement (bgp, p, ri, afi, safi); -          bgp_attr_unintern (&ri->attr); -          ri->attr = attr_new; -          ri->uptime = bgp_clock (); +	for (ri = rn->info; ri; ri = ri->next) +		if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP +		    && ri->sub_type == BGP_ROUTE_STATIC) +			break; + +	if (ri) { +		union gw_addr add; +		memset(&add, 0, sizeof(union gw_addr)); +		if (attrhash_cmp(ri->attr, attr_new) +		    && overlay_index_equal(afi, ri, bgp_static->eth_s_id, &add) +		    && !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) { +			bgp_unlock_node(rn); +			bgp_attr_unintern(&attr_new); +			aspath_unintern(&attr.aspath); +			bgp_attr_extra_free(&attr); +			return; +		} else { +			/* The attribute is changed. */ +			bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED); + +			/* Rewrite BGP route information. */ +			if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) +				bgp_info_restore(rn, ri); +			else +				bgp_aggregate_decrement(bgp, p, ri, afi, safi); +			bgp_attr_unintern(&ri->attr); +			ri->attr = attr_new; +			ri->uptime = bgp_clock();  #if ENABLE_BGP_VNC -          if (ri->extra) -              label = decode_label (ri->extra->tag); +			if (ri->extra) +				label = decode_label(ri->extra->tag);  #endif -          /* Process change. */ -          bgp_aggregate_increment (bgp, p, ri, afi, safi); -          bgp_process (bgp, rn, afi, safi); +			/* Process change. */ +			bgp_aggregate_increment(bgp, p, ri, afi, safi); +			bgp_process(bgp, rn, afi, safi);  #if ENABLE_BGP_VNC -          rfapiProcessUpdate(ri->peer, NULL, p, &bgp_static->prd, -                             ri->attr, afi, safi,  -                             ri->type, ri->sub_type, &label); +			rfapiProcessUpdate(ri->peer, NULL, p, &bgp_static->prd, +					   ri->attr, afi, safi, ri->type, +					   ri->sub_type, &label);  #endif -          bgp_unlock_node (rn); -          aspath_unintern (&attr.aspath); -          bgp_attr_extra_free (&attr); -          return; -        } -    } +			bgp_unlock_node(rn); +			aspath_unintern(&attr.aspath); +			bgp_attr_extra_free(&attr); +			return; +		} +	} -  /* Make new BGP info. */ -  new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self, attr_new, -		  rn); -  SET_FLAG (new->flags, BGP_INFO_VALID); -  new->extra = bgp_info_extra_new(); -  memcpy (new->extra->tag, bgp_static->tag, 3); +	/* Make new BGP info. */ +	new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self, +			attr_new, rn); +	SET_FLAG(new->flags, BGP_INFO_VALID); +	new->extra = bgp_info_extra_new(); +	memcpy(new->extra->tag, bgp_static->tag, 3);  #if ENABLE_BGP_VNC -  label = decode_label (bgp_static->tag); +	label = decode_label(bgp_static->tag);  #endif -  /* Aggregate address increment. */ -  bgp_aggregate_increment (bgp, p, new, afi, safi); +	/* Aggregate address increment. */ +	bgp_aggregate_increment(bgp, p, new, afi, safi); -  /* Register new BGP information. */ -  bgp_info_add (rn, new); -  /* route_node_get lock */ -  bgp_unlock_node (rn); +	/* Register new BGP information. */ +	bgp_info_add(rn, new); +	/* route_node_get lock */ +	bgp_unlock_node(rn); -  /* Process change. */ -  bgp_process (bgp, rn, afi, safi); +	/* Process change. */ +	bgp_process(bgp, rn, afi, safi);  #if ENABLE_BGP_VNC -  rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, -                     new->attr, afi, safi,  -                     new->type, new->sub_type, &label); +	rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi, +			   safi, new->type, new->sub_type, &label);  #endif -  /* Unintern original. */ -  aspath_unintern (&attr.aspath); -  bgp_attr_extra_free (&attr); +	/* Unintern original. */ +	aspath_unintern(&attr.aspath); +	bgp_attr_extra_free(&attr);  }  /* Configure static BGP network.  When user don't run zebra, static     route should be installed as valid.  */ -static int -bgp_static_set (struct vty *vty, const char *ip_str,  -                afi_t afi, safi_t safi, const char *rmap, int backdoor) -{ -  VTY_DECLVAR_CONTEXT(bgp, bgp); -  int ret; -  struct prefix p; -  struct bgp_static *bgp_static; -  struct bgp_node *rn; -  u_char need_update = 0; - -  /* Convert IP prefix string to struct prefix. */ -  ret = str2prefix (ip_str, &p); -  if (! ret) -    { -      vty_out (vty, "%% Malformed prefix%s", VTY_NEWLINE); -      return CMD_WARNING; -    } -  if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6)) -    { -      vty_out (vty, "%% Malformed prefix (link-local address)%s", -	       VTY_NEWLINE); -      return CMD_WARNING; -    } +static int bgp_static_set(struct vty *vty, const char *ip_str, afi_t afi, +			  safi_t safi, const char *rmap, int backdoor) +{ +	VTY_DECLVAR_CONTEXT(bgp, bgp); +	int ret; +	struct prefix p; +	struct bgp_static *bgp_static; +	struct bgp_node *rn; +	u_char need_update = 0; + +	/* Convert IP prefix string to struct prefix. */ +	ret = str2prefix(ip_str, &p); +	if (!ret) { +		vty_out(vty, "%% Malformed prefix%s", VTY_NEWLINE); +		return CMD_WARNING; +	} +	if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) { +		vty_out(vty, "%% Malformed prefix (link-local address)%s", +			VTY_NEWLINE); +		return CMD_WARNING; +	} -  apply_mask (&p); +	apply_mask(&p); -  /* Set BGP static route configuration. */ -  rn = bgp_node_get (bgp->route[afi][safi], &p); +	/* Set BGP static route configuration. */ +	rn = bgp_node_get(bgp->route[afi][safi], &p); -  if (rn->info) -    { -      /* Configuration change. */ -      bgp_static = rn->info; - -      /* Check previous routes are installed into BGP.  */ -      if (bgp_static->valid && bgp_static->backdoor != backdoor) -        need_update = 1; -       -      bgp_static->backdoor = backdoor; -       -      if (rmap) -	{ -	  if (bgp_static->rmap.name) -	    XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name); -	  bgp_static->rmap.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); -	  bgp_static->rmap.map = route_map_lookup_by_name (rmap); -	} -      else -	{ -	  if (bgp_static->rmap.name) -	    XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name); -	  bgp_static->rmap.name = NULL; -	  bgp_static->rmap.map = NULL; -	  bgp_static->valid = 0; -	} -      bgp_unlock_node (rn); -    } -  else -    { -      /* New configuration. */ -      bgp_static = bgp_static_new (); -      bgp_static->backdoor = backdoor; -      bgp_static->valid = 0; -      bgp_static->igpmetric = 0; -      bgp_static->igpnexthop.s_addr = 0; -       -      if (rmap) -	{ -	  if (bgp_static->rmap.name) -	    XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name); -	  bgp_static->rmap.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); -	  bgp_static->rmap.map = route_map_lookup_by_name (rmap); -	} -      rn->info = bgp_static; -    } +	if (rn->info) { +		/* Configuration change. */ +		bgp_static = rn->info; -  bgp_static->valid = 1; -  if (need_update) -    bgp_static_withdraw (bgp, &p, afi, safi); +		/* Check previous routes are installed into BGP.  */ +		if (bgp_static->valid && bgp_static->backdoor != backdoor) +			need_update = 1; + +		bgp_static->backdoor = backdoor; + +		if (rmap) { +			if (bgp_static->rmap.name) +				XFREE(MTYPE_ROUTE_MAP_NAME, +				      bgp_static->rmap.name); +			bgp_static->rmap.name = +				XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); +			bgp_static->rmap.map = route_map_lookup_by_name(rmap); +		} else { +			if (bgp_static->rmap.name) +				XFREE(MTYPE_ROUTE_MAP_NAME, +				      bgp_static->rmap.name); +			bgp_static->rmap.name = NULL; +			bgp_static->rmap.map = NULL; +			bgp_static->valid = 0; +		} +		bgp_unlock_node(rn); +	} else { +		/* New configuration. */ +		bgp_static = bgp_static_new(); +		bgp_static->backdoor = backdoor; +		bgp_static->valid = 0; +		bgp_static->igpmetric = 0; +		bgp_static->igpnexthop.s_addr = 0; + +		if (rmap) { +			if (bgp_static->rmap.name) +				XFREE(MTYPE_ROUTE_MAP_NAME, +				      bgp_static->rmap.name); +			bgp_static->rmap.name = +				XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); +			bgp_static->rmap.map = route_map_lookup_by_name(rmap); +		} +		rn->info = bgp_static; +	} -  if (! bgp_static->backdoor) -    bgp_static_update (bgp, &p, bgp_static, afi, safi); +	bgp_static->valid = 1; +	if (need_update) +		bgp_static_withdraw(bgp, &p, afi, safi); -  return CMD_SUCCESS; +	if (!bgp_static->backdoor) +		bgp_static_update(bgp, &p, bgp_static, afi, safi); + +	return CMD_SUCCESS;  }  /* Configure static BGP network. */ -static int -bgp_static_unset (struct vty *vty, const char *ip_str, -		  afi_t afi, safi_t safi) -{ -  VTY_DECLVAR_CONTEXT(bgp, bgp); -  int ret; -  struct prefix p; -  struct bgp_static *bgp_static; -  struct bgp_node *rn; - -  /* Convert IP prefix string to struct prefix. */ -  ret = str2prefix (ip_str, &p); -  if (! ret) -    { -      vty_out (vty, "%% Malformed prefix%s", VTY_NEWLINE); -      return CMD_WARNING; -    } -  if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6)) -    { -      vty_out (vty, "%% Malformed prefix (link-local address)%s", -	       VTY_NEWLINE); -      return CMD_WARNING; -    } +static int bgp_static_unset(struct vty *vty, const char *ip_str, afi_t afi, +			    safi_t safi) +{ +	VTY_DECLVAR_CONTEXT(bgp, bgp); +	int ret; +	struct prefix p; +	struct bgp_static *bgp_static; +	struct bgp_node *rn; + +	/* Convert IP prefix string to struct prefix. */ +	ret = str2prefix(ip_str, &p); +	if (!ret) { +		vty_out(vty, "%% Malformed prefix%s", VTY_NEWLINE); +		return CMD_WARNING; +	} +	if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) { +		vty_out(vty, "%% Malformed prefix (link-local address)%s", +			VTY_NEWLINE); +		return CMD_WARNING; +	} -  apply_mask (&p); +	apply_mask(&p); -  rn = bgp_node_lookup (bgp->route[afi][safi], &p); -  if (! rn) -    { -      vty_out (vty, "%% Can't find specified static route configuration.%s", -	       VTY_NEWLINE); -      return CMD_WARNING; -    } +	rn = bgp_node_lookup(bgp->route[afi][safi], &p); +	if (!rn) { +		vty_out(vty, +			"%% Can't find specified static route configuration.%s", +			VTY_NEWLINE); +		return CMD_WARNING; +	} -  bgp_static = rn->info; -   -  /* Update BGP RIB. */ -  if (! bgp_static->backdoor) -    bgp_static_withdraw (bgp, &p, afi, safi); - -  /* Clear configuration. */ -  bgp_static_free (bgp_static); -  rn->info = NULL; -  bgp_unlock_node (rn); -  bgp_unlock_node (rn); - -  return CMD_SUCCESS; -} - -void -bgp_static_add (struct bgp *bgp) -{ -  afi_t afi; -  safi_t safi; -  struct bgp_node *rn; -  struct bgp_node *rm; -  struct bgp_table *table; -  struct bgp_static *bgp_static; - -  for (afi = AFI_IP; afi < AFI_MAX; afi++) -    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) -      for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn)) -	if (rn->info != NULL) -	  {       -	    if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN)) -	      { -		table = rn->info; - -		for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm)) -		  { -		    bgp_static = rm->info; -                    bgp_static_update_safi (bgp, &rm->p, bgp_static, afi, safi); -		  } -	      } -	    else -	      { -		bgp_static_update (bgp, &rn->p, rn->info, afi, safi); -	      } -	  } +	bgp_static = rn->info; + +	/* Update BGP RIB. */ +	if (!bgp_static->backdoor) +		bgp_static_withdraw(bgp, &p, afi, safi); + +	/* Clear configuration. */ +	bgp_static_free(bgp_static); +	rn->info = NULL; +	bgp_unlock_node(rn); +	bgp_unlock_node(rn); + +	return CMD_SUCCESS; +} + +void bgp_static_add(struct bgp *bgp) +{ +	afi_t afi; +	safi_t safi; +	struct bgp_node *rn; +	struct bgp_node *rm; +	struct bgp_table *table; +	struct bgp_static *bgp_static; + +	for (afi = AFI_IP; afi < AFI_MAX; afi++) +		for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) +			for (rn = bgp_table_top(bgp->route[afi][safi]); rn; +			     rn = bgp_route_next(rn)) +				if (rn->info != NULL) { +					if ((safi == SAFI_MPLS_VPN) +					    || (safi == SAFI_ENCAP) +					    || (safi == SAFI_EVPN)) { +						table = rn->info; + +						for (rm = bgp_table_top(table); +						     rm; +						     rm = bgp_route_next(rm)) { +							bgp_static = rm->info; +							bgp_static_update_safi( +								bgp, &rm->p, +								bgp_static, afi, +								safi); +						} +					} else { +						bgp_static_update(bgp, &rn->p, +								  rn->info, afi, +								  safi); +					} +				}  }  /* Called from bgp_delete().  Delete all static routes from the BGP     instance. */ -void -bgp_static_delete (struct bgp *bgp) -{ -  afi_t afi; -  safi_t safi; -  struct bgp_node *rn; -  struct bgp_node *rm; -  struct bgp_table *table; -  struct bgp_static *bgp_static; - -  for (afi = AFI_IP; afi < AFI_MAX; afi++) -    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) -      for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn)) -	if (rn->info != NULL) -	  {       -	    if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN)) -	      { -		table = rn->info; - -		for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm)) -		  { -		    bgp_static = rm->info; -		    bgp_static_withdraw_safi (bgp, &rm->p, -					       AFI_IP, safi, -					       (struct prefix_rd *)&rn->p, -					       bgp_static->tag); -		    bgp_static_free (bgp_static); -		    rn->info = NULL; -		    bgp_unlock_node (rn); -		  } -	      } -	    else -	      { -		bgp_static = rn->info; -		bgp_static_withdraw (bgp, &rn->p, afi, safi); -		bgp_static_free (bgp_static); -		rn->info = NULL; -		bgp_unlock_node (rn); -	      } -	  } -} - -void -bgp_static_redo_import_check (struct bgp *bgp) -{ -  afi_t afi; -  safi_t safi; -  struct bgp_node *rn; -  struct bgp_node *rm; -  struct bgp_table *table; -  struct bgp_static *bgp_static; - -  /* Use this flag to force reprocessing of the route */ -  bgp_flag_set(bgp, BGP_FLAG_FORCE_STATIC_PROCESS); -  for (afi = AFI_IP; afi < AFI_MAX; afi++) -    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) -      for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn)) -	if (rn->info != NULL) -	  { -	    if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN)) -	      { -		table = rn->info; - -		for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm)) -		  { -		    bgp_static = rm->info; -		    bgp_static_update_safi (bgp, &rm->p, bgp_static, afi, safi); -		  } -	      } -	    else -	      { -		bgp_static = rn->info; -		bgp_static_update (bgp, &rn->p, bgp_static, afi, safi); -	      } -	  } -  bgp_flag_unset(bgp, BGP_FLAG_FORCE_STATIC_PROCESS); -} - -static void -bgp_purge_af_static_redist_routes (struct bgp *bgp, afi_t afi, safi_t safi) -{ -  struct bgp_table *table; -  struct bgp_node *rn; -  struct bgp_info *ri; - -  table = bgp->rib[afi][safi]; -  for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) -    { -      for (ri = rn->info; ri; ri = ri->next) -        { -          if (ri->peer == bgp->peer_self && -              ((ri->type == ZEBRA_ROUTE_BGP && -                ri->sub_type == BGP_ROUTE_STATIC) || -               (ri->type != ZEBRA_ROUTE_BGP && -                ri->sub_type == BGP_ROUTE_REDISTRIBUTE))) -            { -              bgp_aggregate_decrement (bgp, &rn->p, ri, afi, safi); -              bgp_unlink_nexthop(ri); -              bgp_info_delete (rn, ri); -              bgp_process (bgp, rn, afi, safi); -            } -        } -    } +void bgp_static_delete(struct bgp *bgp) +{ +	afi_t afi; +	safi_t safi; +	struct bgp_node *rn; +	struct bgp_node *rm; +	struct bgp_table *table; +	struct bgp_static *bgp_static; + +	for (afi = AFI_IP; afi < AFI_MAX; afi++) +		for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) +			for (rn = bgp_table_top(bgp->route[afi][safi]); rn; +			     rn = bgp_route_next(rn)) +				if (rn->info != NULL) { +					if ((safi == SAFI_MPLS_VPN) +					    || (safi == SAFI_ENCAP) +					    || (safi == SAFI_EVPN)) { +						table = rn->info; + +						for (rm = bgp_table_top(table); +						     rm; +						     rm = bgp_route_next(rm)) { +							bgp_static = rm->info; +							bgp_static_withdraw_safi( +								bgp, &rm->p, +								AFI_IP, safi, +								(struct +								 prefix_rd *)&rn +									->p, +								bgp_static +									->tag); +							bgp_static_free( +								bgp_static); +							rn->info = NULL; +							bgp_unlock_node(rn); +						} +					} else { +						bgp_static = rn->info; +						bgp_static_withdraw(bgp, &rn->p, +								    afi, safi); +						bgp_static_free(bgp_static); +						rn->info = NULL; +						bgp_unlock_node(rn); +					} +				} +} + +void bgp_static_redo_import_check(struct bgp *bgp) +{ +	afi_t afi; +	safi_t safi; +	struct bgp_node *rn; +	struct bgp_node *rm; +	struct bgp_table *table; +	struct bgp_static *bgp_static; + +	/* Use this flag to force reprocessing of the route */ +	bgp_flag_set(bgp, BGP_FLAG_FORCE_STATIC_PROCESS); +	for (afi = AFI_IP; afi < AFI_MAX; afi++) +		for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) +			for (rn = bgp_table_top(bgp->route[afi][safi]); rn; +			     rn = bgp_route_next(rn)) +				if (rn->info != NULL) { +					if ((safi == SAFI_MPLS_VPN) +					    || (safi == SAFI_ENCAP) +					    || (safi == SAFI_EVPN)) { +						table = rn->info; + +						for (rm = bgp_table_top(table); +						     rm; +						     rm = bgp_route_next(rm)) { +							bgp_static = rm->info; +							bgp_static_update_safi( +								bgp, &rm->p, +								bgp_static, afi, +								safi); +						} +					} else { +						bgp_static = rn->info; +						bgp_static_update(bgp, &rn->p, +								  bgp_static, +								  afi, safi); +					} +				} +	bgp_flag_unset(bgp, BGP_FLAG_FORCE_STATIC_PROCESS); +} + +static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi, +					      safi_t safi) +{ +	struct bgp_table *table; +	struct bgp_node *rn; +	struct bgp_info *ri; + +	table = bgp->rib[afi][safi]; +	for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { +		for (ri = rn->info; ri; ri = ri->next) { +			if (ri->peer == bgp->peer_self +			    && ((ri->type == ZEBRA_ROUTE_BGP +				 && ri->sub_type == BGP_ROUTE_STATIC) +				|| (ri->type != ZEBRA_ROUTE_BGP +				    && ri->sub_type +					       == BGP_ROUTE_REDISTRIBUTE))) { +				bgp_aggregate_decrement(bgp, &rn->p, ri, afi, +							safi); +				bgp_unlink_nexthop(ri); +				bgp_info_delete(rn, ri); +				bgp_process(bgp, rn, afi, safi); +			} +		} +	}  }  /*   * Purge all networks and redistributed routes from routing table.   * Invoked upon the instance going down.   */ -void -bgp_purge_static_redist_routes (struct bgp *bgp) +void bgp_purge_static_redist_routes(struct bgp *bgp)  { -  afi_t afi; -  safi_t safi; +	afi_t afi; +	safi_t safi; -  for (afi = AFI_IP; afi < AFI_MAX; afi++) -    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) -      bgp_purge_af_static_redist_routes (bgp, afi, safi); +	for (afi = AFI_IP; afi < AFI_MAX; afi++) +		for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) +			bgp_purge_af_static_redist_routes(bgp, afi, safi);  }  /* @@ -4451,274 +4413,257 @@ bgp_purge_static_redist_routes (struct bgp *bgp)   * Currently this is used to set static routes for VPN and ENCAP.   * I think it can probably be factored with bgp_static_set.   */ -int -bgp_static_set_safi (afi_t afi, safi_t safi, struct vty *vty, const char *ip_str, -                     const char *rd_str, const char *label_str, -                     const char *rmap_str, int evpn_type, const char *esi, const char *gwip, -                     const char *ethtag, const char *routermac) -{ -  VTY_DECLVAR_CONTEXT(bgp, bgp); -  int ret; -  struct prefix p; -  struct prefix_rd prd; -  struct bgp_node *prn; -  struct bgp_node *rn; -  struct bgp_table *table; -  struct bgp_static *bgp_static; -  u_char tag[3]; -  struct prefix gw_ip; - -  /* validate ip prefix */ -  ret = str2prefix (ip_str, &p); -  if (! ret) -    { -      vty_out (vty, "%% Malformed prefix%s", VTY_NEWLINE); -      return CMD_WARNING; -    } -  apply_mask (&p); -  if ( (afi == AFI_L2VPN) && -       (bgp_build_evpn_prefix ( evpn_type, ethtag!=NULL?atol(ethtag):0, &p))) -    { -      vty_out (vty, "%% L2VPN prefix could not be forged%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty, +			const char *ip_str, const char *rd_str, +			const char *label_str, const char *rmap_str, +			int evpn_type, const char *esi, const char *gwip, +			const char *ethtag, const char *routermac) +{ +	VTY_DECLVAR_CONTEXT(bgp, bgp); +	int ret; +	struct prefix p; +	struct prefix_rd prd; +	struct bgp_node *prn; +	struct bgp_node *rn; +	struct bgp_table *table; +	struct bgp_static *bgp_static; +	u_char tag[3]; +	struct prefix gw_ip; + +	/* validate ip prefix */ +	ret = str2prefix(ip_str, &p); +	if (!ret) { +		vty_out(vty, "%% Malformed prefix%s", VTY_NEWLINE); +		return CMD_WARNING; +	} +	apply_mask(&p); +	if ((afi == AFI_L2VPN) +	    && (bgp_build_evpn_prefix(evpn_type, +				      ethtag != NULL ? atol(ethtag) : 0, &p))) { +		vty_out(vty, "%% L2VPN prefix could not be forged%s", +			VTY_NEWLINE); +		return CMD_WARNING; +	} -  ret = str2prefix_rd (rd_str, &prd); -  if (! ret) -    { -      vty_out (vty, "%% Malformed rd%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +	ret = str2prefix_rd(rd_str, &prd); +	if (!ret) { +		vty_out(vty, "%% Malformed rd%s", VTY_NEWLINE); +		return CMD_WARNING; +	} -  if (label_str) -    { -      unsigned long label_val; -      VTY_GET_INTEGER_RANGE("Label/tag", label_val, label_str, 0, 16777215); -      encode_label (label_val, tag); -    } -  else -    { -      memset (tag, 0, sizeof(tag)); /* empty, not even BoS */ -    } -  if (safi == SAFI_EVPN) -    { -      if( esi && str2esi (esi, NULL) == 0) -        { -          vty_out (vty, "%% Malformed ESI%s", VTY_NEWLINE); -          return CMD_WARNING; -        } -      if( routermac && prefix_str2mac (routermac, NULL) == 0) -        { -          vty_out (vty, "%% Malformed Router MAC%s", VTY_NEWLINE); -          return CMD_WARNING; -        } -      if (gwip) -        { -          memset (&gw_ip, 0, sizeof (struct prefix)); -          ret = str2prefix (gwip, &gw_ip); -          if (! ret) -            { -              vty_out (vty, "%% Malformed GatewayIp%s", VTY_NEWLINE); -              return CMD_WARNING; -            } -          if((gw_ip.family == AF_INET &&  (p.u.prefix_evpn.flags & IP_PREFIX_V6)) -             || (gw_ip.family == AF_INET6 &&  (p.u.prefix_evpn.flags & IP_PREFIX_V4))) -            { -              vty_out (vty, "%% GatewayIp family differs with IP prefix%s", VTY_NEWLINE); -              return CMD_WARNING; -            } -        } -    } -  prn = bgp_node_get (bgp->route[afi][safi], -			(struct prefix *)&prd); -  if (prn->info == NULL) -    prn->info = bgp_table_init (afi, safi); -  else -    bgp_unlock_node (prn); -  table = prn->info; +	if (label_str) { +		unsigned long label_val; +		VTY_GET_INTEGER_RANGE("Label/tag", label_val, label_str, 0, +				      16777215); +		encode_label(label_val, tag); +	} else { +		memset(tag, 0, sizeof(tag)); /* empty, not even BoS */ +	} +	if (safi == SAFI_EVPN) { +		if (esi && str2esi(esi, NULL) == 0) { +			vty_out(vty, "%% Malformed ESI%s", VTY_NEWLINE); +			return CMD_WARNING; +		} +		if (routermac && prefix_str2mac(routermac, NULL) == 0) { +			vty_out(vty, "%% Malformed Router MAC%s", VTY_NEWLINE); +			return CMD_WARNING; +		} +		if (gwip) { +			memset(&gw_ip, 0, sizeof(struct prefix)); +			ret = str2prefix(gwip, &gw_ip); +			if (!ret) { +				vty_out(vty, "%% Malformed GatewayIp%s", +					VTY_NEWLINE); +				return CMD_WARNING; +			} +			if ((gw_ip.family == AF_INET +			     && (p.u.prefix_evpn.flags & IP_PREFIX_V6)) +			    || (gw_ip.family == AF_INET6 +				&& (p.u.prefix_evpn.flags & IP_PREFIX_V4))) { +				vty_out(vty, +					"%% GatewayIp family differs with IP prefix%s", +					VTY_NEWLINE); +				return CMD_WARNING; +			} +		} +	} +	prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd); +	if (prn->info == NULL) +		prn->info = bgp_table_init(afi, safi); +	else +		bgp_unlock_node(prn); +	table = prn->info; + +	rn = bgp_node_get(table, &p); + +	if (rn->info) { +		vty_out(vty, "%% Same network configuration exists%s", +			VTY_NEWLINE); +		bgp_unlock_node(rn); +	} else { +		/* New configuration. */ +		bgp_static = bgp_static_new(); +		bgp_static->backdoor = 0; +		bgp_static->valid = 0; +		bgp_static->igpmetric = 0; +		bgp_static->igpnexthop.s_addr = 0; +		memcpy(bgp_static->tag, tag, 3); +		bgp_static->prd = prd; + +		if (rmap_str) { +			if (bgp_static->rmap.name) +				XFREE(MTYPE_ROUTE_MAP_NAME, +				      bgp_static->rmap.name); +			bgp_static->rmap.name = +				XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str); +			bgp_static->rmap.map = +				route_map_lookup_by_name(rmap_str); +		} -  rn = bgp_node_get (table, &p); +		if (safi == SAFI_EVPN) { +			if (esi) { +				bgp_static->eth_s_id = +					XCALLOC(MTYPE_ATTR, +						sizeof(struct eth_segment_id)); +				str2esi(esi, bgp_static->eth_s_id); +			} +			if (routermac) { +				bgp_static->router_mac = +					XCALLOC(MTYPE_ATTR, ETHER_ADDR_LEN + 1); +				prefix_str2mac(routermac, +					       bgp_static->router_mac); +			} +			if (gwip) +				prefix_copy(&bgp_static->gatewayIp, &gw_ip); +		} +		rn->info = bgp_static; -  if (rn->info) -    { -      vty_out (vty, "%% Same network configuration exists%s", VTY_NEWLINE); -      bgp_unlock_node (rn); -    } -  else -    { -      /* New configuration. */ -      bgp_static = bgp_static_new (); -      bgp_static->backdoor = 0; -      bgp_static->valid = 0; -      bgp_static->igpmetric = 0; -      bgp_static->igpnexthop.s_addr = 0; -      memcpy(bgp_static->tag, tag, 3); -      bgp_static->prd = prd; - -      if (rmap_str) -	{ -	  if (bgp_static->rmap.name) -	    XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name); -	  bgp_static->rmap.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str); -	  bgp_static->rmap.map = route_map_lookup_by_name (rmap_str); -	} - -      if (safi == SAFI_EVPN) -        { -          if(esi) -            { -              bgp_static->eth_s_id = XCALLOC (MTYPE_ATTR, sizeof(struct eth_segment_id)); -              str2esi (esi, bgp_static->eth_s_id); -            } -          if( routermac) -            { -              bgp_static->router_mac = XCALLOC (MTYPE_ATTR, ETHER_ADDR_LEN+1); -              prefix_str2mac (routermac, bgp_static->router_mac); -            } -          if (gwip) -            prefix_copy (&bgp_static->gatewayIp, &gw_ip); -        } -      rn->info = bgp_static; - -      bgp_static->valid = 1; -      bgp_static_update_safi (bgp, &p, bgp_static, afi, safi); -    } +		bgp_static->valid = 1; +		bgp_static_update_safi(bgp, &p, bgp_static, afi, safi); +	} -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  /* Configure static BGP network. */ -int -bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty, const char *ip_str, -                      const char *rd_str, const char *label_str, -                      int evpn_type, const char *esi, const char *gwip, const char *ethtag) -{ -  VTY_DECLVAR_CONTEXT(bgp, bgp); -  int ret; -  struct prefix p; -  struct prefix_rd prd; -  struct bgp_node *prn; -  struct bgp_node *rn; -  struct bgp_table *table; -  struct bgp_static *bgp_static; -  u_char tag[3]; - -  /* Convert IP prefix string to struct prefix. */ -  ret = str2prefix (ip_str, &p); -  if (! ret) -    { -      vty_out (vty, "%% Malformed prefix%s", VTY_NEWLINE); -      return CMD_WARNING; -    } -  apply_mask (&p); -  if ( (afi == AFI_L2VPN) && -       (bgp_build_evpn_prefix ( evpn_type, ethtag!=NULL?atol(ethtag):0, &p))) -    { -      vty_out (vty, "%% L2VPN prefix could not be forged%s", VTY_NEWLINE); -      return CMD_WARNING; -    } -  ret = str2prefix_rd (rd_str, &prd); -  if (! ret) -    { -      vty_out (vty, "%% Malformed rd%s", VTY_NEWLINE); -      return CMD_WARNING; -    } - -  if (label_str) -    { -      unsigned long label_val; -      VTY_GET_INTEGER_RANGE("Label/tag", label_val, label_str, 0, MPLS_LABEL_MAX); -      encode_label (label_val, tag); -    } -  else -    { -      memset (tag, 0, sizeof(tag)); /* empty, not even BoS */ -    } - -  prn = bgp_node_get (bgp->route[afi][safi], -			(struct prefix *)&prd); -  if (prn->info == NULL) -    prn->info = bgp_table_init (afi, safi); -  else -    bgp_unlock_node (prn); -  table = prn->info; - -  rn = bgp_node_lookup (table, &p); +int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty, +			  const char *ip_str, const char *rd_str, +			  const char *label_str, int evpn_type, const char *esi, +			  const char *gwip, const char *ethtag) +{ +	VTY_DECLVAR_CONTEXT(bgp, bgp); +	int ret; +	struct prefix p; +	struct prefix_rd prd; +	struct bgp_node *prn; +	struct bgp_node *rn; +	struct bgp_table *table; +	struct bgp_static *bgp_static; +	u_char tag[3]; + +	/* Convert IP prefix string to struct prefix. */ +	ret = str2prefix(ip_str, &p); +	if (!ret) { +		vty_out(vty, "%% Malformed prefix%s", VTY_NEWLINE); +		return CMD_WARNING; +	} +	apply_mask(&p); +	if ((afi == AFI_L2VPN) +	    && (bgp_build_evpn_prefix(evpn_type, +				      ethtag != NULL ? atol(ethtag) : 0, &p))) { +		vty_out(vty, "%% L2VPN prefix could not be forged%s", +			VTY_NEWLINE); +		return CMD_WARNING; +	} +	ret = str2prefix_rd(rd_str, &prd); +	if (!ret) { +		vty_out(vty, "%% Malformed rd%s", VTY_NEWLINE); +		return CMD_WARNING; +	} -  if (rn) -    { -      bgp_static_withdraw_safi (bgp, &p, afi, safi, &prd, tag); +	if (label_str) { +		unsigned long label_val; +		VTY_GET_INTEGER_RANGE("Label/tag", label_val, label_str, 0, +				      MPLS_LABEL_MAX); +		encode_label(label_val, tag); +	} else { +		memset(tag, 0, sizeof(tag)); /* empty, not even BoS */ +	} -      bgp_static = rn->info; -      bgp_static_free (bgp_static); -      rn->info = NULL; -      bgp_unlock_node (rn); -      bgp_unlock_node (rn); -    } -  else -    vty_out (vty, "%% Can't find the route%s", VTY_NEWLINE); +	prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd); +	if (prn->info == NULL) +		prn->info = bgp_table_init(afi, safi); +	else +		bgp_unlock_node(prn); +	table = prn->info; -  return CMD_SUCCESS; -} +	rn = bgp_node_lookup(table, &p); -static int -bgp_table_map_set (struct vty *vty, afi_t afi, safi_t safi, -                   const char *rmap_name) -{ -  VTY_DECLVAR_CONTEXT(bgp, bgp); -  struct bgp_rmap *rmap; +	if (rn) { +		bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd, tag); -  rmap = &bgp->table_map[afi][safi]; -  if (rmap_name) -    { -      if (rmap->name) -        XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name); -      rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name); -      rmap->map = route_map_lookup_by_name (rmap_name); -    } -  else -    { -      if (rmap->name) -        XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name); -      rmap->name = NULL; -      rmap->map = NULL; -    } +		bgp_static = rn->info; +		bgp_static_free(bgp_static); +		rn->info = NULL; +		bgp_unlock_node(rn); +		bgp_unlock_node(rn); +	} else +		vty_out(vty, "%% Can't find the route%s", VTY_NEWLINE); + +	return CMD_SUCCESS; +} + +static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi, +			     const char *rmap_name) +{ +	VTY_DECLVAR_CONTEXT(bgp, bgp); +	struct bgp_rmap *rmap; + +	rmap = &bgp->table_map[afi][safi]; +	if (rmap_name) { +		if (rmap->name) +			XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name); +		rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name); +		rmap->map = route_map_lookup_by_name(rmap_name); +	} else { +		if (rmap->name) +			XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name); +		rmap->name = NULL; +		rmap->map = NULL; +	} -  bgp_zebra_announce_table(bgp, afi, safi); +	bgp_zebra_announce_table(bgp, afi, safi); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  } -static int -bgp_table_map_unset (struct vty *vty, afi_t afi, safi_t safi, -                     const char *rmap_name) +static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi, +			       const char *rmap_name)  { -  VTY_DECLVAR_CONTEXT(bgp, bgp); -  struct bgp_rmap *rmap; +	VTY_DECLVAR_CONTEXT(bgp, bgp); +	struct bgp_rmap *rmap; -  rmap = &bgp->table_map[afi][safi]; -  if (rmap->name) -    XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name); -  rmap->name = NULL; -  rmap->map = NULL; +	rmap = &bgp->table_map[afi][safi]; +	if (rmap->name) +		XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name); +	rmap->name = NULL; +	rmap->map = NULL; -  bgp_zebra_announce_table(bgp, afi, safi); +	bgp_zebra_announce_table(bgp, afi, safi); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  } -int -bgp_config_write_table_map (struct vty *vty, struct bgp *bgp, afi_t afi, -			   safi_t safi, int *write) +int bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi, +			       safi_t safi, int *write)  { -  if (bgp->table_map[afi][safi].name) -    { -      bgp_config_write_family_header (vty, afi, safi, write); -      vty_out (vty, "  table-map %s%s", -	       bgp->table_map[afi][safi].name, VTY_NEWLINE); -    } +	if (bgp->table_map[afi][safi].name) { +		bgp_config_write_family_header(vty, afi, safi, write); +		vty_out(vty, "  table-map %s%s", bgp->table_map[afi][safi].name, +			VTY_NEWLINE); +	} -  return 0; +	return 0;  }  DEFUN (bgp_table_map, @@ -4727,9 +4672,9 @@ DEFUN (bgp_table_map,         "BGP table to RIB route download filter\n"         "Name of the route map\n")  { -  int idx_word = 1; -  return bgp_table_map_set (vty, -             bgp_node_afi (vty), bgp_node_safi (vty), argv[idx_word]->arg); +	int idx_word = 1; +	return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty), +				 argv[idx_word]->arg);  }  DEFUN (no_bgp_table_map,         no_bgp_table_map_cmd, @@ -4738,9 +4683,9 @@ DEFUN (no_bgp_table_map,         "BGP table to RIB route download filter\n"         "Name of the route map\n")  { -  int idx_word = 2; -  return bgp_table_map_unset (vty, -             bgp_node_afi (vty), bgp_node_safi (vty), argv[idx_word]->arg); +	int idx_word = 2; +	return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty), +				   argv[idx_word]->arg);  }  DEFUN (bgp_network, @@ -4749,9 +4694,9 @@ DEFUN (bgp_network,         "Specify a network to announce via BGP\n"         "IPv4 prefix\n")  { -  int idx_ipv4_prefixlen = 1; -  return bgp_static_set (vty, argv[idx_ipv4_prefixlen]->arg, -			 AFI_IP, bgp_node_safi (vty), NULL, 0); +	int idx_ipv4_prefixlen = 1; +	return bgp_static_set(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP, +			      bgp_node_safi(vty), NULL, 0);  }  DEFUN (bgp_network_route_map, @@ -4762,10 +4707,10 @@ DEFUN (bgp_network_route_map,         "Route-map to modify the attributes\n"         "Name of the route map\n")  { -  int idx_ipv4_prefixlen = 1; -  int idx_word = 3; -  return bgp_static_set (vty, argv[idx_ipv4_prefixlen]->arg, -			 AFI_IP, bgp_node_safi (vty), argv[idx_word]->arg, 0); +	int idx_ipv4_prefixlen = 1; +	int idx_word = 3; +	return bgp_static_set(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP, +			      bgp_node_safi(vty), argv[idx_word]->arg, 0);  }  DEFUN (bgp_network_backdoor, @@ -4775,9 +4720,9 @@ DEFUN (bgp_network_backdoor,         "IPv4 prefix\n"         "Specify a BGP backdoor route\n")  { -  int idx_ipv4_prefixlen = 1; -  return bgp_static_set (vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP, SAFI_UNICAST, -                         NULL, 1); +	int idx_ipv4_prefixlen = 1; +	return bgp_static_set(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP, +			      SAFI_UNICAST, NULL, 1);  }  DEFUN (bgp_network_mask, @@ -4788,20 +4733,20 @@ DEFUN (bgp_network_mask,         "Network mask\n"         "Network mask\n")  { -  int idx_ipv4 = 1; -  int idx_ipv4_2 = 3; -  int ret; -  char prefix_str[BUFSIZ]; -   -  ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, prefix_str); -  if (! ret) -    { -      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +	int idx_ipv4 = 1; +	int idx_ipv4_2 = 3; +	int ret; +	char prefix_str[BUFSIZ]; -  return bgp_static_set (vty, prefix_str, -			 AFI_IP, bgp_node_safi (vty), NULL, 0); +	ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, +				     prefix_str); +	if (!ret) { +		vty_out(vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); +		return CMD_WARNING; +	} + +	return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty), NULL, +			      0);  }  DEFUN (bgp_network_mask_route_map, @@ -4814,21 +4759,21 @@ DEFUN (bgp_network_mask_route_map,         "Route-map to modify the attributes\n"         "Name of the route map\n")  { -  int idx_ipv4 = 1; -  int idx_ipv4_2 = 3; -  int idx_word = 5; -  int ret; -  char prefix_str[BUFSIZ]; -   -  ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, prefix_str); -  if (! ret) -    { -      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +	int idx_ipv4 = 1; +	int idx_ipv4_2 = 3; +	int idx_word = 5; +	int ret; +	char prefix_str[BUFSIZ]; + +	ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, +				     prefix_str); +	if (!ret) { +		vty_out(vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); +		return CMD_WARNING; +	} -  return bgp_static_set (vty, prefix_str, -			 AFI_IP, bgp_node_safi (vty), argv[idx_word]->arg, 0); +	return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty), +			      argv[idx_word]->arg, 0);  }  DEFUN (bgp_network_mask_backdoor, @@ -4840,20 +4785,19 @@ DEFUN (bgp_network_mask_backdoor,         "Network mask\n"         "Specify a BGP backdoor route\n")  { -  int idx_ipv4 = 1; -  int idx_ipv4_2 = 3; -  int ret; -  char prefix_str[BUFSIZ]; -   -  ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, prefix_str); -  if (! ret) -    { -      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +	int idx_ipv4 = 1; +	int idx_ipv4_2 = 3; +	int ret; +	char prefix_str[BUFSIZ]; + +	ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, +				     prefix_str); +	if (!ret) { +		vty_out(vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); +		return CMD_WARNING; +	} -  return bgp_static_set (vty, prefix_str, AFI_IP, SAFI_UNICAST, -                         NULL, 1); +	return bgp_static_set(vty, prefix_str, AFI_IP, SAFI_UNICAST, NULL, 1);  }  DEFUN (bgp_network_mask_natural, @@ -4862,19 +4806,18 @@ DEFUN (bgp_network_mask_natural,         "Specify a network to announce via BGP\n"         "Network number\n")  { -  int idx_ipv4 = 1; -  int ret; -  char prefix_str[BUFSIZ]; +	int idx_ipv4 = 1; +	int ret; +	char prefix_str[BUFSIZ]; -  ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, NULL, prefix_str); -  if (! ret) -    { -      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +	ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str); +	if (!ret) { +		vty_out(vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); +		return CMD_WARNING; +	} -  return bgp_static_set (vty, prefix_str, -			 AFI_IP, bgp_node_safi (vty), NULL, 0); +	return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty), NULL, +			      0);  }  DEFUN (bgp_network_mask_natural_route_map, @@ -4885,20 +4828,19 @@ DEFUN (bgp_network_mask_natural_route_map,         "Route-map to modify the attributes\n"         "Name of the route map\n")  { -  int idx_ipv4 = 1; -  int idx_word = 3; -  int ret; -  char prefix_str[BUFSIZ]; +	int idx_ipv4 = 1; +	int idx_word = 3; +	int ret; +	char prefix_str[BUFSIZ]; -  ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, NULL, prefix_str); -  if (! ret) -    { -      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +	ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str); +	if (!ret) { +		vty_out(vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); +		return CMD_WARNING; +	} -  return bgp_static_set (vty, prefix_str, -			 AFI_IP, bgp_node_safi (vty), argv[idx_word]->arg, 0); +	return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty), +			      argv[idx_word]->arg, 0);  }  DEFUN (bgp_network_mask_natural_backdoor, @@ -4908,19 +4850,17 @@ DEFUN (bgp_network_mask_natural_backdoor,         "Network number\n"         "Specify a BGP backdoor route\n")  { -  int idx_ipv4 = 1; -  int ret; -  char prefix_str[BUFSIZ]; +	int idx_ipv4 = 1; +	int ret; +	char prefix_str[BUFSIZ]; -  ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, NULL, prefix_str); -  if (! ret) -    { -      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +	ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str); +	if (!ret) { +		vty_out(vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); +		return CMD_WARNING; +	} -  return bgp_static_set (vty, prefix_str, AFI_IP, SAFI_UNICAST, -                         NULL, 1); +	return bgp_static_set(vty, prefix_str, AFI_IP, SAFI_UNICAST, NULL, 1);  }  DEFUN (no_bgp_network, @@ -4933,9 +4873,9 @@ DEFUN (no_bgp_network,         "Route-map to modify the attributes\n"         "Name of the route map\n")  { -  int idx_ipv4_prefixlen = 2; -  return bgp_static_unset (vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP,  -			   bgp_node_safi (vty)); +	int idx_ipv4_prefixlen = 2; +	return bgp_static_unset(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP, +				bgp_node_safi(vty));  }  DEFUN (no_bgp_network_mask, @@ -4950,20 +4890,19 @@ DEFUN (no_bgp_network_mask,         "Route-map to modify the attributes\n"         "Name of the route map\n")  { -  int idx_ipv4 = 2; -  int idx_ipv4_2 = 4; -  int ret; -  char prefix_str[BUFSIZ]; +	int idx_ipv4 = 2; +	int idx_ipv4_2 = 4; +	int ret; +	char prefix_str[BUFSIZ]; -  ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, prefix_str); -  if (! ret) -    { -      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +	ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, +				     prefix_str); +	if (!ret) { +		vty_out(vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); +		return CMD_WARNING; +	} -  return bgp_static_unset (vty, prefix_str, AFI_IP,  -			   bgp_node_safi (vty)); +	return bgp_static_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));  }  DEFUN (no_bgp_network_mask_natural, @@ -4976,19 +4915,17 @@ DEFUN (no_bgp_network_mask_natural,         "Route-map to modify the attributes\n"         "Name of the route map\n")  { -  int idx_ipv4 = 2; -  int ret; -  char prefix_str[BUFSIZ]; +	int idx_ipv4 = 2; +	int ret; +	char prefix_str[BUFSIZ]; -  ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, NULL, prefix_str); -  if (! ret) -    { -      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +	ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str); +	if (!ret) { +		vty_out(vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); +		return CMD_WARNING; +	} -  return bgp_static_unset (vty, prefix_str, AFI_IP,  -			   bgp_node_safi (vty)); +	return bgp_static_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));  }  DEFUN (ipv6_bgp_network, @@ -4997,9 +4934,9 @@ DEFUN (ipv6_bgp_network,         "Specify a network to announce via BGP\n"         "IPv6 prefix\n")  { -  int idx_ipv6_prefixlen = 1; -  return bgp_static_set (vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, bgp_node_safi(vty), -                         NULL, 0); +	int idx_ipv6_prefixlen = 1; +	return bgp_static_set(vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, +			      bgp_node_safi(vty), NULL, 0);  }  DEFUN (ipv6_bgp_network_route_map, @@ -5010,10 +4947,10 @@ DEFUN (ipv6_bgp_network_route_map,         "Route-map to modify the attributes\n"         "Name of the route map\n")  { -  int idx_ipv6_prefixlen = 1; -  int idx_word = 3; -  return bgp_static_set (vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, -			 bgp_node_safi (vty), argv[idx_word]->arg, 0); +	int idx_ipv6_prefixlen = 1; +	int idx_word = 3; +	return bgp_static_set(vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, +			      bgp_node_safi(vty), argv[idx_word]->arg, 0);  }  DEFUN (no_ipv6_bgp_network, @@ -5025,8 +4962,9 @@ DEFUN (no_ipv6_bgp_network,         "Route-map to modify the attributes\n"         "Name of the route map\n")  { -  int idx_ipv6_prefixlen = 2; -  return bgp_static_unset (vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, bgp_node_safi(vty)); +	int idx_ipv6_prefixlen = 2; +	return bgp_static_unset(vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, +				bgp_node_safi(vty));  }  /* Aggreagete address: @@ -5039,589 +4977,583 @@ DEFUN (no_ipv6_bgp_network,    suppress-map   Conditionally filter more specific routes from updates    <cr>   */ -struct bgp_aggregate -{ -  /* Summary-only flag. */ -  u_char summary_only; +struct bgp_aggregate { +	/* Summary-only flag. */ +	u_char summary_only; -  /* AS set generation. */ -  u_char as_set; +	/* AS set generation. */ +	u_char as_set; -  /* Route-map for aggregated route. */ -  struct route_map *map; +	/* Route-map for aggregated route. */ +	struct route_map *map; -  /* Suppress-count. */ -  unsigned long count; +	/* Suppress-count. */ +	unsigned long count; -  /* SAFI configuration. */ -  safi_t safi; +	/* SAFI configuration. */ +	safi_t safi;  }; -static struct bgp_aggregate * -bgp_aggregate_new (void) +static struct bgp_aggregate *bgp_aggregate_new(void)  { -  return XCALLOC (MTYPE_BGP_AGGREGATE, sizeof (struct bgp_aggregate)); +	return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));  } -static void -bgp_aggregate_free (struct bgp_aggregate *aggregate) +static void bgp_aggregate_free(struct bgp_aggregate *aggregate)  { -  XFREE (MTYPE_BGP_AGGREGATE, aggregate); -}      +	XFREE(MTYPE_BGP_AGGREGATE, aggregate); +}  /* Update an aggregate as routes are added/removed from the BGP table */ -static void -bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew, -		     afi_t afi, safi_t safi, struct bgp_info *del,  -		     struct bgp_aggregate *aggregate) -{ -  struct bgp_table *table; -  struct bgp_node *top; -  struct bgp_node *rn; -  u_char origin; -  struct aspath *aspath = NULL; -  struct aspath *asmerge = NULL; -  struct community *community = NULL; -  struct community *commerge = NULL; +static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, +				struct bgp_info *rinew, afi_t afi, safi_t safi, +				struct bgp_info *del, +				struct bgp_aggregate *aggregate) +{ +	struct bgp_table *table; +	struct bgp_node *top; +	struct bgp_node *rn; +	u_char origin; +	struct aspath *aspath = NULL; +	struct aspath *asmerge = NULL; +	struct community *community = NULL; +	struct community *commerge = NULL;  #if defined(AGGREGATE_NEXTHOP_CHECK) -  struct in_addr nexthop; -  u_int32_t med = 0; +	struct in_addr nexthop; +	u_int32_t med = 0;  #endif -  struct bgp_info *ri; -  struct bgp_info *new; -  int first = 1; -  unsigned long match = 0; -  u_char atomic_aggregate = 0; - -  /* Record adding route's nexthop and med. */ - if (rinew) -   { +	struct bgp_info *ri; +	struct bgp_info *new; +	int first = 1; +	unsigned long match = 0; +	u_char atomic_aggregate = 0; + +	/* Record adding route's nexthop and med. */ +	if (rinew) {  #if defined(AGGREGATE_NEXTHOP_CHECK) -     nexthop = rinew->attr->nexthop; -     med = rinew->attr->med; +		nexthop = rinew->attr->nexthop; +		med = rinew->attr->med;  #endif -   } - -  /* ORIGIN attribute: If at least one route among routes that are -     aggregated has ORIGIN with the value INCOMPLETE, then the -     aggregated route must have the ORIGIN attribute with the value -     INCOMPLETE. Otherwise, if at least one route among routes that -     are aggregated has ORIGIN with the value EGP, then the aggregated -     route must have the origin attribute with the value EGP. In all -     other case the value of the ORIGIN attribute of the aggregated -     route is INTERNAL. */ -  origin = BGP_ORIGIN_IGP; - -  table = bgp->rib[afi][safi]; - -  top = bgp_node_get (table, p); -  for (rn = bgp_node_get (table, p); rn; rn = bgp_route_next_until (rn, top)) -    if (rn->p.prefixlen > p->prefixlen) -      { -	match = 0; +	} -	for (ri = rn->info; ri; ri = ri->next) -	  { -	    if (BGP_INFO_HOLDDOWN (ri)) -	      continue; +	/* ORIGIN attribute: If at least one route among routes that are +	   aggregated has ORIGIN with the value INCOMPLETE, then the +	   aggregated route must have the ORIGIN attribute with the value +	   INCOMPLETE. Otherwise, if at least one route among routes that +	   are aggregated has ORIGIN with the value EGP, then the aggregated +	   route must have the origin attribute with the value EGP. In all +	   other case the value of the ORIGIN attribute of the aggregated +	   route is INTERNAL. */ +	origin = BGP_ORIGIN_IGP; + +	table = bgp->rib[afi][safi]; -	    if (del && ri == del) -	      continue; +	top = bgp_node_get(table, p); +	for (rn = bgp_node_get(table, p); rn; +	     rn = bgp_route_next_until(rn, top)) +		if (rn->p.prefixlen > p->prefixlen) { +			match = 0; -	    if (! rinew && first) -	      { +			for (ri = rn->info; ri; ri = ri->next) { +				if (BGP_INFO_HOLDDOWN(ri)) +					continue; + +				if (del && ri == del) +					continue; + +				if (!rinew && first) {  #if defined(AGGREGATE_NEXTHOP_CHECK) -		nexthop = ri->attr->nexthop; -		med = ri->attr->med; +					nexthop = ri->attr->nexthop; +					med = ri->attr->med;  #endif -		first = 0; -	      } +					first = 0; +				}  #ifdef AGGREGATE_NEXTHOP_CHECK -	    if (! IPV4_ADDR_SAME (&ri->attr->nexthop, &nexthop) -		|| ri->attr->med != med) -	      { -		if (aspath) -		  aspath_free (aspath); -		if (community) -		  community_free (community); -		bgp_unlock_node (rn); -		bgp_unlock_node (top); -		return; -	      } +				if (!IPV4_ADDR_SAME(&ri->attr->nexthop, +						    &nexthop) +				    || ri->attr->med != med) { +					if (aspath) +						aspath_free(aspath); +					if (community) +						community_free(community); +					bgp_unlock_node(rn); +					bgp_unlock_node(top); +					return; +				}  #endif /* AGGREGATE_NEXTHOP_CHECK */ -            if (ri->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) -              atomic_aggregate = 1; - -	    if (ri->sub_type != BGP_ROUTE_AGGREGATE) -	      { -		if (aggregate->summary_only) -		  { -		    (bgp_info_extra_get (ri))->suppress++; -		    bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED); -		    match++; -		  } +				if (ri->attr->flag +				    & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) +					atomic_aggregate = 1; + +				if (ri->sub_type != BGP_ROUTE_AGGREGATE) { +					if (aggregate->summary_only) { +						(bgp_info_extra_get(ri)) +							->suppress++; +						bgp_info_set_flag( +							rn, ri, +							BGP_INFO_ATTR_CHANGED); +						match++; +					} + +					aggregate->count++; + +					if (origin < ri->attr->origin) +						origin = ri->attr->origin; + +					if (aggregate->as_set) { +						if (aspath) { +							asmerge = aspath_aggregate( +								aspath, +								ri->attr->aspath); +							aspath_free(aspath); +							aspath = asmerge; +						} else +							aspath = aspath_dup( +								ri->attr->aspath); + +						if (ri->attr->community) { +							if (community) { +								commerge = community_merge( +									community, +									ri->attr->community); +								community = community_uniq_sort( +									commerge); +								community_free( +									commerge); +							} else +								community = community_dup( +									ri->attr->community); +						} +					} +				} +			} +			if (match) +				bgp_process(bgp, rn, afi, safi); +		} +	bgp_unlock_node(top); +	if (rinew) {  		aggregate->count++; -		if (origin < ri->attr->origin) -		  origin = ri->attr->origin; - -		if (aggregate->as_set) -		  { -		    if (aspath) -		      { -			asmerge = aspath_aggregate (aspath, ri->attr->aspath); -			aspath_free (aspath); -			aspath = asmerge; -		      } -		    else -		      aspath = aspath_dup (ri->attr->aspath); - -		    if (ri->attr->community) -		      { -			if (community) -			  { -			    commerge = community_merge (community, -							ri->attr->community); -			    community = community_uniq_sort (commerge); -			    community_free (commerge); -			  } -			else -			  community = community_dup (ri->attr->community); -		      } -		  } -	      } -	  } -	if (match) -	  bgp_process (bgp, rn, afi, safi); -      } -  bgp_unlock_node (top); - -  if (rinew) -    { -      aggregate->count++; -       -      if (aggregate->summary_only) -        (bgp_info_extra_get (rinew))->suppress++; - -      if (origin < rinew->attr->origin) -        origin = rinew->attr->origin; - -      if (aggregate->as_set) -	{ -	  if (aspath) -	    { -	      asmerge = aspath_aggregate (aspath, rinew->attr->aspath); -	      aspath_free (aspath); -	      aspath = asmerge; -	    } -	  else -	    aspath = aspath_dup (rinew->attr->aspath); - -	  if (rinew->attr->community) -	    { -	      if (community) -		{ -		  commerge = community_merge (community, -					      rinew->attr->community); -		  community = community_uniq_sort (commerge); -		  community_free (commerge); +		if (aggregate->summary_only) +			(bgp_info_extra_get(rinew))->suppress++; + +		if (origin < rinew->attr->origin) +			origin = rinew->attr->origin; + +		if (aggregate->as_set) { +			if (aspath) { +				asmerge = aspath_aggregate(aspath, +							   rinew->attr->aspath); +				aspath_free(aspath); +				aspath = asmerge; +			} else +				aspath = aspath_dup(rinew->attr->aspath); + +			if (rinew->attr->community) { +				if (community) { +					commerge = community_merge( +						community, +						rinew->attr->community); +					community = +						community_uniq_sort(commerge); +					community_free(commerge); +				} else +					community = community_dup( +						rinew->attr->community); +			}  		} -	      else -		community = community_dup (rinew->attr->community); -	    }  	} -    } -  if (aggregate->count > 0) -    { -      rn = bgp_node_get (table, p); -      new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, bgp->peer_self, -		      bgp_attr_aggregate_intern(bgp, origin, aspath, community, -						aggregate->as_set, -                                                atomic_aggregate), rn); -      SET_FLAG (new->flags, BGP_INFO_VALID); - -      bgp_info_add (rn, new); -      bgp_unlock_node (rn); -      bgp_process (bgp, rn, afi, safi); -    } -  else -    { -      if (aspath) -	aspath_free (aspath); -      if (community) -	community_free (community); -    } +	if (aggregate->count > 0) { +		rn = bgp_node_get(table, p); +		new = info_make( +			ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, bgp->peer_self, +			bgp_attr_aggregate_intern(bgp, origin, aspath, +						  community, aggregate->as_set, +						  atomic_aggregate), +			rn); +		SET_FLAG(new->flags, BGP_INFO_VALID); + +		bgp_info_add(rn, new); +		bgp_unlock_node(rn); +		bgp_process(bgp, rn, afi, safi); +	} else { +		if (aspath) +			aspath_free(aspath); +		if (community) +			community_free(community); +	}  } -void bgp_aggregate_delete (struct bgp *, struct prefix *, afi_t, safi_t, -			   struct bgp_aggregate *); +void bgp_aggregate_delete(struct bgp *, struct prefix *, afi_t, safi_t, +			  struct bgp_aggregate *); -void -bgp_aggregate_increment (struct bgp *bgp, struct prefix *p, -			 struct bgp_info *ri, afi_t afi, safi_t safi) +void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p, +			     struct bgp_info *ri, afi_t afi, safi_t safi)  { -  struct bgp_node *child; -  struct bgp_node *rn; -  struct bgp_aggregate *aggregate; -  struct bgp_table *table; +	struct bgp_node *child; +	struct bgp_node *rn; +	struct bgp_aggregate *aggregate; +	struct bgp_table *table; -  /* MPLS-VPN aggregation is not yet supported. */ -  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN)) -    return; +	/* MPLS-VPN aggregation is not yet supported. */ +	if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) +	    || (safi == SAFI_EVPN)) +		return; -  table = bgp->aggregate[afi][safi]; +	table = bgp->aggregate[afi][safi]; -  /* No aggregates configured. */ -  if (bgp_table_top_nolock (table) == NULL) -    return; +	/* No aggregates configured. */ +	if (bgp_table_top_nolock(table) == NULL) +		return; -  if (p->prefixlen == 0) -    return; +	if (p->prefixlen == 0) +		return; -  if (BGP_INFO_HOLDDOWN (ri)) -    return; +	if (BGP_INFO_HOLDDOWN(ri)) +		return; -  child = bgp_node_get (table, p); +	child = bgp_node_get(table, p); -  /* Aggregate address configuration check. */ -  for (rn = child; rn; rn = bgp_node_parent_nolock (rn)) -    if ((aggregate = rn->info) != NULL && rn->p.prefixlen < p->prefixlen) -      { -	bgp_aggregate_delete (bgp, &rn->p, afi, safi, aggregate); -	bgp_aggregate_route (bgp, &rn->p, ri, afi, safi, NULL, aggregate); -      } -  bgp_unlock_node (child); +	/* Aggregate address configuration check. */ +	for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) +		if ((aggregate = rn->info) != NULL +		    && rn->p.prefixlen < p->prefixlen) { +			bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate); +			bgp_aggregate_route(bgp, &rn->p, ri, afi, safi, NULL, +					    aggregate); +		} +	bgp_unlock_node(child);  } -void -bgp_aggregate_decrement (struct bgp *bgp, struct prefix *p,  -			 struct bgp_info *del, afi_t afi, safi_t safi) +void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p, +			     struct bgp_info *del, afi_t afi, safi_t safi)  { -  struct bgp_node *child; -  struct bgp_node *rn; -  struct bgp_aggregate *aggregate; -  struct bgp_table *table; +	struct bgp_node *child; +	struct bgp_node *rn; +	struct bgp_aggregate *aggregate; +	struct bgp_table *table; -  /* MPLS-VPN aggregation is not yet supported. */ -  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN)) -    return; +	/* MPLS-VPN aggregation is not yet supported. */ +	if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) +	    || (safi == SAFI_EVPN)) +		return; -  table = bgp->aggregate[afi][safi]; +	table = bgp->aggregate[afi][safi]; -  /* No aggregates configured. */ -  if (bgp_table_top_nolock (table) == NULL) -    return; +	/* No aggregates configured. */ +	if (bgp_table_top_nolock(table) == NULL) +		return; -  if (p->prefixlen == 0) -    return; +	if (p->prefixlen == 0) +		return; -  child = bgp_node_get (table, p); +	child = bgp_node_get(table, p); -  /* Aggregate address configuration check. */ -  for (rn = child; rn; rn = bgp_node_parent_nolock (rn)) -    if ((aggregate = rn->info) != NULL && rn->p.prefixlen < p->prefixlen) -      { -	bgp_aggregate_delete (bgp, &rn->p, afi, safi, aggregate); -	bgp_aggregate_route (bgp, &rn->p, NULL, afi, safi, del, aggregate); -      } -  bgp_unlock_node (child); +	/* Aggregate address configuration check. */ +	for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) +		if ((aggregate = rn->info) != NULL +		    && rn->p.prefixlen < p->prefixlen) { +			bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate); +			bgp_aggregate_route(bgp, &rn->p, NULL, afi, safi, del, +					    aggregate); +		} +	bgp_unlock_node(child);  }  /* Called via bgp_aggregate_set when the user configures aggregate-address */ -static void -bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi, -		   struct bgp_aggregate *aggregate) -{ -  struct bgp_table *table; -  struct bgp_node *top; -  struct bgp_node *rn; -  struct bgp_info *new; -  struct bgp_info *ri; -  unsigned long match; -  u_char origin = BGP_ORIGIN_IGP; -  struct aspath *aspath = NULL; -  struct aspath *asmerge = NULL; -  struct community *community = NULL; -  struct community *commerge = NULL; -  u_char atomic_aggregate = 0; - -  table = bgp->rib[afi][safi]; - -  /* Sanity check. */ -  if (afi == AFI_IP && p->prefixlen == IPV4_MAX_BITLEN) -    return; -  if (afi == AFI_IP6 && p->prefixlen == IPV6_MAX_BITLEN) -    return; -     -  /* If routes exists below this node, generate aggregate routes. */ -  top = bgp_node_get (table, p); -  for (rn = bgp_node_get (table, p); rn; rn = bgp_route_next_until (rn, top)) -    if (rn->p.prefixlen > p->prefixlen) -      { -	match = 0; - -	for (ri = rn->info; ri; ri = ri->next) -	  { -	    if (BGP_INFO_HOLDDOWN (ri)) -	      continue; - -            if (ri->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) -              atomic_aggregate = 1; +static void bgp_aggregate_add(struct bgp *bgp, struct prefix *p, afi_t afi, +			      safi_t safi, struct bgp_aggregate *aggregate) +{ +	struct bgp_table *table; +	struct bgp_node *top; +	struct bgp_node *rn; +	struct bgp_info *new; +	struct bgp_info *ri; +	unsigned long match; +	u_char origin = BGP_ORIGIN_IGP; +	struct aspath *aspath = NULL; +	struct aspath *asmerge = NULL; +	struct community *community = NULL; +	struct community *commerge = NULL; +	u_char atomic_aggregate = 0; + +	table = bgp->rib[afi][safi]; + +	/* Sanity check. */ +	if (afi == AFI_IP && p->prefixlen == IPV4_MAX_BITLEN) +		return; +	if (afi == AFI_IP6 && p->prefixlen == IPV6_MAX_BITLEN) +		return; -	    if (ri->sub_type != BGP_ROUTE_AGGREGATE) -	      { -		/* summary-only aggregate route suppress aggregated -		   route announcement.  */ -		if (aggregate->summary_only) -		  { -		    (bgp_info_extra_get (ri))->suppress++; -		    bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED); -		    match++; -		  } - -                /* If at least one route among routes that are aggregated has -                 * ORIGIN with the value INCOMPLETE, then the aggregated route -                 * MUST have the ORIGIN attribute with the value INCOMPLETE. -                 * Otherwise, if at least one route among routes that are -                 * aggregated has ORIGIN with the value EGP, then the aggregated -                 * route MUST have the ORIGIN attribute with the value EGP. -                 */ -                if (origin < ri->attr->origin) -                    origin = ri->attr->origin; - -		/* as-set aggregate route generate origin, as path, -		   community aggregation.  */ -		if (aggregate->as_set) -		  { -		    if (aspath) -		      { -			asmerge = aspath_aggregate (aspath, ri->attr->aspath); -			aspath_free (aspath); -			aspath = asmerge; -		      } -		    else -		      aspath = aspath_dup (ri->attr->aspath); - -		    if (ri->attr->community) -		      { -			if (community) -			  { -			    commerge = community_merge (community, -							ri->attr->community); -			    community = community_uniq_sort (commerge); -			    community_free (commerge); -			  } -			else -			  community = community_dup (ri->attr->community); -		      } -		  } -		aggregate->count++; -	      } -	  } -	 -	/* If this node is suppressed, process the change. */ -	if (match) -	  bgp_process (bgp, rn, afi, safi); -      } -  bgp_unlock_node (top); - -  /* Add aggregate route to BGP table. */ -  if (aggregate->count) -    { -      rn = bgp_node_get (table, p); -      new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, bgp->peer_self, -		      bgp_attr_aggregate_intern(bgp, origin, aspath, community, -						aggregate->as_set, -                                                atomic_aggregate), rn); -      SET_FLAG (new->flags, BGP_INFO_VALID); - -      bgp_info_add (rn, new); -      bgp_unlock_node (rn); -       -      /* Process change. */ -      bgp_process (bgp, rn, afi, safi); -    } -  else -    { -      if (aspath) -	aspath_free (aspath); -      if (community) -	community_free (community); -    } +	/* If routes exists below this node, generate aggregate routes. */ +	top = bgp_node_get(table, p); +	for (rn = bgp_node_get(table, p); rn; +	     rn = bgp_route_next_until(rn, top)) +		if (rn->p.prefixlen > p->prefixlen) { +			match = 0; + +			for (ri = rn->info; ri; ri = ri->next) { +				if (BGP_INFO_HOLDDOWN(ri)) +					continue; + +				if (ri->attr->flag +				    & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) +					atomic_aggregate = 1; + +				if (ri->sub_type != BGP_ROUTE_AGGREGATE) { +					/* summary-only aggregate route suppress +					   aggregated +					   route announcement.  */ +					if (aggregate->summary_only) { +						(bgp_info_extra_get(ri)) +							->suppress++; +						bgp_info_set_flag( +							rn, ri, +							BGP_INFO_ATTR_CHANGED); +						match++; +					} + +					/* If at least one route among routes +					 * that are aggregated has +					 * ORIGIN with the value INCOMPLETE, +					 * then the aggregated route +					 * MUST have the ORIGIN attribute with +					 * the value INCOMPLETE. +					 * Otherwise, if at least one route +					 * among routes that are +					 * aggregated has ORIGIN with the value +					 * EGP, then the aggregated +					 * route MUST have the ORIGIN attribute +					 * with the value EGP. +					 */ +					if (origin < ri->attr->origin) +						origin = ri->attr->origin; + +					/* as-set aggregate route generate +					   origin, as path, +					   community aggregation.  */ +					if (aggregate->as_set) { +						if (aspath) { +							asmerge = aspath_aggregate( +								aspath, +								ri->attr->aspath); +							aspath_free(aspath); +							aspath = asmerge; +						} else +							aspath = aspath_dup( +								ri->attr->aspath); + +						if (ri->attr->community) { +							if (community) { +								commerge = community_merge( +									community, +									ri->attr->community); +								community = community_uniq_sort( +									commerge); +								community_free( +									commerge); +							} else +								community = community_dup( +									ri->attr->community); +						} +					} +					aggregate->count++; +				} +			} + +			/* If this node is suppressed, process the change. */ +			if (match) +				bgp_process(bgp, rn, afi, safi); +		} +	bgp_unlock_node(top); + +	/* Add aggregate route to BGP table. */ +	if (aggregate->count) { +		rn = bgp_node_get(table, p); +		new = info_make( +			ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, bgp->peer_self, +			bgp_attr_aggregate_intern(bgp, origin, aspath, +						  community, aggregate->as_set, +						  atomic_aggregate), +			rn); +		SET_FLAG(new->flags, BGP_INFO_VALID); + +		bgp_info_add(rn, new); +		bgp_unlock_node(rn); + +		/* Process change. */ +		bgp_process(bgp, rn, afi, safi); +	} else { +		if (aspath) +			aspath_free(aspath); +		if (community) +			community_free(community); +	}  } -void -bgp_aggregate_delete (struct bgp *bgp, struct prefix *p, afi_t afi,  -		      safi_t safi, struct bgp_aggregate *aggregate) +void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi, +			  safi_t safi, struct bgp_aggregate *aggregate)  { -  struct bgp_table *table; -  struct bgp_node *top; -  struct bgp_node *rn; -  struct bgp_info *ri; -  unsigned long match; +	struct bgp_table *table; +	struct bgp_node *top; +	struct bgp_node *rn; +	struct bgp_info *ri; +	unsigned long match; -  table = bgp->rib[afi][safi]; +	table = bgp->rib[afi][safi]; -  if (afi == AFI_IP && p->prefixlen == IPV4_MAX_BITLEN) -    return; -  if (afi == AFI_IP6 && p->prefixlen == IPV6_MAX_BITLEN) -    return; +	if (afi == AFI_IP && p->prefixlen == IPV4_MAX_BITLEN) +		return; +	if (afi == AFI_IP6 && p->prefixlen == IPV6_MAX_BITLEN) +		return; + +	/* If routes exists below this node, generate aggregate routes. */ +	top = bgp_node_get(table, p); +	for (rn = bgp_node_get(table, p); rn; +	     rn = bgp_route_next_until(rn, top)) +		if (rn->p.prefixlen > p->prefixlen) { +			match = 0; + +			for (ri = rn->info; ri; ri = ri->next) { +				if (BGP_INFO_HOLDDOWN(ri)) +					continue; + +				if (ri->sub_type != BGP_ROUTE_AGGREGATE) { +					if (aggregate->summary_only +					    && ri->extra) { +						ri->extra->suppress--; + +						if (ri->extra->suppress == 0) { +							bgp_info_set_flag( +								rn, ri, +								BGP_INFO_ATTR_CHANGED); +							match++; +						} +					} +					aggregate->count--; +				} +			} + +			/* If this node was suppressed, process the change. */ +			if (match) +				bgp_process(bgp, rn, afi, safi); +		} +	bgp_unlock_node(top); -  /* If routes exists below this node, generate aggregate routes. */ -  top = bgp_node_get (table, p); -  for (rn = bgp_node_get (table, p); rn; rn = bgp_route_next_until (rn, top)) -    if (rn->p.prefixlen > p->prefixlen) -      { -	match = 0; +	/* Delete aggregate route from BGP table. */ +	rn = bgp_node_get(table, p);  	for (ri = rn->info; ri; ri = ri->next) -	  { -	    if (BGP_INFO_HOLDDOWN (ri)) -	      continue; - -	    if (ri->sub_type != BGP_ROUTE_AGGREGATE) -	      { -		if (aggregate->summary_only && ri->extra) -		  { -		    ri->extra->suppress--; - -		    if (ri->extra->suppress == 0) -		      { -			bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED); -			match++; -		      } -		  } -		aggregate->count--; -	      } -	  } - -	/* If this node was suppressed, process the change. */ -	if (match) -	  bgp_process (bgp, rn, afi, safi); -      } -  bgp_unlock_node (top); - -  /* Delete aggregate route from BGP table. */ -  rn = bgp_node_get (table, p); - -  for (ri = rn->info; ri; ri = ri->next) -    if (ri->peer == bgp->peer_self  -	&& ri->type == ZEBRA_ROUTE_BGP -	&& ri->sub_type == BGP_ROUTE_AGGREGATE) -      break; - -  /* Withdraw static BGP route from routing table. */ -  if (ri) -    { -      bgp_info_delete (rn, ri); -      bgp_process (bgp, rn, afi, safi); -    } +		if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP +		    && ri->sub_type == BGP_ROUTE_AGGREGATE) +			break; + +	/* Withdraw static BGP route from routing table. */ +	if (ri) { +		bgp_info_delete(rn, ri); +		bgp_process(bgp, rn, afi, safi); +	} -  /* Unlock bgp_node_lookup. */ -  bgp_unlock_node (rn); +	/* Unlock bgp_node_lookup. */ +	bgp_unlock_node(rn);  }  /* Aggregate route attribute. */  #define AGGREGATE_SUMMARY_ONLY 1  #define AGGREGATE_AS_SET       1 -static int -bgp_aggregate_unset (struct vty *vty, const char *prefix_str, -                     afi_t afi, safi_t safi) +static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str, +			       afi_t afi, safi_t safi)  { -  VTY_DECLVAR_CONTEXT(bgp, bgp); -  int ret; -  struct prefix p; -  struct bgp_node *rn; -  struct bgp_aggregate *aggregate; +	VTY_DECLVAR_CONTEXT(bgp, bgp); +	int ret; +	struct prefix p; +	struct bgp_node *rn; +	struct bgp_aggregate *aggregate; -  /* Convert string to prefix structure. */ -  ret = str2prefix (prefix_str, &p); -  if (!ret) -    { -      vty_out (vty, "Malformed prefix%s", VTY_NEWLINE); -      return CMD_WARNING; -    } -  apply_mask (&p); - -  /* Old configuration check. */ -  rn = bgp_node_lookup (bgp->aggregate[afi][safi], &p); -  if (! rn) -    { -      vty_out (vty, "%% There is no aggregate-address configuration.%s", -               VTY_NEWLINE); -      return CMD_WARNING; -    } +	/* Convert string to prefix structure. */ +	ret = str2prefix(prefix_str, &p); +	if (!ret) { +		vty_out(vty, "Malformed prefix%s", VTY_NEWLINE); +		return CMD_WARNING; +	} +	apply_mask(&p); + +	/* Old configuration check. */ +	rn = bgp_node_lookup(bgp->aggregate[afi][safi], &p); +	if (!rn) { +		vty_out(vty, +			"%% There is no aggregate-address configuration.%s", +			VTY_NEWLINE); +		return CMD_WARNING; +	} -  aggregate = rn->info; -  if (aggregate->safi & SAFI_UNICAST) -    bgp_aggregate_delete (bgp, &p, afi, SAFI_UNICAST, aggregate); -  if (aggregate->safi & SAFI_MULTICAST) -    bgp_aggregate_delete (bgp, &p, afi, SAFI_MULTICAST, aggregate); +	aggregate = rn->info; +	if (aggregate->safi & SAFI_UNICAST) +		bgp_aggregate_delete(bgp, &p, afi, SAFI_UNICAST, aggregate); +	if (aggregate->safi & SAFI_MULTICAST) +		bgp_aggregate_delete(bgp, &p, afi, SAFI_MULTICAST, aggregate); -  /* Unlock aggregate address configuration. */ -  rn->info = NULL; -  bgp_aggregate_free (aggregate); -  bgp_unlock_node (rn); -  bgp_unlock_node (rn); +	/* Unlock aggregate address configuration. */ +	rn->info = NULL; +	bgp_aggregate_free(aggregate); +	bgp_unlock_node(rn); +	bgp_unlock_node(rn); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  } -static int -bgp_aggregate_set (struct vty *vty, const char *prefix_str, -                   afi_t afi, safi_t safi, -		   u_char summary_only, u_char as_set) +static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi, +			     safi_t safi, u_char summary_only, u_char as_set)  { -  VTY_DECLVAR_CONTEXT(bgp, bgp); -  int ret; -  struct prefix p; -  struct bgp_node *rn; -  struct bgp_aggregate *aggregate; - -  /* Convert string to prefix structure. */ -  ret = str2prefix (prefix_str, &p); -  if (!ret) -    { -      vty_out (vty, "Malformed prefix%s", VTY_NEWLINE); -      return CMD_WARNING; -    } -  apply_mask (&p); - -  /* Old configuration check. */ -  rn = bgp_node_get (bgp->aggregate[afi][safi], &p); +	VTY_DECLVAR_CONTEXT(bgp, bgp); +	int ret; +	struct prefix p; +	struct bgp_node *rn; +	struct bgp_aggregate *aggregate; -  if (rn->info) -    { -      vty_out (vty, "There is already same aggregate network.%s", VTY_NEWLINE); -      /* try to remove the old entry */ -      ret = bgp_aggregate_unset (vty, prefix_str, afi, safi); -      if (ret) -        { -          vty_out (vty, "Error deleting aggregate.%s", VTY_NEWLINE); -	  bgp_unlock_node (rn); -	  return CMD_WARNING; -        } -    } +	/* Convert string to prefix structure. */ +	ret = str2prefix(prefix_str, &p); +	if (!ret) { +		vty_out(vty, "Malformed prefix%s", VTY_NEWLINE); +		return CMD_WARNING; +	} +	apply_mask(&p); + +	/* Old configuration check. */ +	rn = bgp_node_get(bgp->aggregate[afi][safi], &p); + +	if (rn->info) { +		vty_out(vty, "There is already same aggregate network.%s", +			VTY_NEWLINE); +		/* try to remove the old entry */ +		ret = bgp_aggregate_unset(vty, prefix_str, afi, safi); +		if (ret) { +			vty_out(vty, "Error deleting aggregate.%s", +				VTY_NEWLINE); +			bgp_unlock_node(rn); +			return CMD_WARNING; +		} +	} -  /* Make aggregate address structure. */ -  aggregate = bgp_aggregate_new (); -  aggregate->summary_only = summary_only; -  aggregate->as_set = as_set; -  aggregate->safi = safi; -  rn->info = aggregate; +	/* Make aggregate address structure. */ +	aggregate = bgp_aggregate_new(); +	aggregate->summary_only = summary_only; +	aggregate->as_set = as_set; +	aggregate->safi = safi; +	rn->info = aggregate; -  /* Aggregate address insert into BGP routing table. */ -  if (safi & SAFI_UNICAST) -    bgp_aggregate_add (bgp, &p, afi, SAFI_UNICAST, aggregate); -  if (safi & SAFI_MULTICAST) -    bgp_aggregate_add (bgp, &p, afi, SAFI_MULTICAST, aggregate); +	/* Aggregate address insert into BGP routing table. */ +	if (safi & SAFI_UNICAST) +		bgp_aggregate_add(bgp, &p, afi, SAFI_UNICAST, aggregate); +	if (safi & SAFI_MULTICAST) +		bgp_aggregate_add(bgp, &p, afi, SAFI_MULTICAST, aggregate); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (aggregate_address, @@ -5634,14 +5566,18 @@ DEFUN (aggregate_address,         "Filter more specific routes from updates\n"         "Generate AS set path information\n")  { -  int idx = 0; -  argv_find (argv, argc, "A.B.C.D/M", &idx); -  char *prefix = argv[idx]->arg; -  int as_set = argv_find (argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0; -  idx = 0; -  int summary_only = argv_find (argv, argc, "summary-only", &idx) ? AGGREGATE_SUMMARY_ONLY : 0; +	int idx = 0; +	argv_find(argv, argc, "A.B.C.D/M", &idx); +	char *prefix = argv[idx]->arg; +	int as_set = +		argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0; +	idx = 0; +	int summary_only = argv_find(argv, argc, "summary-only", &idx) +				   ? AGGREGATE_SUMMARY_ONLY +				   : 0; -  return bgp_aggregate_set (vty, prefix, AFI_IP, bgp_node_safi (vty), summary_only, as_set); +	return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty), +				 summary_only, as_set);  }  DEFUN (aggregate_address_mask, @@ -5655,25 +5591,28 @@ DEFUN (aggregate_address_mask,         "Filter more specific routes from updates\n"         "Generate AS set path information\n")  { -  int idx = 0; -  argv_find (argv, argc, "A.B.C.D", &idx); -  char *prefix = argv[idx++]->arg; -  argv_find (argv, argc, "A.B.C.D", &idx); -  char *mask = argv[idx]->arg; -  int as_set = argv_find (argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0; -  idx = 0; -  int summary_only = argv_find (argv, argc, "summary-only", &idx) ? AGGREGATE_SUMMARY_ONLY : 0; - -  char prefix_str[BUFSIZ]; -  int ret = netmask_str2prefix_str (prefix, mask, prefix_str); - -  if (! ret) -    { -      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +	int idx = 0; +	argv_find(argv, argc, "A.B.C.D", &idx); +	char *prefix = argv[idx++]->arg; +	argv_find(argv, argc, "A.B.C.D", &idx); +	char *mask = argv[idx]->arg; +	int as_set = +		argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0; +	idx = 0; +	int summary_only = argv_find(argv, argc, "summary-only", &idx) +				   ? AGGREGATE_SUMMARY_ONLY +				   : 0; + +	char prefix_str[BUFSIZ]; +	int ret = netmask_str2prefix_str(prefix, mask, prefix_str); + +	if (!ret) { +		vty_out(vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); +		return CMD_WARNING; +	} -  return bgp_aggregate_set (vty, prefix_str, AFI_IP, bgp_node_safi (vty), summary_only, as_set); +	return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty), +				 summary_only, as_set);  }  DEFUN (no_aggregate_address, @@ -5687,10 +5626,10 @@ DEFUN (no_aggregate_address,         "Filter more specific routes from updates\n"         "Generate AS set path information\n")  { -  int idx = 0; -  argv_find (argv, argc, "A.B.C.D/M", &idx); -  char *prefix = argv[idx]->arg; -  return bgp_aggregate_unset (vty, prefix, AFI_IP, bgp_node_safi (vty)); +	int idx = 0; +	argv_find(argv, argc, "A.B.C.D/M", &idx); +	char *prefix = argv[idx]->arg; +	return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty));  }  DEFUN (no_aggregate_address_mask, @@ -5705,22 +5644,21 @@ DEFUN (no_aggregate_address_mask,         "Filter more specific routes from updates\n"         "Generate AS set path information\n")  { -  int idx = 0; -  argv_find (argv, argc, "A.B.C.D", &idx); -  char *prefix = argv[idx++]->arg; -  argv_find (argv, argc, "A.B.C.D", &idx); -  char *mask = argv[idx]->arg; +	int idx = 0; +	argv_find(argv, argc, "A.B.C.D", &idx); +	char *prefix = argv[idx++]->arg; +	argv_find(argv, argc, "A.B.C.D", &idx); +	char *mask = argv[idx]->arg; -  char prefix_str[BUFSIZ]; -  int ret = netmask_str2prefix_str (prefix, mask, prefix_str); +	char prefix_str[BUFSIZ]; +	int ret = netmask_str2prefix_str(prefix, mask, prefix_str); -  if (! ret) -    { -      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +	if (!ret) { +		vty_out(vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); +		return CMD_WARNING; +	} -  return bgp_aggregate_unset (vty, prefix_str, AFI_IP, bgp_node_safi (vty)); +	return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));  }  DEFUN (ipv6_aggregate_address, @@ -5730,11 +5668,14 @@ DEFUN (ipv6_aggregate_address,         "Aggregate prefix\n"         "Filter more specific routes from updates\n")  { -  int idx = 0; -  argv_find (argv, argc, "X:X::X:X/M", &idx); -  char *prefix = argv[idx]->arg; -  int sum_only = argv_find (argv, argc, "summary-only", &idx) ? AGGREGATE_SUMMARY_ONLY : 0; -  return bgp_aggregate_set (vty, prefix, AFI_IP6, SAFI_UNICAST, sum_only, 0); +	int idx = 0; +	argv_find(argv, argc, "X:X::X:X/M", &idx); +	char *prefix = argv[idx]->arg; +	int sum_only = argv_find(argv, argc, "summary-only", &idx) +			       ? AGGREGATE_SUMMARY_ONLY +			       : 0; +	return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, sum_only, +				 0);  }  DEFUN (no_ipv6_aggregate_address, @@ -5745,2464 +5686,2639 @@ DEFUN (no_ipv6_aggregate_address,         "Aggregate prefix\n"         "Filter more specific routes from updates\n")  { -  int idx = 0; -  argv_find (argv, argc, "X:X::X:X/M", &idx); -  char *prefix = argv[idx]->arg; -  return bgp_aggregate_unset (vty, prefix, AFI_IP6, SAFI_UNICAST); +	int idx = 0; +	argv_find(argv, argc, "X:X::X:X/M", &idx); +	char *prefix = argv[idx]->arg; +	return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST);  }  /* Redistribute route treatment. */ -void -bgp_redistribute_add (struct bgp *bgp, struct prefix *p, const struct in_addr *nexthop, -		      const struct in6_addr *nexthop6, unsigned int ifindex, -		      u_int32_t metric, u_char type, u_short instance, route_tag_t tag) -{ -  struct bgp_info *new; -  struct bgp_info *bi; -  struct bgp_info info; -  struct bgp_node *bn; -  struct attr attr; -  struct attr *new_attr; -  afi_t afi; -  int ret; -  struct bgp_redist *red; - -  /* Make default attribute. */ -  bgp_attr_default_set (&attr, BGP_ORIGIN_INCOMPLETE); -  if (nexthop) -    attr.nexthop = *nexthop; -  attr.nh_ifindex = ifindex; - -  if (nexthop6) -    { -      struct attr_extra *extra = bgp_attr_extra_get(&attr); -      extra->mp_nexthop_global = *nexthop6; -      extra->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; -    } +void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, +			  const struct in_addr *nexthop, +			  const struct in6_addr *nexthop6, unsigned int ifindex, +			  u_int32_t metric, u_char type, u_short instance, +			  route_tag_t tag) +{ +	struct bgp_info *new; +	struct bgp_info *bi; +	struct bgp_info info; +	struct bgp_node *bn; +	struct attr attr; +	struct attr *new_attr; +	afi_t afi; +	int ret; +	struct bgp_redist *red; + +	/* Make default attribute. */ +	bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE); +	if (nexthop) +		attr.nexthop = *nexthop; +	attr.nh_ifindex = ifindex; + +	if (nexthop6) { +		struct attr_extra *extra = bgp_attr_extra_get(&attr); +		extra->mp_nexthop_global = *nexthop6; +		extra->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; +	} -  attr.med = metric; -  attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); -  attr.extra->tag = tag; +	attr.med = metric; +	attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC); +	attr.extra->tag = tag; -  afi = family2afi (p->family); +	afi = family2afi(p->family); -  red = bgp_redist_lookup(bgp, afi, type, instance); -  if (red) -    { -      struct attr attr_new; -      struct attr_extra extra_new; - -      /* Copy attribute for modification. */ -      attr_new.extra = &extra_new; -      bgp_attr_dup (&attr_new, &attr); - -      if (red->redist_metric_flag) -        attr_new.med = red->redist_metric; - -      /* Apply route-map. */ -      if (red->rmap.name) -        { -          info.peer = bgp->peer_self; -          info.attr = &attr_new; - -          SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_REDISTRIBUTE); - -          ret = route_map_apply (red->rmap.map, p, RMAP_BGP, &info); - -          bgp->peer_self->rmap_type = 0; - -          if (ret == RMAP_DENYMATCH) -            { -              /* Free uninterned attribute. */ -              bgp_attr_flush (&attr_new); - -              /* Unintern original. */ -              aspath_unintern (&attr.aspath); -              bgp_attr_extra_free (&attr); -              bgp_redistribute_delete (bgp, p, type, instance); -              return; -            } -        } - -      bn = bgp_afi_node_get (bgp->rib[afi][SAFI_UNICAST],  -                             afi, SAFI_UNICAST, p, NULL); - -      new_attr = bgp_attr_intern (&attr_new); - -      for (bi = bn->info; bi; bi = bi->next) -        if (bi->peer == bgp->peer_self -            && bi->sub_type == BGP_ROUTE_REDISTRIBUTE) -          break; - -      if (bi) -        { -          /* Ensure the (source route) type is updated. */ -          bi->type = type; -          if (attrhash_cmp (bi->attr, new_attr) && -              !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) -            { -              bgp_attr_unintern (&new_attr); -              aspath_unintern (&attr.aspath); -              bgp_attr_extra_free (&attr); -              bgp_unlock_node (bn); -              return; -            } -          else -            { -              /* The attribute is changed. */ -              bgp_info_set_flag (bn, bi, BGP_INFO_ATTR_CHANGED); - -              /* Rewrite BGP route information. */ -              if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) -                bgp_info_restore(bn, bi); -              else -                bgp_aggregate_decrement (bgp, p, bi, afi, SAFI_UNICAST); -              bgp_attr_unintern (&bi->attr); -              bi->attr = new_attr; -              bi->uptime = bgp_clock (); - -              /* Process change. */ -              bgp_aggregate_increment (bgp, p, bi, afi, SAFI_UNICAST); -              bgp_process (bgp, bn, afi, SAFI_UNICAST); -              bgp_unlock_node (bn); -              aspath_unintern (&attr.aspath); -              bgp_attr_extra_free (&attr); -              return; -            } -        } - -      new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance, bgp->peer_self, -                      new_attr, bn); -      SET_FLAG (new->flags, BGP_INFO_VALID); - -      bgp_aggregate_increment (bgp, p, new, afi, SAFI_UNICAST); -      bgp_info_add (bn, new); -      bgp_unlock_node (bn); -      bgp_process (bgp, bn, afi, SAFI_UNICAST); -    } +	red = bgp_redist_lookup(bgp, afi, type, instance); +	if (red) { +		struct attr attr_new; +		struct attr_extra extra_new; -  /* Unintern original. */ -  aspath_unintern (&attr.aspath); -  bgp_attr_extra_free (&attr); -} +		/* Copy attribute for modification. */ +		attr_new.extra = &extra_new; +		bgp_attr_dup(&attr_new, &attr); -void -bgp_redistribute_delete (struct bgp *bgp, struct prefix *p, u_char type, u_short instance) -{ -  afi_t afi; -  struct bgp_node *rn; -  struct bgp_info *ri; -  struct bgp_redist *red; +		if (red->redist_metric_flag) +			attr_new.med = red->redist_metric; -  afi = family2afi (p->family); +		/* Apply route-map. */ +		if (red->rmap.name) { +			info.peer = bgp->peer_self; +			info.attr = &attr_new; -  red = bgp_redist_lookup(bgp, afi, type, instance); -  if (red) -    { -      rn = bgp_afi_node_get (bgp->rib[afi][SAFI_UNICAST], afi, SAFI_UNICAST, p, NULL); - -      for (ri = rn->info; ri; ri = ri->next) -        if (ri->peer == bgp->peer_self -            && ri->type == type) -          break; - -      if (ri) -        { -          bgp_aggregate_decrement (bgp, p, ri, afi, SAFI_UNICAST); -          bgp_info_delete (rn, ri); -          bgp_process (bgp, rn, afi, SAFI_UNICAST); -        } -      bgp_unlock_node (rn); -    } +			SET_FLAG(bgp->peer_self->rmap_type, +				 PEER_RMAP_TYPE_REDISTRIBUTE); + +			ret = route_map_apply(red->rmap.map, p, RMAP_BGP, +					      &info); + +			bgp->peer_self->rmap_type = 0; + +			if (ret == RMAP_DENYMATCH) { +				/* Free uninterned attribute. */ +				bgp_attr_flush(&attr_new); + +				/* Unintern original. */ +				aspath_unintern(&attr.aspath); +				bgp_attr_extra_free(&attr); +				bgp_redistribute_delete(bgp, p, type, instance); +				return; +			} +		} + +		bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi, +				      SAFI_UNICAST, p, NULL); + +		new_attr = bgp_attr_intern(&attr_new); + +		for (bi = bn->info; bi; bi = bi->next) +			if (bi->peer == bgp->peer_self +			    && bi->sub_type == BGP_ROUTE_REDISTRIBUTE) +				break; + +		if (bi) { +			/* Ensure the (source route) type is updated. */ +			bi->type = type; +			if (attrhash_cmp(bi->attr, new_attr) +			    && !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) { +				bgp_attr_unintern(&new_attr); +				aspath_unintern(&attr.aspath); +				bgp_attr_extra_free(&attr); +				bgp_unlock_node(bn); +				return; +			} else { +				/* The attribute is changed. */ +				bgp_info_set_flag(bn, bi, +						  BGP_INFO_ATTR_CHANGED); + +				/* Rewrite BGP route information. */ +				if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) +					bgp_info_restore(bn, bi); +				else +					bgp_aggregate_decrement(bgp, p, bi, afi, +								SAFI_UNICAST); +				bgp_attr_unintern(&bi->attr); +				bi->attr = new_attr; +				bi->uptime = bgp_clock(); + +				/* Process change. */ +				bgp_aggregate_increment(bgp, p, bi, afi, +							SAFI_UNICAST); +				bgp_process(bgp, bn, afi, SAFI_UNICAST); +				bgp_unlock_node(bn); +				aspath_unintern(&attr.aspath); +				bgp_attr_extra_free(&attr); +				return; +			} +		} + +		new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance, +				bgp->peer_self, new_attr, bn); +		SET_FLAG(new->flags, BGP_INFO_VALID); + +		bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST); +		bgp_info_add(bn, new); +		bgp_unlock_node(bn); +		bgp_process(bgp, bn, afi, SAFI_UNICAST); +	} + +	/* Unintern original. */ +	aspath_unintern(&attr.aspath); +	bgp_attr_extra_free(&attr);  } -/* Withdraw specified route type's route. */ -void -bgp_redistribute_withdraw (struct bgp *bgp, afi_t afi, int type, u_short instance) +void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, u_char type, +			     u_short instance)  { -  struct bgp_node *rn; -  struct bgp_info *ri; -  struct bgp_table *table; +	afi_t afi; +	struct bgp_node *rn; +	struct bgp_info *ri; +	struct bgp_redist *red; -  table = bgp->rib[afi][SAFI_UNICAST]; +	afi = family2afi(p->family); -  for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) -    { -      for (ri = rn->info; ri; ri = ri->next) -	if (ri->peer == bgp->peer_self -	    && ri->type == type -            && ri->instance == instance) -	  break; - -      if (ri) -	{ -	  bgp_aggregate_decrement (bgp, &rn->p, ri, afi, SAFI_UNICAST); -	  bgp_info_delete (rn, ri); -	  bgp_process (bgp, rn, afi, SAFI_UNICAST); +	red = bgp_redist_lookup(bgp, afi, type, instance); +	if (red) { +		rn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi, +				      SAFI_UNICAST, p, NULL); + +		for (ri = rn->info; ri; ri = ri->next) +			if (ri->peer == bgp->peer_self && ri->type == type) +				break; + +		if (ri) { +			bgp_aggregate_decrement(bgp, p, ri, afi, SAFI_UNICAST); +			bgp_info_delete(rn, ri); +			bgp_process(bgp, rn, afi, SAFI_UNICAST); +		} +		bgp_unlock_node(rn); +	} +} + +/* Withdraw specified route type's route. */ +void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type, +			       u_short instance) +{ +	struct bgp_node *rn; +	struct bgp_info *ri; +	struct bgp_table *table; + +	table = bgp->rib[afi][SAFI_UNICAST]; + +	for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { +		for (ri = rn->info; ri; ri = ri->next) +			if (ri->peer == bgp->peer_self && ri->type == type +			    && ri->instance == instance) +				break; + +		if (ri) { +			bgp_aggregate_decrement(bgp, &rn->p, ri, afi, +						SAFI_UNICAST); +			bgp_info_delete(rn, ri); +			bgp_process(bgp, rn, afi, SAFI_UNICAST); +		}  	} -    }  }  /* Static function to display route. */ -static void -route_vty_out_route (struct prefix *p, struct vty *vty) +static void route_vty_out_route(struct prefix *p, struct vty *vty)  { -  int len; -  u_int32_t destination;  -  char buf[BUFSIZ]; - -  if (p->family == AF_INET) -    { -      len = vty_out (vty, "%s", inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ)); -      destination = ntohl (p->u.prefix4.s_addr); - -      if ((IN_CLASSC (destination) && p->prefixlen == 24) -          || (IN_CLASSB (destination) && p->prefixlen == 16) -          || (IN_CLASSA (destination) && p->prefixlen == 8) -          || p->u.prefix4.s_addr == 0) -        { -          /* When mask is natural, mask is not displayed. */ -        } -      else -        len += vty_out (vty, "/%d", p->prefixlen); -    } -  else if (p->family == AF_ETHERNET) -    { -      prefix2str(p, buf, PREFIX_STRLEN); -      len = vty_out (vty, "%s", buf); -    } -  else -    len = vty_out (vty, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), -		   p->prefixlen); +	int len; +	u_int32_t destination; +	char buf[BUFSIZ]; -  len = 17 - len; -  if (len < 1) -    vty_out (vty, "%s%*s", VTY_NEWLINE, 20, " "); -  else -    vty_out (vty, "%*s", len, " "); +	if (p->family == AF_INET) { +		len = vty_out(vty, "%s", +			      inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ)); +		destination = ntohl(p->u.prefix4.s_addr); + +		if ((IN_CLASSC(destination) && p->prefixlen == 24) +		    || (IN_CLASSB(destination) && p->prefixlen == 16) +		    || (IN_CLASSA(destination) && p->prefixlen == 8) +		    || p->u.prefix4.s_addr == 0) { +			/* When mask is natural, mask is not displayed. */ +		} else +			len += vty_out(vty, "/%d", p->prefixlen); +	} else if (p->family == AF_ETHERNET) { +		prefix2str(p, buf, PREFIX_STRLEN); +		len = vty_out(vty, "%s", buf); +	} else +		len = vty_out(vty, "%s/%d", +			      inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ), +			      p->prefixlen); + +	len = 17 - len; +	if (len < 1) +		vty_out(vty, "%s%*s", VTY_NEWLINE, 20, " "); +	else +		vty_out(vty, "%*s", len, " ");  } -enum bgp_display_type -{ -  normal_list, +enum bgp_display_type { +	normal_list,  };  /* Print the short form route status for a bgp_info */ -static void -route_vty_short_status_out (struct vty *vty, struct bgp_info *binfo, -                            json_object *json_path) +static void route_vty_short_status_out(struct vty *vty, struct bgp_info *binfo, +				       json_object *json_path)  { -  if (json_path) -    { +	if (json_path) { -      /* Route status display. */ -      if (CHECK_FLAG (binfo->flags, BGP_INFO_REMOVED)) -        json_object_boolean_true_add(json_path, "removed"); +		/* Route status display. */ +		if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED)) +			json_object_boolean_true_add(json_path, "removed"); -      if (CHECK_FLAG (binfo->flags, BGP_INFO_STALE)) -        json_object_boolean_true_add(json_path, "stale"); +		if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE)) +			json_object_boolean_true_add(json_path, "stale"); -      if (binfo->extra && binfo->extra->suppress) -        json_object_boolean_true_add(json_path, "suppressed"); +		if (binfo->extra && binfo->extra->suppress) +			json_object_boolean_true_add(json_path, "suppressed"); -      if (CHECK_FLAG (binfo->flags, BGP_INFO_VALID) && -               ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) -        json_object_boolean_true_add(json_path, "valid"); +		if (CHECK_FLAG(binfo->flags, BGP_INFO_VALID) +		    && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) +			json_object_boolean_true_add(json_path, "valid"); -      /* Selected */ -      if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) -        json_object_boolean_true_add(json_path, "history"); +		/* Selected */ +		if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) +			json_object_boolean_true_add(json_path, "history"); -      if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)) -        json_object_boolean_true_add(json_path, "damped"); +		if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)) +			json_object_boolean_true_add(json_path, "damped"); -      if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED)) -        json_object_boolean_true_add(json_path, "bestpath"); +		if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED)) +			json_object_boolean_true_add(json_path, "bestpath"); -      if (CHECK_FLAG (binfo->flags, BGP_INFO_MULTIPATH)) -        json_object_boolean_true_add(json_path, "multipath"); +		if (CHECK_FLAG(binfo->flags, BGP_INFO_MULTIPATH)) +			json_object_boolean_true_add(json_path, "multipath"); -      /* Internal route. */ -      if ((binfo->peer->as) && (binfo->peer->as == binfo->peer->local_as)) -        json_object_string_add(json_path, "pathFrom", "internal"); -      else -        json_object_string_add(json_path, "pathFrom", "external"); +		/* Internal route. */ +		if ((binfo->peer->as) +		    && (binfo->peer->as == binfo->peer->local_as)) +			json_object_string_add(json_path, "pathFrom", +					       "internal"); +		else +			json_object_string_add(json_path, "pathFrom", +					       "external"); -      return; -    } +		return; +	} - /* Route status display. */ -  if (CHECK_FLAG (binfo->flags, BGP_INFO_REMOVED)) -    vty_out (vty, "R"); -  else if (CHECK_FLAG (binfo->flags, BGP_INFO_STALE)) -    vty_out (vty, "S"); -  else if (binfo->extra && binfo->extra->suppress) -    vty_out (vty, "s"); -  else if (CHECK_FLAG (binfo->flags, BGP_INFO_VALID) && -           ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) -    vty_out (vty, "*"); -  else -    vty_out (vty, " "); - -  /* Selected */ -  if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) -    vty_out (vty, "h"); -  else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)) -    vty_out (vty, "d"); -  else if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED)) -    vty_out (vty, ">"); -  else if (CHECK_FLAG (binfo->flags, BGP_INFO_MULTIPATH)) -    vty_out (vty, "="); -  else -    vty_out (vty, " "); +	/* Route status display. */ +	if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED)) +		vty_out(vty, "R"); +	else if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE)) +		vty_out(vty, "S"); +	else if (binfo->extra && binfo->extra->suppress) +		vty_out(vty, "s"); +	else if (CHECK_FLAG(binfo->flags, BGP_INFO_VALID) +		 && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) +		vty_out(vty, "*"); +	else +		vty_out(vty, " "); + +	/* Selected */ +	if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) +		vty_out(vty, "h"); +	else if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)) +		vty_out(vty, "d"); +	else if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED)) +		vty_out(vty, ">"); +	else if (CHECK_FLAG(binfo->flags, BGP_INFO_MULTIPATH)) +		vty_out(vty, "="); +	else +		vty_out(vty, " "); -  /* Internal route. */ -  if (binfo->peer &&  -      (binfo->peer->as) && (binfo->peer->as == binfo->peer->local_as)) -    vty_out (vty, "i"); -  else -    vty_out (vty, " "); +	/* Internal route. */ +	if (binfo->peer && (binfo->peer->as) +	    && (binfo->peer->as == binfo->peer->local_as)) +		vty_out(vty, "i"); +	else +		vty_out(vty, " ");  }  /* called from terminal list command */ -void -route_vty_out (struct vty *vty, struct prefix *p, -	       struct bgp_info *binfo, int display, safi_t safi, -               json_object *json_paths) -{ -  struct attr *attr; -  json_object *json_path = NULL; -  json_object *json_nexthops = NULL; -  json_object *json_nexthop_global = NULL; -  json_object *json_nexthop_ll = NULL; - -  if (json_paths) -    json_path = json_object_new_object(); - -  /* short status lead text */ -  route_vty_short_status_out (vty, binfo, json_path); +void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo, +		   int display, safi_t safi, json_object *json_paths) +{ +	struct attr *attr; +	json_object *json_path = NULL; +	json_object *json_nexthops = NULL; +	json_object *json_nexthop_global = NULL; +	json_object *json_nexthop_ll = NULL; + +	if (json_paths) +		json_path = json_object_new_object(); + +	/* short status lead text */ +	route_vty_short_status_out(vty, binfo, json_path); + +	if (!json_paths) { +		/* print prefix and mask */ +		if (!display) +			route_vty_out_route(p, vty); +		else +			vty_out(vty, "%*s", 17, " "); +	} -  if (!json_paths) -    { -      /* print prefix and mask */ -      if (! display) -        route_vty_out_route (p, vty); -      else -        vty_out (vty, "%*s", 17, " "); -    } +	/* Print attribute */ +	attr = binfo->attr; +	if (attr) { +		/* +		 * For ENCAP routes, nexthop address family is not +		 * neccessarily the same as the prefix address family. +		 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field +		 */ +		if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN) +		    || (safi == SAFI_EVPN)) { +			if (attr->extra) { +				char buf[BUFSIZ]; +				int af = NEXTHOP_FAMILY( +					attr->extra->mp_nexthop_len); + +				switch (af) { +				case AF_INET: +					vty_out(vty, "%s", +						inet_ntop( +							af, +							&attr->extra +								 ->mp_nexthop_global_in, +							buf, BUFSIZ)); +					break; +				case AF_INET6: +					vty_out(vty, "%s", +						inet_ntop( +							af, +							&attr->extra +								 ->mp_nexthop_global, +							buf, BUFSIZ)); +					break; +				default: +					vty_out(vty, "?"); +					break; +				} +			} else +				vty_out(vty, "?"); +		} +		/* IPv4 Next Hop */ +		else if (p->family == AF_INET +			 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) { +			if (json_paths) { +				json_nexthop_global = json_object_new_object(); + +				if ((safi == SAFI_MPLS_VPN) +				    || (safi == SAFI_EVPN)) +					json_object_string_add( +						json_nexthop_global, "ip", +						inet_ntoa( +							attr->extra +								->mp_nexthop_global_in)); +				else +					json_object_string_add( +						json_nexthop_global, "ip", +						inet_ntoa(attr->nexthop)); + +				json_object_string_add(json_nexthop_global, +						       "afi", "ipv4"); +				json_object_boolean_true_add( +					json_nexthop_global, "used"); +			} else { +				if ((safi == SAFI_MPLS_VPN) +				    || (safi == SAFI_EVPN)) +					vty_out(vty, "%-16s", +						inet_ntoa( +							attr->extra +								->mp_nexthop_global_in)); +				else +					vty_out(vty, "%-16s", +						inet_ntoa(attr->nexthop)); +			} +		} -  /* Print attribute */ -  attr = binfo->attr; -  if (attr)  -    { -      /* -       * For ENCAP routes, nexthop address family is not -       * neccessarily the same as the prefix address family. -       * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field -       */ -      if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN)) -        { -	  if (attr->extra) -            { -	      char buf[BUFSIZ]; -              int af = NEXTHOP_FAMILY(attr->extra->mp_nexthop_len); - -              switch (af) -                { -                  case AF_INET: -                    vty_out (vty, "%s", inet_ntop(af, -                             &attr->extra->mp_nexthop_global_in, buf, BUFSIZ)); -                  break; -                  case AF_INET6: -                    vty_out (vty, "%s", inet_ntop(af, -                             &attr->extra->mp_nexthop_global, buf, BUFSIZ)); -                  break; -                  default: -                    vty_out(vty, "?"); -                  break; -                } -            } -          else -            vty_out(vty, "?"); -        } -      /* IPv4 Next Hop */ -      else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) -	{ -          if (json_paths) -            { -              json_nexthop_global = json_object_new_object(); - -	      if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN)) -                json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->extra->mp_nexthop_global_in)); -              else -                json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->nexthop)); - -              json_object_string_add(json_nexthop_global, "afi", "ipv4"); -              json_object_boolean_true_add(json_nexthop_global, "used"); -            } -          else -            { -	      if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN)) -	        vty_out (vty, "%-16s", -                         inet_ntoa (attr->extra->mp_nexthop_global_in)); -	      else -	        vty_out (vty, "%-16s", inet_ntoa (attr->nexthop)); -            } -	} - -      /* IPv6 Next Hop */ -      else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) -	{ -	  int len; -	  char buf[BUFSIZ]; - -          if (json_paths) -            { -              json_nexthop_global = json_object_new_object(); -              json_object_string_add(json_nexthop_global, "ip", -                                     inet_ntop (AF_INET6, -                                                &attr->extra->mp_nexthop_global, -                                                buf, BUFSIZ)); -              json_object_string_add(json_nexthop_global, "afi", "ipv6"); -              json_object_string_add(json_nexthop_global, "scope", "global"); - -              /* We display both LL & GL if both have been received */ -              if ((attr->extra->mp_nexthop_len == 32) || (binfo->peer->conf_if)) -                { -                  json_nexthop_ll = json_object_new_object(); -                  json_object_string_add(json_nexthop_ll, "ip", -                                         inet_ntop (AF_INET6, -                                                    &attr->extra->mp_nexthop_local, -                                                    buf, BUFSIZ)); -                  json_object_string_add(json_nexthop_ll, "afi", "ipv6"); -                  json_object_string_add(json_nexthop_ll, "scope", "link-local"); - -                  if ((IPV6_ADDR_CMP (&attr->extra->mp_nexthop_global, -                                      &attr->extra->mp_nexthop_local) != 0) && -                                      !attr->extra->mp_nexthop_prefer_global) -                    json_object_boolean_true_add(json_nexthop_ll, "used"); -                  else -                    json_object_boolean_true_add(json_nexthop_global, "used"); -                } -              else -                json_object_boolean_true_add(json_nexthop_global, "used"); -            } -          else -            { -              /* Display LL if LL/Global both in table unless prefer-global is set */ -	      if (((attr->extra->mp_nexthop_len == 32) && -                   !attr->extra->mp_nexthop_prefer_global) || -                   (binfo->peer->conf_if)) -		{ -		  if (binfo->peer->conf_if) -		    { -		      len = vty_out (vty, "%s", -				     binfo->peer->conf_if); -		      len = 7 - len; /* len of IPv6 addr + max len of def ifname */ - -		      if (len < 1) -			vty_out (vty, "%s%*s", VTY_NEWLINE, 45, " "); -		      else -			vty_out (vty, "%*s", len, " "); -		    } -		  else -		    { -		      len = vty_out (vty, "%s", -				     inet_ntop (AF_INET6, -						&attr->extra->mp_nexthop_local, +		/* IPv6 Next Hop */ +		else if (p->family == AF_INET6 +			 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) { +			int len; +			char buf[BUFSIZ]; + +			if (json_paths) { +				json_nexthop_global = json_object_new_object(); +				json_object_string_add( +					json_nexthop_global, "ip", +					inet_ntop( +						AF_INET6, +						&attr->extra->mp_nexthop_global,  						buf, BUFSIZ)); -		      len = 16 - len; +				json_object_string_add(json_nexthop_global, +						       "afi", "ipv6"); +				json_object_string_add(json_nexthop_global, +						       "scope", "global"); + +				/* We display both LL & GL if both have been +				 * received */ +				if ((attr->extra->mp_nexthop_len == 32) +				    || (binfo->peer->conf_if)) { +					json_nexthop_ll = +						json_object_new_object(); +					json_object_string_add( +						json_nexthop_ll, "ip", +						inet_ntop( +							AF_INET6, +							&attr->extra +								 ->mp_nexthop_local, +							buf, BUFSIZ)); +					json_object_string_add(json_nexthop_ll, +							       "afi", "ipv6"); +					json_object_string_add(json_nexthop_ll, +							       "scope", +							       "link-local"); + +					if ((IPV6_ADDR_CMP( +						     &attr->extra +							      ->mp_nexthop_global, +						     &attr->extra +							      ->mp_nexthop_local) +					     != 0) +					    && !attr->extra +							->mp_nexthop_prefer_global) +						json_object_boolean_true_add( +							json_nexthop_ll, +							"used"); +					else +						json_object_boolean_true_add( +							json_nexthop_global, +							"used"); +				} else +					json_object_boolean_true_add( +						json_nexthop_global, "used"); +			} else { +				/* Display LL if LL/Global both in table unless +				 * prefer-global is set */ +				if (((attr->extra->mp_nexthop_len == 32) +				     && !attr->extra->mp_nexthop_prefer_global) +				    || (binfo->peer->conf_if)) { +					if (binfo->peer->conf_if) { +						len = vty_out( +							vty, "%s", +							binfo->peer->conf_if); +						len = +							7 - len; /* len of IPv6 +								    addr + max +								    len of def +								    ifname */ + +						if (len < 1) +							vty_out(vty, "%s%*s", +								VTY_NEWLINE, 45, +								" "); +						else +							vty_out(vty, "%*s", len, +								" "); +					} else { +						len = vty_out( +							vty, "%s", +							inet_ntop( +								AF_INET6, +								&attr->extra +									 ->mp_nexthop_local, +								buf, BUFSIZ)); +						len = 16 - len; + +						if (len < 1) +							vty_out(vty, "%s%*s", +								VTY_NEWLINE, 36, +								" "); +						else +							vty_out(vty, "%*s", len, +								" "); +					} +				} else { +					len = vty_out( +						vty, "%s", +						inet_ntop( +							AF_INET6, +							&attr->extra +								 ->mp_nexthop_global, +							buf, BUFSIZ)); +					len = 16 - len; + +					if (len < 1) +						vty_out(vty, "%s%*s", +							VTY_NEWLINE, 36, " "); +					else +						vty_out(vty, "%*s", len, " "); +				} +			} +		} -		      if (len < 1) -			vty_out (vty, "%s%*s", VTY_NEWLINE, 36, " "); -		      else -			vty_out (vty, "%*s", len, " "); -		    } +		/* MED/Metric */ +		if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) +			if (json_paths) +				json_object_int_add(json_path, "med", +						    attr->med); +			else +				vty_out(vty, "%10u", attr->med); +		else if (!json_paths) +			vty_out(vty, "          "); + +		/* Local Pref */ +		if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) +			if (json_paths) +				json_object_int_add(json_path, "localpref", +						    attr->local_pref); +			else +				vty_out(vty, "%7u", attr->local_pref); +		else if (!json_paths) +			vty_out(vty, "       "); + +		if (json_paths) { +			if (attr->extra) +				json_object_int_add(json_path, "weight", +						    attr->extra->weight); +			else +				json_object_int_add(json_path, "weight", 0); +		} else +			vty_out(vty, "%7u ", +				(attr->extra ? attr->extra->weight : 0)); + +		if (json_paths) { +			char buf[BUFSIZ]; +			json_object_string_add(json_path, "peerId", +					       sockunion2str(&binfo->peer->su, +							     buf, +							     SU_ADDRSTRLEN));  		} - 	      else -		{ -		  len = vty_out (vty, "%s", -				 inet_ntop (AF_INET6, -					    &attr->extra->mp_nexthop_global, -					    buf, BUFSIZ)); -		  len = 16 - len; - -		  if (len < 1) -		    vty_out (vty, "%s%*s", VTY_NEWLINE, 36, " "); -		  else -		    vty_out (vty, "%*s", len, " "); -		} -            } -	} - -      /* MED/Metric */ -      if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) -        if (json_paths) -          json_object_int_add(json_path, "med", attr->med); -        else -	  vty_out (vty, "%10u", attr->med); -      else -        if (!json_paths) -	  vty_out (vty, "          "); - -      /* Local Pref */ -      if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) -        if (json_paths) -          json_object_int_add(json_path, "localpref", attr->local_pref); -        else -	  vty_out (vty, "%7u", attr->local_pref); -      else -        if (!json_paths) -	  vty_out (vty, "       "); - -      if (json_paths) -        { -          if (attr->extra) -            json_object_int_add(json_path, "weight", attr->extra->weight); -          else -            json_object_int_add(json_path, "weight", 0); -        } -      else -        vty_out (vty, "%7u ", (attr->extra ? attr->extra->weight : 0)); - -      if (json_paths) { -	char buf[BUFSIZ]; -	json_object_string_add(json_path, "peerId", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN)); -      } - -      /* Print aspath */ -      if (attr->aspath) -        { -          if (json_paths) -            json_object_string_add(json_path, "aspath", attr->aspath->str); -          else -            aspath_print_vty (vty, "%s", attr->aspath, " "); -        } - -      /* Print origin */ -      if (json_paths) -        json_object_string_add(json_path, "origin", bgp_origin_long_str[attr->origin]); -      else -        vty_out (vty, "%s", bgp_origin_str[attr->origin]); -    } -  else -    { -      if (json_paths) -        json_object_string_add(json_path, "alert", "No attributes"); -      else -        vty_out (vty, "No attributes to print%s", VTY_NEWLINE); -    } -  if (json_paths) -    { -      if (json_nexthop_global || json_nexthop_ll) -        { -          json_nexthops = json_object_new_array(); +		/* Print aspath */ +		if (attr->aspath) { +			if (json_paths) +				json_object_string_add(json_path, "aspath", +						       attr->aspath->str); +			else +				aspath_print_vty(vty, "%s", attr->aspath, " "); +		} -          if (json_nexthop_global) -            json_object_array_add(json_nexthops, json_nexthop_global); +		/* Print origin */ +		if (json_paths) +			json_object_string_add( +				json_path, "origin", +				bgp_origin_long_str[attr->origin]); +		else +			vty_out(vty, "%s", bgp_origin_str[attr->origin]); +	} else { +		if (json_paths) +			json_object_string_add(json_path, "alert", +					       "No attributes"); +		else +			vty_out(vty, "No attributes to print%s", VTY_NEWLINE); +	} -          if (json_nexthop_ll) -            json_object_array_add(json_nexthops, json_nexthop_ll); +	if (json_paths) { +		if (json_nexthop_global || json_nexthop_ll) { +			json_nexthops = json_object_new_array(); -          json_object_object_add(json_path, "nexthops", json_nexthops); -        } +			if (json_nexthop_global) +				json_object_array_add(json_nexthops, +						      json_nexthop_global); -      json_object_array_add(json_paths, json_path); -    } -  else -    { -    vty_out (vty, "%s", VTY_NEWLINE); +			if (json_nexthop_ll) +				json_object_array_add(json_nexthops, +						      json_nexthop_ll); + +			json_object_object_add(json_path, "nexthops", +					       json_nexthops); +		} + +		json_object_array_add(json_paths, json_path); +	} else { +		vty_out(vty, "%s", VTY_NEWLINE);  #if ENABLE_BGP_VNC -      /* prints an additional line, indented, with VNC info, if present */ -      if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) -        rfapi_vty_out_vncinfo(vty, p, binfo, safi); +		/* prints an additional line, indented, with VNC info, if +		 * present */ +		if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) +			rfapi_vty_out_vncinfo(vty, p, binfo, safi);  #endif -    } -}   +	} +}  /* called from terminal list command */ -void -route_vty_out_tmp (struct vty *vty, struct prefix *p, struct attr *attr, safi_t safi, -                   u_char use_json, json_object *json_ar) -{ -  json_object *json_status = NULL; -  json_object *json_net = NULL; -  char buff[BUFSIZ]; -  /* Route status display. */ -  if (use_json) -    { -      json_status = json_object_new_object(); -      json_net = json_object_new_object(); -    } -  else -    { -      vty_out (vty, "*"); -      vty_out (vty, ">"); -      vty_out (vty, " "); -    } +void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr, +		       safi_t safi, u_char use_json, json_object *json_ar) +{ +	json_object *json_status = NULL; +	json_object *json_net = NULL; +	char buff[BUFSIZ]; +	/* Route status display. */ +	if (use_json) { +		json_status = json_object_new_object(); +		json_net = json_object_new_object(); +	} else { +		vty_out(vty, "*"); +		vty_out(vty, ">"); +		vty_out(vty, " "); +	} -  /* print prefix and mask */ -  if (use_json) -    json_object_string_add(json_net, "addrPrefix", inet_ntop (p->family, &p->u.prefix, buff, BUFSIZ)); -  else -    route_vty_out_route (p, vty); +	/* print prefix and mask */ +	if (use_json) +		json_object_string_add( +			json_net, "addrPrefix", +			inet_ntop(p->family, &p->u.prefix, buff, BUFSIZ)); +	else +		route_vty_out_route(p, vty); + +	/* Print attribute */ +	if (attr) { +		if (use_json) { +			if (p->family == AF_INET +			    && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP +				|| safi == SAFI_EVPN +				|| !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) { +				if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP +				    || safi == SAFI_EVPN) +					json_object_string_add( +						json_net, "nextHop", +						inet_ntoa( +							attr->extra +								->mp_nexthop_global_in)); +				else +					json_object_string_add( +						json_net, "nextHop", +						inet_ntoa(attr->nexthop)); +			} else if (p->family == AF_INET6 +				   || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) { +				char buf[BUFSIZ]; + +				json_object_string_add( +					json_net, "netHopGloabal", +					inet_ntop( +						AF_INET6, +						&attr->extra->mp_nexthop_global, +						buf, BUFSIZ)); +			} -  /* Print attribute */ -  if (attr)  -    { -      if (use_json) -        { -          if (p->family == AF_INET && -              (safi == SAFI_MPLS_VPN || -               safi == SAFI_ENCAP || -               safi == SAFI_EVPN || -               !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) -            { -              if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) -                json_object_string_add(json_net, "nextHop", inet_ntoa (attr->extra->mp_nexthop_global_in)); -              else -                json_object_string_add(json_net, "nextHop", inet_ntoa (attr->nexthop)); -            } -          else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) -            { -              char buf[BUFSIZ]; - -              json_object_string_add(json_net, "netHopGloabal", inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, -                                  buf, BUFSIZ)); -            } - -          if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) -            json_object_int_add(json_net, "metric", attr->med); - -          if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) -            json_object_int_add(json_net, "localPref", attr->local_pref); - -          if (attr->extra) -            json_object_int_add(json_net, "weight", attr->extra->weight); -          else -            json_object_int_add(json_net, "weight", 0); - -          /* Print aspath */ -          if (attr->aspath) -            json_object_string_add(json_net, "asPath", attr->aspath->str); - -          /* Print origin */ -          json_object_string_add(json_net, "bgpOriginCode", bgp_origin_str[attr->origin]); -        } -      else -        { -          if (p->family == AF_INET && -              (safi == SAFI_MPLS_VPN || -               safi == SAFI_ENCAP || -               safi == SAFI_EVPN || -               !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) -            { -              if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) -                vty_out (vty, "%-16s", -                         inet_ntoa (attr->extra->mp_nexthop_global_in)); -              else -                vty_out (vty, "%-16s", inet_ntoa (attr->nexthop)); -            } -          else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) -            { -              int len; -              char buf[BUFSIZ]; - -              assert (attr->extra); - -              len = vty_out (vty, "%s", -                             inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, -                             buf, BUFSIZ)); -              len = 16 - len; -              if (len < 1) -                vty_out (vty, "%s%*s", VTY_NEWLINE, 36, " "); -              else -                vty_out (vty, "%*s", len, " "); -            } -          if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) -            vty_out (vty, "%10u", attr->med); -          else -            vty_out (vty, "          "); - -          if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) -            vty_out (vty, "%7u", attr->local_pref); -          else -            vty_out (vty, "       "); - -          vty_out (vty, "%7u ", (attr->extra ? attr->extra->weight : 0)); - -          /* Print aspath */ -          if (attr->aspath) -            aspath_print_vty (vty, "%s", attr->aspath, " "); - -          /* Print origin */ -          vty_out (vty, "%s", bgp_origin_str[attr->origin]); -        } -    } -  if (use_json) -    { -      json_object_boolean_true_add(json_status, "*"); -      json_object_boolean_true_add(json_status, ">"); -      json_object_object_add(json_net, "appliedStatusSymbols", json_status); -      char buf_cut[BUFSIZ]; -      json_object_object_add(json_ar, inet_ntop (p->family, &p->u.prefix, buf_cut, BUFSIZ), json_net); -    } -  else -    vty_out (vty, "%s", VTY_NEWLINE); -}   +			if (attr->flag +			    & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) +				json_object_int_add(json_net, "metric", +						    attr->med); -void -route_vty_out_tag (struct vty *vty, struct prefix *p, -		   struct bgp_info *binfo, int display, safi_t safi, json_object *json) -{ -  json_object *json_out = NULL; -  struct attr *attr; -  u_int32_t label = 0; +			if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) +				json_object_int_add(json_net, "localPref", +						    attr->local_pref); -  if (!binfo->extra) -    return; +			if (attr->extra) +				json_object_int_add(json_net, "weight", +						    attr->extra->weight); +			else +				json_object_int_add(json_net, "weight", 0); + +			/* Print aspath */ +			if (attr->aspath) +				json_object_string_add(json_net, "asPath", +						       attr->aspath->str); + +			/* Print origin */ +			json_object_string_add(json_net, "bgpOriginCode", +					       bgp_origin_str[attr->origin]); +		} else { +			if (p->family == AF_INET +			    && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP +				|| safi == SAFI_EVPN +				|| !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) { +				if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP +				    || safi == SAFI_EVPN) +					vty_out(vty, "%-16s", +						inet_ntoa( +							attr->extra +								->mp_nexthop_global_in)); +				else +					vty_out(vty, "%-16s", +						inet_ntoa(attr->nexthop)); +			} else if (p->family == AF_INET6 +				   || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) { +				int len; +				char buf[BUFSIZ]; + +				assert(attr->extra); + +				len = vty_out( +					vty, "%s", +					inet_ntop( +						AF_INET6, +						&attr->extra->mp_nexthop_global, +						buf, BUFSIZ)); +				len = 16 - len; +				if (len < 1) +					vty_out(vty, "%s%*s", VTY_NEWLINE, 36, +						" "); +				else +					vty_out(vty, "%*s", len, " "); +			} +			if (attr->flag +			    & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) +				vty_out(vty, "%10u", attr->med); +			else +				vty_out(vty, "          "); -  if (json) -    json_out = json_object_new_object(); -   -  /* short status lead text */  -  route_vty_short_status_out (vty, binfo, json_out); -     -  /* print prefix and mask */ -  if (json == NULL) -    { -      if (! display) -        route_vty_out_route (p, vty); -      else -        vty_out (vty, "%*s", 17, " "); -    } +			if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) +				vty_out(vty, "%7u", attr->local_pref); +			else +				vty_out(vty, "       "); -  /* Print attribute */ -  attr = binfo->attr; -  if (attr)  -    { -      if (((p->family == AF_INET) && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) -          || (safi == SAFI_EVPN && p->family == AF_ETHERNET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) -          || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) -	{ -	  if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) -            { -              if (json) -                json_object_string_add(json_out, "mpNexthopGlobalIn", inet_ntoa (attr->extra->mp_nexthop_global_in)); -              else -                vty_out (vty, "%-16s", inet_ntoa (attr->extra->mp_nexthop_global_in)); -            } -	  else -            { -              if (json) -                json_object_string_add(json_out, "nexthop", inet_ntoa (attr->nexthop)); -              else -                vty_out (vty, "%-16s", inet_ntoa (attr->nexthop)); -            } -	} -      else if (((p->family == AF_INET6) && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) -               || (safi == SAFI_EVPN && p->family == AF_ETHERNET && BGP_ATTR_NEXTHOP_AFI_IP6(attr)) -               || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) -	{ -	  assert (attr->extra); -	  char buf_a[BUFSIZ]; -	  char buf_b[BUFSIZ]; -          char buf_c[BUFSIZ]; -	  if (attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) -            { -              if (json) -                json_object_string_add(json_out, "mpNexthopGlobalIn", -                                       inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, buf_a, BUFSIZ)); -              else -                vty_out (vty, "%s", -                         inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, -                                    buf_a, BUFSIZ)); -            } -	  else if (attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) -            { -              if (json) -                { -                  inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, -                             buf_a, BUFSIZ); -                  inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local, -                             buf_b, BUFSIZ); -                  sprintf(buf_c, "%s(%s)", buf_a, buf_b); -                  json_object_string_add(json_out, "mpNexthopGlobalLocal", buf_c); -                } -              else -                vty_out (vty, "%s(%s)", -                         inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, -                                    buf_a, BUFSIZ), -                         inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local, -                                    buf_b, BUFSIZ)); -            } +			vty_out(vty, "%7u ", +				(attr->extra ? attr->extra->weight : 0)); + +			/* Print aspath */ +			if (attr->aspath) +				aspath_print_vty(vty, "%s", attr->aspath, " "); +			/* Print origin */ +			vty_out(vty, "%s", bgp_origin_str[attr->origin]); +		}  	} -    } +	if (use_json) { +		json_object_boolean_true_add(json_status, "*"); +		json_object_boolean_true_add(json_status, ">"); +		json_object_object_add(json_net, "appliedStatusSymbols", +				       json_status); +		char buf_cut[BUFSIZ]; +		json_object_object_add( +			json_ar, +			inet_ntop(p->family, &p->u.prefix, buf_cut, BUFSIZ), +			json_net); +	} else +		vty_out(vty, "%s", VTY_NEWLINE); +} + +void route_vty_out_tag(struct vty *vty, struct prefix *p, +		       struct bgp_info *binfo, int display, safi_t safi, +		       json_object *json) +{ +	json_object *json_out = NULL; +	struct attr *attr; +	u_int32_t label = 0; + +	if (!binfo->extra) +		return; -  label = decode_label (binfo->extra->tag); +	if (json) +		json_out = json_object_new_object(); -  if (json) -    { -      if (label) -        json_object_int_add(json_out, "notag", label); -      json_object_array_add(json, json_out); -    } -  else -    { -      vty_out (vty, "notag/%d", label); +	/* short status lead text */ +	route_vty_short_status_out(vty, binfo, json_out); -      vty_out (vty, "%s", VTY_NEWLINE); -    } -}   +	/* print prefix and mask */ +	if (json == NULL) { +		if (!display) +			route_vty_out_route(p, vty); +		else +			vty_out(vty, "%*s", 17, " "); +	} -void -route_vty_out_overlay (struct vty *vty, struct prefix *p, -                       struct bgp_info *binfo, int display, json_object *json_paths) -{ -  struct attr *attr; -  char buf[BUFSIZ]; -  json_object *json_path = NULL; +	/* Print attribute */ +	attr = binfo->attr; +	if (attr) { +		if (((p->family == AF_INET) +		     && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) +		    || (safi == SAFI_EVPN && p->family == AF_ETHERNET +			&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) +		    || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) { +			if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP +			    || safi == SAFI_EVPN) { +				if (json) +					json_object_string_add( +						json_out, "mpNexthopGlobalIn", +						inet_ntoa( +							attr->extra +								->mp_nexthop_global_in)); +				else +					vty_out(vty, "%-16s", +						inet_ntoa( +							attr->extra +								->mp_nexthop_global_in)); +			} else { +				if (json) +					json_object_string_add( +						json_out, "nexthop", +						inet_ntoa(attr->nexthop)); +				else +					vty_out(vty, "%-16s", +						inet_ntoa(attr->nexthop)); +			} +		} else if (((p->family == AF_INET6) +			    && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) +			   || (safi == SAFI_EVPN && p->family == AF_ETHERNET +			       && BGP_ATTR_NEXTHOP_AFI_IP6(attr)) +			   || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) { +			assert(attr->extra); +			char buf_a[BUFSIZ]; +			char buf_b[BUFSIZ]; +			char buf_c[BUFSIZ]; +			if (attr->extra->mp_nexthop_len +			    == BGP_ATTR_NHLEN_IPV6_GLOBAL) { +				if (json) +					json_object_string_add( +						json_out, "mpNexthopGlobalIn", +						inet_ntop( +							AF_INET6, +							&attr->extra +								 ->mp_nexthop_global, +							buf_a, BUFSIZ)); +				else +					vty_out(vty, "%s", +						inet_ntop( +							AF_INET6, +							&attr->extra +								 ->mp_nexthop_global, +							buf_a, BUFSIZ)); +			} else if (attr->extra->mp_nexthop_len +				   == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) { +				if (json) { +					inet_ntop( +						AF_INET6, +						&attr->extra->mp_nexthop_global, +						buf_a, BUFSIZ); +					inet_ntop( +						AF_INET6, +						&attr->extra->mp_nexthop_local, +						buf_b, BUFSIZ); +					sprintf(buf_c, "%s(%s)", buf_a, buf_b); +					json_object_string_add( +						json_out, +						"mpNexthopGlobalLocal", buf_c); +				} else +					vty_out(vty, "%s(%s)", +						inet_ntop( +							AF_INET6, +							&attr->extra +								 ->mp_nexthop_global, +							buf_a, BUFSIZ), +						inet_ntop( +							AF_INET6, +							&attr->extra +								 ->mp_nexthop_local, +							buf_b, BUFSIZ)); +			} +		} +	} -  if (json_paths) -    json_path = json_object_new_object(); +	label = decode_label(binfo->extra->tag); -  if (!binfo->extra) -    return; +	if (json) { +		if (label) +			json_object_int_add(json_out, "notag", label); +		json_object_array_add(json, json_out); +	} else { +		vty_out(vty, "notag/%d", label); -  /* short status lead text */ -  route_vty_short_status_out (vty, binfo, json_path); +		vty_out(vty, "%s", VTY_NEWLINE); +	} +} -  /* print prefix and mask */ -  if (! display) -    route_vty_out_route (p, vty); -  else -    vty_out (vty, "%*s", 17, " "); +void route_vty_out_overlay(struct vty *vty, struct prefix *p, +			   struct bgp_info *binfo, int display, +			   json_object *json_paths) +{ +	struct attr *attr; +	char buf[BUFSIZ]; +	json_object *json_path = NULL; -  /* Print attribute */ -  attr = binfo->attr; -  if (attr) -    { -      if (attr->extra) -        { -          char	buf1[BUFSIZ]; -          int af = NEXTHOP_FAMILY(attr->extra->mp_nexthop_len); - -          switch (af) { -          case AF_INET: -            vty_out (vty, "%-16s", inet_ntop(af, -                                             &attr->extra->mp_nexthop_global_in, buf, BUFSIZ)); -            break; -          case AF_INET6: -            vty_out (vty, "%s(%s)", -                     inet_ntop (af, -                                &attr->extra->mp_nexthop_global, buf, BUFSIZ), -                     inet_ntop (af, -                                &attr->extra->mp_nexthop_local, buf1, BUFSIZ)); -            break; -          default: -            vty_out(vty, "?"); -          } -        } else { -        vty_out(vty, "?"); -      } -    } +	if (json_paths) +		json_path = json_object_new_object(); -  if(attr->extra) -    { -      struct eth_segment_id *id = &(attr->extra->evpn_overlay.eth_s_id); -      char *str = esi2str(id); -      vty_out (vty, "%s", str); -      XFREE (MTYPE_TMP, str); -      if (p->u.prefix_evpn.flags & IP_PREFIX_V4) -	{ -          vty_out (vty, "/%s", inet_ntoa (attr->extra->evpn_overlay.gw_ip.ipv4)); -	} -      else if (p->u.prefix_evpn.flags & IP_PREFIX_V6) -	{ -          vty_out (vty, "/%s", -                   inet_ntop (AF_INET6, &(attr->extra->evpn_overlay.gw_ip.ipv6), -                              buf, BUFSIZ)); -	} -      if(attr->extra->ecommunity) -        { -          char *mac = NULL; -          struct ecommunity_val *routermac = ecommunity_lookup (attr->extra->ecommunity, -                                                                ECOMMUNITY_ENCODE_EVPN, -                                                                ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC); -          if(routermac) -            mac = ecom_mac2str((char *)routermac->val); -          if(mac) -            { -              vty_out (vty, "/%s",(char *)mac); -              XFREE(MTYPE_TMP, mac); -            } -        } -    } -  vty_out (vty, "%s", VTY_NEWLINE); +	if (!binfo->extra) +		return; + +	/* short status lead text */ +	route_vty_short_status_out(vty, binfo, json_path); + +	/* print prefix and mask */ +	if (!display) +		route_vty_out_route(p, vty); +	else +		vty_out(vty, "%*s", 17, " "); + +	/* Print attribute */ +	attr = binfo->attr; +	if (attr) { +		if (attr->extra) { +			char buf1[BUFSIZ]; +			int af = NEXTHOP_FAMILY(attr->extra->mp_nexthop_len); + +			switch (af) { +			case AF_INET: +				vty_out(vty, "%-16s", +					inet_ntop( +						af, +						&attr->extra +							 ->mp_nexthop_global_in, +						buf, BUFSIZ)); +				break; +			case AF_INET6: +				vty_out(vty, "%s(%s)", +					inet_ntop( +						af, +						&attr->extra->mp_nexthop_global, +						buf, BUFSIZ), +					inet_ntop( +						af, +						&attr->extra->mp_nexthop_local, +						buf1, BUFSIZ)); +				break; +			default: +				vty_out(vty, "?"); +			} +		} else { +			vty_out(vty, "?"); +		} +	} + +	if (attr->extra) { +		struct eth_segment_id *id = +			&(attr->extra->evpn_overlay.eth_s_id); +		char *str = esi2str(id); +		vty_out(vty, "%s", str); +		XFREE(MTYPE_TMP, str); +		if (p->u.prefix_evpn.flags & IP_PREFIX_V4) { +			vty_out(vty, "/%s", +				inet_ntoa( +					attr->extra->evpn_overlay.gw_ip.ipv4)); +		} else if (p->u.prefix_evpn.flags & IP_PREFIX_V6) { +			vty_out(vty, "/%s", +				inet_ntop( +					AF_INET6, +					&(attr->extra->evpn_overlay.gw_ip.ipv6), +					buf, BUFSIZ)); +		} +		if (attr->extra->ecommunity) { +			char *mac = NULL; +			struct ecommunity_val *routermac = ecommunity_lookup( +				attr->extra->ecommunity, ECOMMUNITY_ENCODE_EVPN, +				ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC); +			if (routermac) +				mac = ecom_mac2str((char *)routermac->val); +			if (mac) { +				vty_out(vty, "/%s", (char *)mac); +				XFREE(MTYPE_TMP, mac); +			} +		} +	} +	vty_out(vty, "%s", VTY_NEWLINE);  }  /* dampening route */ -static void -damp_route_vty_out (struct vty *vty, struct prefix *p, struct bgp_info *binfo, -                    int display, safi_t safi, u_char use_json, json_object *json) -{ -  struct attr *attr; -  int len; -  char timebuf[BGP_UPTIME_LEN]; - -  /* short status lead text */  -  route_vty_short_status_out (vty, binfo, json); -   -  /* print prefix and mask */ -  if (!use_json) -    { -      if (! display) -        route_vty_out_route (p, vty); -      else -        vty_out (vty, "%*s", 17, " "); -    } +static void damp_route_vty_out(struct vty *vty, struct prefix *p, +			       struct bgp_info *binfo, int display, safi_t safi, +			       u_char use_json, json_object *json) +{ +	struct attr *attr; +	int len; +	char timebuf[BGP_UPTIME_LEN]; + +	/* short status lead text */ +	route_vty_short_status_out(vty, binfo, json); + +	/* print prefix and mask */ +	if (!use_json) { +		if (!display) +			route_vty_out_route(p, vty); +		else +			vty_out(vty, "%*s", 17, " "); +	} -  len = vty_out (vty, "%s", binfo->peer->host); -  len = 17 - len; -  if (len < 1) -    { -      if (!use_json) -        vty_out (vty, "%s%*s", VTY_NEWLINE, 34, " "); -    } -  else -    { -      if (use_json) -        json_object_int_add(json, "peerHost", len); -      else -        vty_out (vty, "%*s", len, " "); -    } +	len = vty_out(vty, "%s", binfo->peer->host); +	len = 17 - len; +	if (len < 1) { +		if (!use_json) +			vty_out(vty, "%s%*s", VTY_NEWLINE, 34, " "); +	} else { +		if (use_json) +			json_object_int_add(json, "peerHost", len); +		else +			vty_out(vty, "%*s", len, " "); +	} -  if (use_json) -    bgp_damp_reuse_time_vty (vty, binfo, timebuf, BGP_UPTIME_LEN, use_json, json); -  else -    vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo, timebuf, BGP_UPTIME_LEN, use_json, json)); +	if (use_json) +		bgp_damp_reuse_time_vty(vty, binfo, timebuf, BGP_UPTIME_LEN, +					use_json, json); +	else +		vty_out(vty, "%s ", bgp_damp_reuse_time_vty(vty, binfo, timebuf, +							    BGP_UPTIME_LEN, +							    use_json, json)); + +	/* Print attribute */ +	attr = binfo->attr; +	if (attr) { +		/* Print aspath */ +		if (attr->aspath) { +			if (use_json) +				json_object_string_add(json, "asPath", +						       attr->aspath->str); +			else +				aspath_print_vty(vty, "%s", attr->aspath, " "); +		} -  /* Print attribute */ -  attr = binfo->attr; -  if (attr) -    { -      /* Print aspath */ -      if (attr->aspath) -        { -          if (use_json) -            json_object_string_add(json, "asPath", attr->aspath->str); -          else -            aspath_print_vty (vty, "%s", attr->aspath, " "); -        } - -      /* Print origin */ -      if (use_json) -        json_object_string_add(json, "origin", bgp_origin_str[attr->origin]); -      else -        vty_out (vty, "%s", bgp_origin_str[attr->origin]); -    } -  if (!use_json) -    vty_out (vty, "%s", VTY_NEWLINE); +		/* Print origin */ +		if (use_json) +			json_object_string_add(json, "origin", +					       bgp_origin_str[attr->origin]); +		else +			vty_out(vty, "%s", bgp_origin_str[attr->origin]); +	} +	if (!use_json) +		vty_out(vty, "%s", VTY_NEWLINE);  }  /* flap route */ -static void -flap_route_vty_out (struct vty *vty, struct prefix *p, struct bgp_info *binfo, -                    int display, safi_t safi, u_char use_json, json_object *json) -{ -  struct attr *attr; -  struct bgp_damp_info *bdi; -  char timebuf[BGP_UPTIME_LEN]; -  int len; -   -  if (!binfo->extra) -    return; -   -  bdi = binfo->extra->damp_info; +static void flap_route_vty_out(struct vty *vty, struct prefix *p, +			       struct bgp_info *binfo, int display, safi_t safi, +			       u_char use_json, json_object *json) +{ +	struct attr *attr; +	struct bgp_damp_info *bdi; +	char timebuf[BGP_UPTIME_LEN]; +	int len; -  /* short status lead text */ -  route_vty_short_status_out (vty, binfo, json); -   -  /* print prefix and mask */ -  if (!use_json) -    { -      if (! display) -        route_vty_out_route (p, vty); -      else -        vty_out (vty, "%*s", 17, " "); -    } +	if (!binfo->extra) +		return; -  len = vty_out (vty, "%s", binfo->peer->host); -  len = 16 - len; -  if (len < 1) -    { -      if (!use_json) -        vty_out (vty, "%s%*s", VTY_NEWLINE, 33, " "); -    } -  else -    { -      if (use_json) -        json_object_int_add(json, "peerHost", len); -      else -        vty_out (vty, "%*s", len, " "); -    } +	bdi = binfo->extra->damp_info; -  len = vty_out (vty, "%d", bdi->flap); -  len = 5 - len; -  if (len < 1) -    { -      if (!use_json) -        vty_out (vty, " "); -    } -  else -    { -      if (use_json) -        json_object_int_add(json, "bdiFlap", len); -      else -        vty_out (vty, "%*s", len, " "); -    } +	/* short status lead text */ +	route_vty_short_status_out(vty, binfo, json); -  if (use_json) -    peer_uptime (bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json, json); -  else -    vty_out (vty, "%s ", peer_uptime (bdi->start_time, -             timebuf, BGP_UPTIME_LEN, 0, NULL)); +	/* print prefix and mask */ +	if (!use_json) { +		if (!display) +			route_vty_out_route(p, vty); +		else +			vty_out(vty, "%*s", 17, " "); +	} -  if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED) -      && ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) -    { -      if (use_json) -        bgp_damp_reuse_time_vty (vty, binfo, timebuf, BGP_UPTIME_LEN, use_json, json); -      else -        vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo, timebuf, BGP_UPTIME_LEN, use_json, json)); -    } -  else -    { -      if (!use_json) -        vty_out (vty, "%*s ", 8, " "); -    } +	len = vty_out(vty, "%s", binfo->peer->host); +	len = 16 - len; +	if (len < 1) { +		if (!use_json) +			vty_out(vty, "%s%*s", VTY_NEWLINE, 33, " "); +	} else { +		if (use_json) +			json_object_int_add(json, "peerHost", len); +		else +			vty_out(vty, "%*s", len, " "); +	} -  /* Print attribute */ -  attr = binfo->attr; -  if (attr) -    { -      /* Print aspath */ -      if (attr->aspath) -        { -          if (use_json) -            json_object_string_add(json, "asPath", attr->aspath->str); -          else -            aspath_print_vty (vty, "%s", attr->aspath, " "); -        } - -      /* Print origin */ -      if (use_json) -        json_object_string_add(json, "origin", bgp_origin_str[attr->origin]); -      else -        vty_out (vty, "%s", bgp_origin_str[attr->origin]); -    } -  if (!use_json) -    vty_out (vty, "%s", VTY_NEWLINE); -} +	len = vty_out(vty, "%d", bdi->flap); +	len = 5 - len; +	if (len < 1) { +		if (!use_json) +			vty_out(vty, " "); +	} else { +		if (use_json) +			json_object_int_add(json, "bdiFlap", len); +		else +			vty_out(vty, "%*s", len, " "); +	} -static void -route_vty_out_advertised_to (struct vty *vty, struct peer *peer, int *first, -                             const char *header, json_object *json_adv_to) -{ -  char buf1[INET6_ADDRSTRLEN]; -  json_object *json_peer = NULL; +	if (use_json) +		peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json, +			    json); +	else +		vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf, +						BGP_UPTIME_LEN, 0, NULL)); + +	if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED) +	    && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) { +		if (use_json) +			bgp_damp_reuse_time_vty(vty, binfo, timebuf, +						BGP_UPTIME_LEN, use_json, json); +		else +			vty_out(vty, "%s ", +				bgp_damp_reuse_time_vty(vty, binfo, timebuf, +							BGP_UPTIME_LEN, +							use_json, json)); +	} else { +		if (!use_json) +			vty_out(vty, "%*s ", 8, " "); +	} -  if (json_adv_to) -    { -      /* 'advertised-to' is a dictionary of peers we have advertised this -       * prefix too.  The key is the peer's IP or swpX, the value is the -       * hostname if we know it and "" if not. -       */ -      json_peer = json_object_new_object(); - -      if (peer->hostname) -        json_object_string_add(json_peer, "hostname", peer->hostname); - -      if (peer->conf_if) -        json_object_object_add(json_adv_to, peer->conf_if, json_peer); -      else -        json_object_object_add(json_adv_to, -                               sockunion2str (&peer->su, buf1, SU_ADDRSTRLEN), -                               json_peer); -    } -  else -    { -      if (*first) -        { -          vty_out (vty, "%s", header); -          *first = 0; -        } - -      if (peer->hostname && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) -        { -          if (peer->conf_if) -            vty_out (vty, " %s(%s)", peer->hostname, peer->conf_if); -          else -            vty_out (vty, " %s(%s)", peer->hostname, -                     sockunion2str (&peer->su, buf1, SU_ADDRSTRLEN)); -        } -      else -        { -          if (peer->conf_if) -            vty_out (vty, " %s", peer->conf_if); -          else -            vty_out (vty, " %s", sockunion2str (&peer->su, buf1, SU_ADDRSTRLEN)); -        } -    } +	/* Print attribute */ +	attr = binfo->attr; +	if (attr) { +		/* Print aspath */ +		if (attr->aspath) { +			if (use_json) +				json_object_string_add(json, "asPath", +						       attr->aspath->str); +			else +				aspath_print_vty(vty, "%s", attr->aspath, " "); +		} + +		/* Print origin */ +		if (use_json) +			json_object_string_add(json, "origin", +					       bgp_origin_str[attr->origin]); +		else +			vty_out(vty, "%s", bgp_origin_str[attr->origin]); +	} +	if (!use_json) +		vty_out(vty, "%s", VTY_NEWLINE); +} + +static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer, +					int *first, const char *header, +					json_object *json_adv_to) +{ +	char buf1[INET6_ADDRSTRLEN]; +	json_object *json_peer = NULL; + +	if (json_adv_to) { +		/* 'advertised-to' is a dictionary of peers we have advertised +		 * this +		 * prefix too.  The key is the peer's IP or swpX, the value is +		 * the +		 * hostname if we know it and "" if not. +		 */ +		json_peer = json_object_new_object(); + +		if (peer->hostname) +			json_object_string_add(json_peer, "hostname", +					       peer->hostname); + +		if (peer->conf_if) +			json_object_object_add(json_adv_to, peer->conf_if, +					       json_peer); +		else +			json_object_object_add( +				json_adv_to, +				sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN), +				json_peer); +	} else { +		if (*first) { +			vty_out(vty, "%s", header); +			*first = 0; +		} + +		if (peer->hostname +		    && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) { +			if (peer->conf_if) +				vty_out(vty, " %s(%s)", peer->hostname, +					peer->conf_if); +			else +				vty_out(vty, " %s(%s)", peer->hostname, +					sockunion2str(&peer->su, buf1, +						      SU_ADDRSTRLEN)); +		} else { +			if (peer->conf_if) +				vty_out(vty, " %s", peer->conf_if); +			else +				vty_out(vty, " %s", +					sockunion2str(&peer->su, buf1, +						      SU_ADDRSTRLEN)); +		} +	}  } -static void -route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,  -		      struct bgp_info *binfo, afi_t afi, safi_t safi, -                      json_object *json_paths) -{ -  char buf[INET6_ADDRSTRLEN]; -  char buf1[BUFSIZ]; -  struct attr *attr; -  int sockunion_vty_out (struct vty *, union sockunion *); -  time_t tbuf; -  json_object *json_bestpath = NULL; -  json_object *json_cluster_list = NULL; -  json_object *json_cluster_list_list = NULL; -  json_object *json_ext_community = NULL; -  json_object *json_last_update = NULL; -  json_object *json_nexthop_global = NULL; -  json_object *json_nexthop_ll = NULL; -  json_object *json_nexthops = NULL; -  json_object *json_path = NULL; -  json_object *json_peer = NULL; -  json_object *json_string = NULL; -  json_object *json_adv_to = NULL; -  int first = 0; -  struct listnode *node, *nnode; -  struct peer *peer; -  int addpath_capable; -  int has_adj; -  unsigned int first_as; - -  if (json_paths) -    { -      json_path = json_object_new_object(); -      json_peer = json_object_new_object(); -      json_nexthop_global = json_object_new_object(); -    } +static void route_vty_out_detail(struct vty *vty, struct bgp *bgp, +				 struct prefix *p, struct bgp_info *binfo, +				 afi_t afi, safi_t safi, +				 json_object *json_paths) +{ +	char buf[INET6_ADDRSTRLEN]; +	char buf1[BUFSIZ]; +	struct attr *attr; +	int sockunion_vty_out(struct vty *, union sockunion *); +	time_t tbuf; +	json_object *json_bestpath = NULL; +	json_object *json_cluster_list = NULL; +	json_object *json_cluster_list_list = NULL; +	json_object *json_ext_community = NULL; +	json_object *json_last_update = NULL; +	json_object *json_nexthop_global = NULL; +	json_object *json_nexthop_ll = NULL; +	json_object *json_nexthops = NULL; +	json_object *json_path = NULL; +	json_object *json_peer = NULL; +	json_object *json_string = NULL; +	json_object *json_adv_to = NULL; +	int first = 0; +	struct listnode *node, *nnode; +	struct peer *peer; +	int addpath_capable; +	int has_adj; +	unsigned int first_as; + +	if (json_paths) { +		json_path = json_object_new_object(); +		json_peer = json_object_new_object(); +		json_nexthop_global = json_object_new_object(); +	} -  attr = binfo->attr; +	attr = binfo->attr; + +	if (attr) { +		/* Line1 display AS-path, Aggregator */ +		if (attr->aspath) { +			if (json_paths) { +				json_object_lock(attr->aspath->json); +				json_object_object_add(json_path, "aspath", +						       attr->aspath->json); +			} else { +				if (attr->aspath->segments) +					aspath_print_vty(vty, "  %s", +							 attr->aspath, ""); +				else +					vty_out(vty, "  Local"); +			} +		} -  if (attr) -    { -      /* Line1 display AS-path, Aggregator */ -      if (attr->aspath) -	{ -          if (json_paths) -           { -            json_object_lock(attr->aspath->json); -            json_object_object_add(json_path, "aspath", attr->aspath->json); -           } -          else -            { -              if (attr->aspath->segments) -                aspath_print_vty (vty, "  %s", attr->aspath, ""); -              else -                vty_out (vty, "  Local"); -            } -	} - -      if (CHECK_FLAG (binfo->flags, BGP_INFO_REMOVED)) -        { -          if (json_paths) -            json_object_boolean_true_add(json_path, "removed"); -          else -            vty_out (vty, ", (removed)"); -        } - -      if (CHECK_FLAG (binfo->flags, BGP_INFO_STALE)) -        { -          if (json_paths) -            json_object_boolean_true_add(json_path, "stale"); -          else -	    vty_out (vty, ", (stale)"); -        } - -      if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))) -        { -          if (json_paths) -            { -              json_object_int_add(json_path, "aggregatorAs", attr->extra->aggregator_as); -              json_object_string_add(json_path, "aggregatorId", inet_ntoa (attr->extra->aggregator_addr)); -            } -          else -            { -	      vty_out (vty, ", (aggregated by %u %s)", -	               attr->extra->aggregator_as, -		       inet_ntoa (attr->extra->aggregator_addr)); -            } -        } - -      if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) -        { -          if (json_paths) -            json_object_boolean_true_add(json_path, "rxedFromRrClient"); -          else -	    vty_out (vty, ", (Received from a RR-client)"); -        } - -      if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)) -        { -          if (json_paths) -            json_object_boolean_true_add(json_path, "rxedFromRsClient"); -          else -	    vty_out (vty, ", (Received from a RS-client)"); -        } - -      if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) -        { -          if (json_paths) -            json_object_boolean_true_add(json_path, "dampeningHistoryEntry"); -          else -	    vty_out (vty, ", (history entry)"); -        } -      else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)) -        { -          if (json_paths) -            json_object_boolean_true_add(json_path, "dampeningSuppressed"); -          else -	    vty_out (vty, ", (suppressed due to dampening)"); -        } - -      if (!json_paths) -        vty_out (vty, "%s", VTY_NEWLINE); -	   -      /* Line2 display Next-hop, Neighbor, Router-id */ -      /* Display the nexthop */ -      if (p->family == AF_INET && -          (safi == SAFI_MPLS_VPN || -           safi == SAFI_ENCAP || -           safi == SAFI_EVPN || -           !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) -	{ -          if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) -            { -              if (json_paths) -                json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->extra->mp_nexthop_global_in)); -              else -	        vty_out (vty, "    %s", inet_ntoa (attr->extra->mp_nexthop_global_in)); -            } -          else -            { -              if (json_paths) -                json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->nexthop)); -              else -	        vty_out (vty, "    %s", inet_ntoa (attr->nexthop)); -            } - -          if (json_paths) -            json_object_string_add(json_nexthop_global, "afi", "ipv4"); -	} -      else -	{ -	  assert (attr->extra); -          if (json_paths) -            { -              json_object_string_add(json_nexthop_global, "ip", -                                     inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, -                                                buf, INET6_ADDRSTRLEN)); -              json_object_string_add(json_nexthop_global, "afi", "ipv6"); -              json_object_string_add(json_nexthop_global, "scope", "global"); -            } -          else -            { -	      vty_out (vty, "    %s", -		       inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, -			          buf, INET6_ADDRSTRLEN)); -            } -	} - -      /* Display the IGP cost or 'inaccessible' */ -      if (! CHECK_FLAG (binfo->flags, BGP_INFO_VALID)) -        { -          if (json_paths) -            json_object_boolean_false_add(json_nexthop_global, "accessible"); -          else -            vty_out (vty, " (inaccessible)"); -        } -      else -        { -          if (binfo->extra && binfo->extra->igpmetric) -            { -              if (json_paths) -                json_object_int_add(json_nexthop_global, "metric", binfo->extra->igpmetric); -              else -                vty_out (vty, " (metric %u)", binfo->extra->igpmetric); -            } - -          /* IGP cost is 0, display this only for json */ -          else -            { -              if (json_paths) -                json_object_int_add(json_nexthop_global, "metric", 0); -            } - -          if (json_paths) -            json_object_boolean_true_add(json_nexthop_global, "accessible"); -        } - -      /* Display peer "from" output */ -      /* This path was originated locally */ -      if (binfo->peer == bgp->peer_self) -	{ - -          if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) -            { -              if (json_paths) -                json_object_string_add(json_peer, "peerId", "0.0.0.0"); -              else -	        vty_out (vty, " from 0.0.0.0 "); -            } -          else -            { -              if (json_paths) -                json_object_string_add(json_peer, "peerId", "::"); -              else -	        vty_out (vty, " from :: "); -            } - -          if (json_paths) -            json_object_string_add(json_peer, "routerId", inet_ntoa(bgp->router_id)); -          else -	    vty_out (vty, "(%s)", inet_ntoa(bgp->router_id)); -	} - -      /* We RXed this path from one of our peers */ -      else -	{ - -          if (json_paths) -            { -              json_object_string_add(json_peer, "peerId", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN)); -              json_object_string_add(json_peer, "routerId", inet_ntop (AF_INET, &binfo->peer->remote_id, buf1, BUFSIZ)); - -              if (binfo->peer->hostname) -                json_object_string_add(json_peer, "hostname", binfo->peer->hostname); - -              if (binfo->peer->domainname) -                json_object_string_add(json_peer, "domainname", binfo->peer->domainname); - -              if (binfo->peer->conf_if) -                json_object_string_add(json_peer, "interface", binfo->peer->conf_if); -            } -          else -            { -              if (binfo->peer->conf_if) -		{ -		  if (binfo->peer->hostname && -		      bgp_flag_check(binfo->peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) -		    vty_out (vty, " from %s(%s)", binfo->peer->hostname, -			     binfo->peer->conf_if); -		  else -		    vty_out (vty, " from %s", binfo->peer->conf_if); -		} -              else -		{ -		  if (binfo->peer->hostname && -		      bgp_flag_check(binfo->peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) -		    vty_out (vty, " from %s(%s)", binfo->peer->hostname, -			     binfo->peer->host); -		  else -		    vty_out (vty, " from %s", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN)); -		} - -              if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) -                vty_out (vty, " (%s)", inet_ntoa (attr->extra->originator_id)); -              else -                vty_out (vty, " (%s)", inet_ntop (AF_INET, &binfo->peer->remote_id, buf1, BUFSIZ)); -            } -	} - -      if (!json_paths) -        vty_out (vty, "%s", VTY_NEWLINE); - -      /* display the link-local nexthop */ -      if (attr->extra && attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) -	{ -          if (json_paths) -            { -              json_nexthop_ll = json_object_new_object(); -              json_object_string_add(json_nexthop_ll, "ip", -                                     inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local, -                                                buf, INET6_ADDRSTRLEN)); -              json_object_string_add(json_nexthop_ll, "afi", "ipv6"); -              json_object_string_add(json_nexthop_ll, "scope", "link-local"); - -              json_object_boolean_true_add(json_nexthop_ll, "accessible"); - -              if (!attr->extra->mp_nexthop_prefer_global) -                json_object_boolean_true_add(json_nexthop_ll, "used"); -              else -                json_object_boolean_true_add(json_nexthop_global, "used"); -            } -          else -            { -	      vty_out (vty, "    (%s) %s%s", -                       inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local, -			          buf, INET6_ADDRSTRLEN), -                       attr->extra->mp_nexthop_prefer_global ? -                                   "(prefer-global)" : "(used)", -		       VTY_NEWLINE); -            } -	} -      /* If we do not have a link-local nexthop then we must flag the global as "used" */ -      else -        { -          if (json_paths) -            json_object_boolean_true_add(json_nexthop_global, "used"); -        } - -      /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid, Int/Ext/Local, Atomic, best */ -      if (json_paths) -        json_object_string_add(json_path, "origin", bgp_origin_long_str[attr->origin]); -      else -        vty_out (vty, "      Origin %s", bgp_origin_long_str[attr->origin]); -	   -      if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) -        { -          if (json_paths) -            json_object_int_add(json_path, "med", attr->med); -          else -	    vty_out (vty, ", metric %u", attr->med); -        } -	   -      if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) -        { -          if (json_paths) -            json_object_int_add(json_path, "localpref", attr->local_pref); -          else -	    vty_out (vty, ", localpref %u", attr->local_pref); -        } -      else -        { -          if (json_paths) -            json_object_int_add(json_path, "localpref", bgp->default_local_pref); -          else -	    vty_out (vty, ", localpref %u", bgp->default_local_pref); -        } - -      if (attr->extra && attr->extra->weight != 0) -        { -          if (json_paths) -            json_object_int_add(json_path, "weight", attr->extra->weight); -          else -	    vty_out (vty, ", weight %u", attr->extra->weight); -        } - -      if (attr->extra && attr->extra->tag != 0) -        { -          if (json_paths) -            json_object_int_add(json_path, "tag", attr->extra->tag); -          else -            vty_out (vty, ", tag %"ROUTE_TAG_PRI, attr->extra->tag); -        } -	 -      if (! CHECK_FLAG (binfo->flags, BGP_INFO_VALID)) -        { -          if (json_paths) -            json_object_boolean_false_add(json_path, "valid"); -          else -	    vty_out (vty, ", invalid"); -        } -      else if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) -        { -          if (json_paths) -            json_object_boolean_true_add(json_path, "valid"); -          else -	    vty_out (vty, ", valid"); -        } - -      if (binfo->peer != bgp->peer_self) -	{ -          if (binfo->peer->as == binfo->peer->local_as) -            { -              if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) -                { -                  if (json_paths) -                    json_object_string_add(json_peer, "type", "confed-internal"); -                  else -                    vty_out (vty, ", confed-internal"); -                } -              else -                { -                  if (json_paths) -                    json_object_string_add(json_peer, "type", "internal"); -                  else -                    vty_out (vty, ", internal"); -                } -            } -          else -            { -              if (bgp_confederation_peers_check(bgp, binfo->peer->as)) -                { -                  if (json_paths) -                    json_object_string_add(json_peer, "type", "confed-external"); -                  else -                    vty_out (vty, ", confed-external"); -                } -              else -                { -                  if (json_paths) -                    json_object_string_add(json_peer, "type", "external"); -                  else -                    vty_out (vty, ", external"); -                } -            } -	} -      else if (binfo->sub_type == BGP_ROUTE_AGGREGATE) -        { -          if (json_paths) -            { -              json_object_boolean_true_add(json_path, "aggregated"); -              json_object_boolean_true_add(json_path, "local"); -            } -          else -            { -	      vty_out (vty, ", aggregated, local"); -            } -        } -      else if (binfo->type != ZEBRA_ROUTE_BGP) -        { -          if (json_paths) -            json_object_boolean_true_add(json_path, "sourced"); -          else -	    vty_out (vty, ", sourced"); -        } -      else -        { -          if (json_paths) -            { -              json_object_boolean_true_add(json_path, "sourced"); -              json_object_boolean_true_add(json_path, "local"); -            } -          else -            { -	      vty_out (vty, ", sourced, local"); -            } -        } - -      if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) -        { -          if (json_paths) -            json_object_boolean_true_add(json_path, "atomicAggregate"); -          else -	    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))) -        { -          if (json_paths) -            json_object_boolean_true_add(json_path, "multipath"); -          else -	    vty_out (vty, ", multipath"); -        } - -      // Mark the bestpath(s) -      if (CHECK_FLAG (binfo->flags, BGP_INFO_DMED_SELECTED)) -        { -          first_as = aspath_get_first_as(attr->aspath); - -          if (json_paths) -            { -              if (!json_bestpath) -                json_bestpath = json_object_new_object(); -              json_object_int_add(json_bestpath, "bestpathFromAs", first_as); -            } -          else -            { -              if (first_as) -	        vty_out (vty, ", bestpath-from-AS %d", first_as); -              else -	        vty_out (vty, ", bestpath-from-AS Local"); -            } -        } - -      if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED)) -        { -          if (json_paths) -            { -              if (!json_bestpath) -                json_bestpath = json_object_new_object(); -              json_object_boolean_true_add(json_bestpath, "overall"); -            } -          else -	    vty_out (vty, ", best"); -        } - -      if (json_bestpath) -        json_object_object_add(json_path, "bestpath", json_bestpath); - -      if (!json_paths) -        vty_out (vty, "%s", VTY_NEWLINE); -	   -      /* Line 4 display Community */ -      if (attr->community) -        { -          if (json_paths) -            { -              json_object_lock(attr->community->json); -              json_object_object_add(json_path, "community", attr->community->json); -            } -          else -            { -	      vty_out (vty, "      Community: %s%s", attr->community->str, -		       VTY_NEWLINE); -            } -        } -	   -      /* Line 5 display Extended-community */ -      if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) -        { -          if (json_paths) -            { -              json_ext_community = json_object_new_object(); -              json_object_string_add(json_ext_community, "string", attr->extra->ecommunity->str); -              json_object_object_add(json_path, "extendedCommunity", json_ext_community); -            } -          else -            { -	       vty_out (vty, "      Extended Community: %s%s", -	                attr->extra->ecommunity->str, VTY_NEWLINE); -            } -        } - -      /* Line 6 display Large community */ -      if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) -        vty_out (vty, "      Large Community: %s%s", -                 attr->extra->lcommunity->str, VTY_NEWLINE); - -      /* Line 7 display Originator, Cluster-id */ -      if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) || -	  (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) -	{ -	  assert (attr->extra); -	  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) -            { -              if (json_paths) -                json_object_string_add(json_path, "originatorId", inet_ntoa (attr->extra->originator_id)); -              else -	        vty_out (vty, "      Originator: %s", -	                 inet_ntoa (attr->extra->originator_id)); -            } - -	  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) -	    { -	      int i; - -              if (json_paths) -                { -                  json_cluster_list = json_object_new_object(); -                  json_cluster_list_list = json_object_new_array(); - -	          for (i = 0; i < attr->extra->cluster->length / 4; i++) -                    { -                      json_string = json_object_new_string(inet_ntoa (attr->extra->cluster->list[i])); -                      json_object_array_add(json_cluster_list_list, json_string); -                    } - -                  /* struct cluster_list does not have "str" variable like -                   * aspath and community do.  Add this someday if someone -                   * asks for it. -                  json_object_string_add(json_cluster_list, "string", attr->extra->cluster->str); -                   */ -                  json_object_object_add(json_cluster_list, "list", json_cluster_list_list); -                  json_object_object_add(json_path, "clusterList", json_cluster_list); -                } -              else -                { -	          vty_out (vty, ", Cluster list: "); - -	          for (i = 0; i < attr->extra->cluster->length / 4; i++) -                    { -		       vty_out (vty, "%s ", -		                inet_ntoa (attr->extra->cluster->list[i])); -                    } -                } -	    } - -          if (!json_paths) -	    vty_out (vty, "%s", VTY_NEWLINE); -	} - -      if (binfo->extra && binfo->extra->damp_info) -	bgp_damp_info_vty (vty, binfo, json_path); - -      /* Line 8 display Addpath IDs */ -      if (binfo->addpath_rx_id || binfo->addpath_tx_id) -        { -          if (json_paths) -            { -              json_object_int_add(json_path, "addpathRxId", binfo->addpath_rx_id); -              json_object_int_add(json_path, "addpathTxId", binfo->addpath_tx_id); -            } -          else -            { -              vty_out (vty, "      AddPath ID: RX %u, TX %u%s", -                       binfo->addpath_rx_id, binfo->addpath_tx_id, -                       VTY_NEWLINE); -            } -        } - -      /* If we used addpath to TX a non-bestpath we need to display -       * "Advertised to" on a path-by-path basis */ -      if (bgp->addpath_tx_used[afi][safi]) -        { -          first = 1; - -          for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) -            { -              addpath_capable = bgp_addpath_encode_tx (peer, afi, safi); -              has_adj = bgp_adj_out_lookup (peer, binfo->net, binfo->addpath_tx_id); - -              if ((addpath_capable && has_adj) || -                  (!addpath_capable && has_adj && CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))) -                { -                    if (json_path && !json_adv_to) -                      json_adv_to = json_object_new_object(); - -                    route_vty_out_advertised_to(vty, peer, &first, -                                                "      Advertised to:", -                                                json_adv_to); -                } -            } - -          if (json_path) -            { -              if (json_adv_to) -                { -                  json_object_object_add(json_path, "advertisedTo", json_adv_to); -                } -            } -          else -            { -              if (!first) -                { -	          vty_out (vty, "%s", VTY_NEWLINE); -                } -            } -        } - -      /* Line 9 display Uptime */ -      tbuf = time(NULL) - (bgp_clock() - binfo->uptime); -      if (json_paths) -        { -          json_last_update = json_object_new_object(); -          json_object_int_add(json_last_update, "epoch", tbuf); -          json_object_string_add(json_last_update, "string", ctime(&tbuf)); -          json_object_object_add(json_path, "lastUpdate", json_last_update); -        } -      else -        vty_out (vty, "      Last update: %s", ctime(&tbuf)); -    } +		if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED)) { +			if (json_paths) +				json_object_boolean_true_add(json_path, +							     "removed"); +			else +				vty_out(vty, ", (removed)"); +		} -  /* We've constructed the json object for this path, add it to the json -   * array of paths -   */ -  if (json_paths) -    { -      if (json_nexthop_global || json_nexthop_ll) -        { -          json_nexthops = json_object_new_array(); +		if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE)) { +			if (json_paths) +				json_object_boolean_true_add(json_path, +							     "stale"); +			else +				vty_out(vty, ", (stale)"); +		} -          if (json_nexthop_global) -            json_object_array_add(json_nexthops, json_nexthop_global); +		if (CHECK_FLAG(attr->flag, +			       ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) { +			if (json_paths) { +				json_object_int_add(json_path, "aggregatorAs", +						    attr->extra->aggregator_as); +				json_object_string_add( +					json_path, "aggregatorId", +					inet_ntoa( +						attr->extra->aggregator_addr)); +			} else { +				vty_out(vty, ", (aggregated by %u %s)", +					attr->extra->aggregator_as, +					inet_ntoa( +						attr->extra->aggregator_addr)); +			} +		} -          if (json_nexthop_ll) -            json_object_array_add(json_nexthops, json_nexthop_ll); +		if (CHECK_FLAG(binfo->peer->af_flags[afi][safi], +			       PEER_FLAG_REFLECTOR_CLIENT)) { +			if (json_paths) +				json_object_boolean_true_add( +					json_path, "rxedFromRrClient"); +			else +				vty_out(vty, ", (Received from a RR-client)"); +		} -          json_object_object_add(json_path, "nexthops", json_nexthops); -        } +		if (CHECK_FLAG(binfo->peer->af_flags[afi][safi], +			       PEER_FLAG_RSERVER_CLIENT)) { +			if (json_paths) +				json_object_boolean_true_add( +					json_path, "rxedFromRsClient"); +			else +				vty_out(vty, ", (Received from a RS-client)"); +		} -      json_object_object_add(json_path, "peer", json_peer); -      json_object_array_add(json_paths, json_path); -    } -  else -    vty_out (vty, "%s", VTY_NEWLINE); +		if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) { +			if (json_paths) +				json_object_boolean_true_add( +					json_path, "dampeningHistoryEntry"); +			else +				vty_out(vty, ", (history entry)"); +		} else if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)) { +			if (json_paths) +				json_object_boolean_true_add( +					json_path, "dampeningSuppressed"); +			else +				vty_out(vty, ", (suppressed due to dampening)"); +		} + +		if (!json_paths) +			vty_out(vty, "%s", VTY_NEWLINE); + +		/* Line2 display Next-hop, Neighbor, Router-id */ +		/* Display the nexthop */ +		if (p->family == AF_INET +		    && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP +			|| safi == SAFI_EVPN +			|| !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) { +			if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP +			    || safi == SAFI_EVPN) { +				if (json_paths) +					json_object_string_add( +						json_nexthop_global, "ip", +						inet_ntoa( +							attr->extra +								->mp_nexthop_global_in)); +				else +					vty_out(vty, "    %s", +						inet_ntoa( +							attr->extra +								->mp_nexthop_global_in)); +			} else { +				if (json_paths) +					json_object_string_add( +						json_nexthop_global, "ip", +						inet_ntoa(attr->nexthop)); +				else +					vty_out(vty, "    %s", +						inet_ntoa(attr->nexthop)); +			} + +			if (json_paths) +				json_object_string_add(json_nexthop_global, +						       "afi", "ipv4"); +		} else { +			assert(attr->extra); +			if (json_paths) { +				json_object_string_add( +					json_nexthop_global, "ip", +					inet_ntop( +						AF_INET6, +						&attr->extra->mp_nexthop_global, +						buf, INET6_ADDRSTRLEN)); +				json_object_string_add(json_nexthop_global, +						       "afi", "ipv6"); +				json_object_string_add(json_nexthop_global, +						       "scope", "global"); +			} else { +				vty_out(vty, "    %s", +					inet_ntop( +						AF_INET6, +						&attr->extra->mp_nexthop_global, +						buf, INET6_ADDRSTRLEN)); +			} +		} + +		/* Display the IGP cost or 'inaccessible' */ +		if (!CHECK_FLAG(binfo->flags, BGP_INFO_VALID)) { +			if (json_paths) +				json_object_boolean_false_add( +					json_nexthop_global, "accessible"); +			else +				vty_out(vty, " (inaccessible)"); +		} else { +			if (binfo->extra && binfo->extra->igpmetric) { +				if (json_paths) +					json_object_int_add( +						json_nexthop_global, "metric", +						binfo->extra->igpmetric); +				else +					vty_out(vty, " (metric %u)", +						binfo->extra->igpmetric); +			} + +			/* IGP cost is 0, display this only for json */ +			else { +				if (json_paths) +					json_object_int_add(json_nexthop_global, +							    "metric", 0); +			} + +			if (json_paths) +				json_object_boolean_true_add( +					json_nexthop_global, "accessible"); +		} + +		/* Display peer "from" output */ +		/* This path was originated locally */ +		if (binfo->peer == bgp->peer_self) { + +			if (p->family == AF_INET +			    && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) { +				if (json_paths) +					json_object_string_add( +						json_peer, "peerId", "0.0.0.0"); +				else +					vty_out(vty, " from 0.0.0.0 "); +			} else { +				if (json_paths) +					json_object_string_add(json_peer, +							       "peerId", "::"); +				else +					vty_out(vty, " from :: "); +			} + +			if (json_paths) +				json_object_string_add( +					json_peer, "routerId", +					inet_ntoa(bgp->router_id)); +			else +				vty_out(vty, "(%s)", inet_ntoa(bgp->router_id)); +		} + +		/* We RXed this path from one of our peers */ +		else { + +			if (json_paths) { +				json_object_string_add( +					json_peer, "peerId", +					sockunion2str(&binfo->peer->su, buf, +						      SU_ADDRSTRLEN)); +				json_object_string_add( +					json_peer, "routerId", +					inet_ntop(AF_INET, +						  &binfo->peer->remote_id, buf1, +						  BUFSIZ)); + +				if (binfo->peer->hostname) +					json_object_string_add( +						json_peer, "hostname", +						binfo->peer->hostname); + +				if (binfo->peer->domainname) +					json_object_string_add( +						json_peer, "domainname", +						binfo->peer->domainname); + +				if (binfo->peer->conf_if) +					json_object_string_add( +						json_peer, "interface", +						binfo->peer->conf_if); +			} else { +				if (binfo->peer->conf_if) { +					if (binfo->peer->hostname +					    && bgp_flag_check( +						       binfo->peer->bgp, +						       BGP_FLAG_SHOW_HOSTNAME)) +						vty_out(vty, " from %s(%s)", +							binfo->peer->hostname, +							binfo->peer->conf_if); +					else +						vty_out(vty, " from %s", +							binfo->peer->conf_if); +				} else { +					if (binfo->peer->hostname +					    && bgp_flag_check( +						       binfo->peer->bgp, +						       BGP_FLAG_SHOW_HOSTNAME)) +						vty_out(vty, " from %s(%s)", +							binfo->peer->hostname, +							binfo->peer->host); +					else +						vty_out(vty, " from %s", +							sockunion2str( +								&binfo->peer +									 ->su, +								buf, +								SU_ADDRSTRLEN)); +				} + +				if (attr->flag +				    & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) +					vty_out(vty, " (%s)", +						inet_ntoa( +							attr->extra +								->originator_id)); +				else +					vty_out(vty, " (%s)", +						inet_ntop( +							AF_INET, +							&binfo->peer->remote_id, +							buf1, BUFSIZ)); +			} +		} + +		if (!json_paths) +			vty_out(vty, "%s", VTY_NEWLINE); + +		/* display the link-local nexthop */ +		if (attr->extra +		    && attr->extra->mp_nexthop_len +			       == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) { +			if (json_paths) { +				json_nexthop_ll = json_object_new_object(); +				json_object_string_add( +					json_nexthop_ll, "ip", +					inet_ntop( +						AF_INET6, +						&attr->extra->mp_nexthop_local, +						buf, INET6_ADDRSTRLEN)); +				json_object_string_add(json_nexthop_ll, "afi", +						       "ipv6"); +				json_object_string_add(json_nexthop_ll, "scope", +						       "link-local"); + +				json_object_boolean_true_add(json_nexthop_ll, +							     "accessible"); + +				if (!attr->extra->mp_nexthop_prefer_global) +					json_object_boolean_true_add( +						json_nexthop_ll, "used"); +				else +					json_object_boolean_true_add( +						json_nexthop_global, "used"); +			} else { +				vty_out(vty, "    (%s) %s%s", +					inet_ntop( +						AF_INET6, +						&attr->extra->mp_nexthop_local, +						buf, INET6_ADDRSTRLEN), +					attr->extra->mp_nexthop_prefer_global +						? "(prefer-global)" +						: "(used)", +					VTY_NEWLINE); +			} +		} +		/* If we do not have a link-local nexthop then we must flag the +		   global as "used" */ +		else { +			if (json_paths) +				json_object_boolean_true_add( +					json_nexthop_global, "used"); +		} + +		/* Line 3 display Origin, Med, Locpref, Weight, Tag, valid, +		 * Int/Ext/Local, Atomic, best */ +		if (json_paths) +			json_object_string_add( +				json_path, "origin", +				bgp_origin_long_str[attr->origin]); +		else +			vty_out(vty, "      Origin %s", +				bgp_origin_long_str[attr->origin]); + +		if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) { +			if (json_paths) +				json_object_int_add(json_path, "med", +						    attr->med); +			else +				vty_out(vty, ", metric %u", attr->med); +		} + +		if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) { +			if (json_paths) +				json_object_int_add(json_path, "localpref", +						    attr->local_pref); +			else +				vty_out(vty, ", localpref %u", +					attr->local_pref); +		} else { +			if (json_paths) +				json_object_int_add(json_path, "localpref", +						    bgp->default_local_pref); +			else +				vty_out(vty, ", localpref %u", +					bgp->default_local_pref); +		} + +		if (attr->extra && attr->extra->weight != 0) { +			if (json_paths) +				json_object_int_add(json_path, "weight", +						    attr->extra->weight); +			else +				vty_out(vty, ", weight %u", +					attr->extra->weight); +		} + +		if (attr->extra && attr->extra->tag != 0) { +			if (json_paths) +				json_object_int_add(json_path, "tag", +						    attr->extra->tag); +			else +				vty_out(vty, ", tag %" ROUTE_TAG_PRI, +					attr->extra->tag); +		} + +		if (!CHECK_FLAG(binfo->flags, BGP_INFO_VALID)) { +			if (json_paths) +				json_object_boolean_false_add(json_path, +							      "valid"); +			else +				vty_out(vty, ", invalid"); +		} else if (!CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) { +			if (json_paths) +				json_object_boolean_true_add(json_path, +							     "valid"); +			else +				vty_out(vty, ", valid"); +		} + +		if (binfo->peer != bgp->peer_self) { +			if (binfo->peer->as == binfo->peer->local_as) { +				if (CHECK_FLAG(bgp->config, +					       BGP_CONFIG_CONFEDERATION)) { +					if (json_paths) +						json_object_string_add( +							json_peer, "type", +							"confed-internal"); +					else +						vty_out(vty, +							", confed-internal"); +				} else { +					if (json_paths) +						json_object_string_add( +							json_peer, "type", +							"internal"); +					else +						vty_out(vty, ", internal"); +				} +			} else { +				if (bgp_confederation_peers_check( +					    bgp, binfo->peer->as)) { +					if (json_paths) +						json_object_string_add( +							json_peer, "type", +							"confed-external"); +					else +						vty_out(vty, +							", confed-external"); +				} else { +					if (json_paths) +						json_object_string_add( +							json_peer, "type", +							"external"); +					else +						vty_out(vty, ", external"); +				} +			} +		} else if (binfo->sub_type == BGP_ROUTE_AGGREGATE) { +			if (json_paths) { +				json_object_boolean_true_add(json_path, +							     "aggregated"); +				json_object_boolean_true_add(json_path, +							     "local"); +			} else { +				vty_out(vty, ", aggregated, local"); +			} +		} else if (binfo->type != ZEBRA_ROUTE_BGP) { +			if (json_paths) +				json_object_boolean_true_add(json_path, +							     "sourced"); +			else +				vty_out(vty, ", sourced"); +		} else { +			if (json_paths) { +				json_object_boolean_true_add(json_path, +							     "sourced"); +				json_object_boolean_true_add(json_path, +							     "local"); +			} else { +				vty_out(vty, ", sourced, local"); +			} +		} + +		if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) { +			if (json_paths) +				json_object_boolean_true_add(json_path, +							     "atomicAggregate"); +			else +				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))) { +			if (json_paths) +				json_object_boolean_true_add(json_path, +							     "multipath"); +			else +				vty_out(vty, ", multipath"); +		} + +		// Mark the bestpath(s) +		if (CHECK_FLAG(binfo->flags, BGP_INFO_DMED_SELECTED)) { +			first_as = aspath_get_first_as(attr->aspath); + +			if (json_paths) { +				if (!json_bestpath) +					json_bestpath = +						json_object_new_object(); +				json_object_int_add(json_bestpath, +						    "bestpathFromAs", first_as); +			} else { +				if (first_as) +					vty_out(vty, ", bestpath-from-AS %d", +						first_as); +				else +					vty_out(vty, +						", bestpath-from-AS Local"); +			} +		} + +		if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED)) { +			if (json_paths) { +				if (!json_bestpath) +					json_bestpath = +						json_object_new_object(); +				json_object_boolean_true_add(json_bestpath, +							     "overall"); +			} else +				vty_out(vty, ", best"); +		} + +		if (json_bestpath) +			json_object_object_add(json_path, "bestpath", +					       json_bestpath); + +		if (!json_paths) +			vty_out(vty, "%s", VTY_NEWLINE); + +		/* Line 4 display Community */ +		if (attr->community) { +			if (json_paths) { +				json_object_lock(attr->community->json); +				json_object_object_add(json_path, "community", +						       attr->community->json); +			} else { +				vty_out(vty, "      Community: %s%s", +					attr->community->str, VTY_NEWLINE); +			} +		} + +		/* Line 5 display Extended-community */ +		if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) { +			if (json_paths) { +				json_ext_community = json_object_new_object(); +				json_object_string_add( +					json_ext_community, "string", +					attr->extra->ecommunity->str); +				json_object_object_add(json_path, +						       "extendedCommunity", +						       json_ext_community); +			} else { +				vty_out(vty, "      Extended Community: %s%s", +					attr->extra->ecommunity->str, +					VTY_NEWLINE); +			} +		} + +		/* Line 6 display Large community */ +		if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) +			vty_out(vty, "      Large Community: %s%s", +				attr->extra->lcommunity->str, VTY_NEWLINE); + +		/* Line 7 display Originator, Cluster-id */ +		if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) +		    || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) { +			assert(attr->extra); +			if (attr->flag +			    & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) { +				if (json_paths) +					json_object_string_add( +						json_path, "originatorId", +						inet_ntoa( +							attr->extra +								->originator_id)); +				else +					vty_out(vty, "      Originator: %s", +						inet_ntoa( +							attr->extra +								->originator_id)); +			} + +			if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) { +				int i; + +				if (json_paths) { +					json_cluster_list = +						json_object_new_object(); +					json_cluster_list_list = +						json_object_new_array(); + +					for (i = 0; +					     i +					     < attr->extra->cluster->length / 4; +					     i++) { +						json_string = json_object_new_string( +							inet_ntoa( +								attr->extra +									->cluster +									->list[i])); +						json_object_array_add( +							json_cluster_list_list, +							json_string); +					} + +					/* struct cluster_list does not have +					"str" variable like +					 * aspath and community do.  Add this +					someday if someone +					 * asks for it. +					json_object_string_add(json_cluster_list, +					"string", attr->extra->cluster->str); +					 */ +					json_object_object_add( +						json_cluster_list, "list", +						json_cluster_list_list); +					json_object_object_add( +						json_path, "clusterList", +						json_cluster_list); +				} else { +					vty_out(vty, ", Cluster list: "); + +					for (i = 0; +					     i +					     < attr->extra->cluster->length / 4; +					     i++) { +						vty_out(vty, "%s ", +							inet_ntoa( +								attr->extra +									->cluster +									->list[i])); +					} +				} +			} + +			if (!json_paths) +				vty_out(vty, "%s", VTY_NEWLINE); +		} + +		if (binfo->extra && binfo->extra->damp_info) +			bgp_damp_info_vty(vty, binfo, json_path); + +		/* Line 8 display Addpath IDs */ +		if (binfo->addpath_rx_id || binfo->addpath_tx_id) { +			if (json_paths) { +				json_object_int_add(json_path, "addpathRxId", +						    binfo->addpath_rx_id); +				json_object_int_add(json_path, "addpathTxId", +						    binfo->addpath_tx_id); +			} else { +				vty_out(vty, "      AddPath ID: RX %u, TX %u%s", +					binfo->addpath_rx_id, +					binfo->addpath_tx_id, VTY_NEWLINE); +			} +		} + +		/* If we used addpath to TX a non-bestpath we need to display +		 * "Advertised to" on a path-by-path basis */ +		if (bgp->addpath_tx_used[afi][safi]) { +			first = 1; + +			for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { +				addpath_capable = +					bgp_addpath_encode_tx(peer, afi, safi); +				has_adj = bgp_adj_out_lookup( +					peer, binfo->net, binfo->addpath_tx_id); + +				if ((addpath_capable && has_adj) +				    || (!addpath_capable && has_adj +					&& CHECK_FLAG(binfo->flags, +						      BGP_INFO_SELECTED))) { +					if (json_path && !json_adv_to) +						json_adv_to = +							json_object_new_object(); + +					route_vty_out_advertised_to( +						vty, peer, &first, +						"      Advertised to:", +						json_adv_to); +				} +			} + +			if (json_path) { +				if (json_adv_to) { +					json_object_object_add(json_path, +							       "advertisedTo", +							       json_adv_to); +				} +			} else { +				if (!first) { +					vty_out(vty, "%s", VTY_NEWLINE); +				} +			} +		} + +		/* Line 9 display Uptime */ +		tbuf = time(NULL) - (bgp_clock() - binfo->uptime); +		if (json_paths) { +			json_last_update = json_object_new_object(); +			json_object_int_add(json_last_update, "epoch", tbuf); +			json_object_string_add(json_last_update, "string", +					       ctime(&tbuf)); +			json_object_object_add(json_path, "lastUpdate", +					       json_last_update); +		} else +			vty_out(vty, "      Last update: %s", ctime(&tbuf)); +	} + +	/* We've constructed the json object for this path, add it to the json +	 * array of paths +	 */ +	if (json_paths) { +		if (json_nexthop_global || json_nexthop_ll) { +			json_nexthops = json_object_new_array(); + +			if (json_nexthop_global) +				json_object_array_add(json_nexthops, +						      json_nexthop_global); + +			if (json_nexthop_ll) +				json_object_array_add(json_nexthops, +						      json_nexthop_ll); + +			json_object_object_add(json_path, "nexthops", +					       json_nexthops); +		} + +		json_object_object_add(json_path, "peer", json_peer); +		json_object_array_add(json_paths, json_path); +	} else +		vty_out(vty, "%s", VTY_NEWLINE);  }  #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path%s"  #define BGP_SHOW_DAMP_HEADER "   Network          From             Reuse    Path%s"  #define BGP_SHOW_FLAP_HEADER "   Network          From            Flaps Duration Reuse    Path%s" -static int -bgp_show_prefix_list (struct vty *vty, struct bgp *bgp, -                      const char *prefix_list_str, afi_t afi, -                      safi_t safi, enum bgp_show_type type); -static int -bgp_show_filter_list (struct vty *vty, struct bgp *bgp, -                      const char *filter, afi_t afi, -                      safi_t safi, enum bgp_show_type type); -static int -bgp_show_route_map (struct vty *vty, struct bgp *bgp, -                    const char *rmap_str, afi_t afi, -                    safi_t safi, enum bgp_show_type type); -static int -bgp_show_community_list (struct vty *vty, struct bgp *bgp, -                         const char *com, int exact, -                         afi_t afi, safi_t safi); -static int -bgp_show_prefix_longer (struct vty *vty, struct bgp *bgp, -                        const char *prefix, afi_t afi, -                        safi_t safi, enum bgp_show_type type); -static int -bgp_show_regexp (struct vty *vty, const char *regstr, afi_t afi, -		 safi_t safi, enum bgp_show_type type); -static int -bgp_show_community (struct vty *vty, struct bgp *bgp, int argc, -		    struct cmd_token **argv, int exact, afi_t afi, safi_t safi); - -static int -bgp_show_table (struct vty *vty, struct bgp *bgp, struct bgp_table *table, -                enum bgp_show_type type, void *output_arg, u_char use_json) -{ -  struct bgp_info *ri; -  struct bgp_node *rn; -  int header = 1; -  int display; -  unsigned long output_count; -  unsigned long total_count; -  struct prefix *p; -  char buf[BUFSIZ]; -  char buf2[BUFSIZ]; -  json_object *json_paths = NULL; -  int first = 1; - -  if (use_json) -    { -      vty_out (vty, "{ \"vrfId\": %d, \"vrfName\": \"%s\", \"tableVersion\": %" PRId64 ", \"routerId\": \"%s\", \"routes\": { ", -	       bgp->vrf_id == VRF_UNKNOWN ? -1 : bgp->vrf_id, -	       bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT ? "Default" : bgp->name, -	       table->version, inet_ntoa (bgp->router_id)); -      json_paths = json_object_new_object(); -    } +static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp, +				const char *prefix_list_str, afi_t afi, +				safi_t safi, enum bgp_show_type type); +static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp, +				const char *filter, afi_t afi, safi_t safi, +				enum bgp_show_type type); +static int bgp_show_route_map(struct vty *vty, struct bgp *bgp, +			      const char *rmap_str, afi_t afi, safi_t safi, +			      enum bgp_show_type type); +static int bgp_show_community_list(struct vty *vty, struct bgp *bgp, +				   const char *com, int exact, afi_t afi, +				   safi_t safi); +static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp, +				  const char *prefix, afi_t afi, safi_t safi, +				  enum bgp_show_type type); +static int bgp_show_regexp(struct vty *vty, const char *regstr, afi_t afi, +			   safi_t safi, enum bgp_show_type type); +static int bgp_show_community(struct vty *vty, struct bgp *bgp, int argc, +			      struct cmd_token **argv, int exact, afi_t afi, +			      safi_t safi); + +static int bgp_show_table(struct vty *vty, struct bgp *bgp, +			  struct bgp_table *table, enum bgp_show_type type, +			  void *output_arg, u_char use_json) +{ +	struct bgp_info *ri; +	struct bgp_node *rn; +	int header = 1; +	int display; +	unsigned long output_count; +	unsigned long total_count; +	struct prefix *p; +	char buf[BUFSIZ]; +	char buf2[BUFSIZ]; +	json_object *json_paths = NULL; +	int first = 1; + +	if (use_json) { +		vty_out(vty, +			"{ \"vrfId\": %d, \"vrfName\": \"%s\", \"tableVersion\": %" PRId64 +			", \"routerId\": \"%s\", \"routes\": { ", +			bgp->vrf_id == VRF_UNKNOWN ? -1 : bgp->vrf_id, +			bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT ? "Default" +								    : bgp->name, +			table->version, inet_ntoa(bgp->router_id)); +		json_paths = json_object_new_object(); +	} -  /* This is first entry point, so reset total line. */ -  output_count = 0; -  total_count  = 0; - -  /* Start processing of routes. */ -  for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))  -    if (rn->info != NULL) -      { -        display = 0; -	if (!first && use_json) -	  { -	    vty_out (vty, ","); -	  } -        if (use_json) -          json_paths = json_object_new_array(); -        else -          json_paths = NULL; - -        for (ri = rn->info; ri; ri = ri->next) -          { -            total_count++; -            if (type == bgp_show_type_flap_statistics -                || type == bgp_show_type_flap_neighbor -                || type == bgp_show_type_dampend_paths -                || type == bgp_show_type_damp_neighbor) -              { -                if (!(ri->extra && ri->extra->damp_info)) -                  continue; -              } -            if (type == bgp_show_type_regexp) -              { -                regex_t *regex = output_arg; - -                if (bgp_regexec (regex, ri->attr->aspath) == REG_NOMATCH) -                  continue; -              } -            if (type == bgp_show_type_prefix_list) -              { -                struct prefix_list *plist = output_arg; - -                if (prefix_list_apply (plist, &rn->p) != PREFIX_PERMIT) -                  continue; -              } -            if (type == bgp_show_type_filter_list) -              { -                struct as_list *as_list = output_arg; - -                if (as_list_apply (as_list, ri->attr->aspath) != AS_FILTER_PERMIT) -                  continue; -              } -            if (type == bgp_show_type_route_map) -              { -                struct route_map *rmap = output_arg; -                struct bgp_info binfo; -                struct attr dummy_attr; -                struct attr_extra dummy_extra; -                int ret; - -                dummy_attr.extra = &dummy_extra; -                bgp_attr_dup (&dummy_attr, ri->attr); - -                binfo.peer = ri->peer; -                binfo.attr = &dummy_attr; - -                ret = route_map_apply (rmap, &rn->p, RMAP_BGP, &binfo); -                if (ret == RMAP_DENYMATCH) -                  continue; -              } -            if (type == bgp_show_type_neighbor -                || type == bgp_show_type_flap_neighbor -                || type == bgp_show_type_damp_neighbor) -              { -                union sockunion *su = output_arg; - -                if (ri->peer == NULL || -                    ri->peer->su_remote == NULL || ! sockunion_same(ri->peer->su_remote, su)) -                  continue; -              } -            if (type == bgp_show_type_cidr_only) -              { -                u_int32_t destination; - -                destination = ntohl (rn->p.u.prefix4.s_addr); -                if (IN_CLASSC (destination) && rn->p.prefixlen == 24) -                  continue; -                if (IN_CLASSB (destination) && rn->p.prefixlen == 16) -                  continue; -                if (IN_CLASSA (destination) && rn->p.prefixlen == 8) -                  continue; -              } -            if (type == bgp_show_type_prefix_longer) -              { -                struct prefix *p = output_arg; - -                if (! prefix_match (p, &rn->p)) -                  continue; -              } -            if (type == bgp_show_type_community_all) -              { -                if (! ri->attr->community) -                  continue; -              } -            if (type == bgp_show_type_community) -              { -                struct community *com = output_arg; - -                if (! ri->attr->community || -                    ! community_match (ri->attr->community, com)) -                  continue; -              } -            if (type == bgp_show_type_community_exact) -              { -                struct community *com = output_arg; - -                if (! ri->attr->community || -                    ! community_cmp (ri->attr->community, com)) -                  continue; -              } -            if (type == bgp_show_type_community_list) -              { -                struct community_list *list = output_arg; - -                if (! community_list_match (ri->attr->community, list)) -                  continue; -              } -            if (type == bgp_show_type_community_list_exact) -              { -                struct community_list *list = output_arg; - -                if (! community_list_exact_match (ri->attr->community, list)) -                  continue; -              } -            if (type == bgp_show_type_lcommunity) -              { -                struct lcommunity *lcom = output_arg; - -                if (! ri->attr->extra || ! ri->attr->extra->lcommunity || -                    ! lcommunity_match (ri->attr->extra->lcommunity, lcom)) -                  continue; -              } -            if (type == bgp_show_type_lcommunity_list) -              { -                struct community_list *list = output_arg; - -                if (! ri->attr->extra || -                    ! lcommunity_list_match (ri->attr->extra->lcommunity, list)) -                  continue; -              } -            if (type == bgp_show_type_lcommunity_all) -              { -                if (! ri->attr->extra || ! ri->attr->extra->lcommunity) -                  continue; -              } -            if (type == bgp_show_type_dampend_paths -                || type == bgp_show_type_damp_neighbor) -              { -                if (! CHECK_FLAG (ri->flags, BGP_INFO_DAMPED) -                    || CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) -                  continue; -              } - -            if (!use_json && header) -              { -                vty_out (vty, "BGP table version is %" PRIu64 ", local router ID is %s%s", table->version, inet_ntoa (bgp->router_id), VTY_NEWLINE); -                vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE); -                vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE); -                if (type == bgp_show_type_dampend_paths -                    || type == bgp_show_type_damp_neighbor) -                  vty_out (vty, BGP_SHOW_DAMP_HEADER, VTY_NEWLINE); -                else if (type == bgp_show_type_flap_statistics -                         || type == bgp_show_type_flap_neighbor) -                  vty_out (vty, BGP_SHOW_FLAP_HEADER, VTY_NEWLINE); -                else -                  vty_out (vty, BGP_SHOW_HEADER, VTY_NEWLINE); -                header = 0; -              } - -            if (type == bgp_show_type_dampend_paths -                || type == bgp_show_type_damp_neighbor) -              damp_route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST, use_json, json_paths); -            else if (type == bgp_show_type_flap_statistics -                     || type == bgp_show_type_flap_neighbor) -              flap_route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST, use_json, json_paths); -            else -              route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST, json_paths); -            display++; -          } - -        if (display) -          { -            output_count++; -            if (use_json) -              { -                p = &rn->p; -                sprintf(buf2, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), p->prefixlen); -		vty_out (vty, "\"%s\": ", buf2); -		vty_out (vty, "%s", json_object_to_json_string (json_paths)); -		json_object_free (json_paths); -		first = 0; - -              } -          } -        } - -  if (use_json) -    { -      json_object_free (json_paths); -      vty_out (vty, " } }%s", VTY_NEWLINE); -    } -  else -    { -      /* No route is displayed */ -      if (output_count == 0) -        { -          if (type == bgp_show_type_normal) -            vty_out (vty, "No BGP prefixes displayed, %ld exist%s", total_count, VTY_NEWLINE); -        } -      else -        vty_out (vty, "%sDisplayed  %ld routes and %ld total paths%s", -                 VTY_NEWLINE, output_count, total_count, VTY_NEWLINE); -    } +	/* This is first entry point, so reset total line. */ +	output_count = 0; +	total_count = 0; + +	/* Start processing of routes. */ +	for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) +		if (rn->info != NULL) { +			display = 0; +			if (!first && use_json) { +				vty_out(vty, ","); +			} +			if (use_json) +				json_paths = json_object_new_array(); +			else +				json_paths = NULL; + +			for (ri = rn->info; ri; ri = ri->next) { +				total_count++; +				if (type == bgp_show_type_flap_statistics +				    || type == bgp_show_type_flap_neighbor +				    || type == bgp_show_type_dampend_paths +				    || type == bgp_show_type_damp_neighbor) { +					if (!(ri->extra +					      && ri->extra->damp_info)) +						continue; +				} +				if (type == bgp_show_type_regexp) { +					regex_t *regex = output_arg; + +					if (bgp_regexec(regex, ri->attr->aspath) +					    == REG_NOMATCH) +						continue; +				} +				if (type == bgp_show_type_prefix_list) { +					struct prefix_list *plist = output_arg; + +					if (prefix_list_apply(plist, &rn->p) +					    != PREFIX_PERMIT) +						continue; +				} +				if (type == bgp_show_type_filter_list) { +					struct as_list *as_list = output_arg; + +					if (as_list_apply(as_list, +							  ri->attr->aspath) +					    != AS_FILTER_PERMIT) +						continue; +				} +				if (type == bgp_show_type_route_map) { +					struct route_map *rmap = output_arg; +					struct bgp_info binfo; +					struct attr dummy_attr; +					struct attr_extra dummy_extra; +					int ret; + +					dummy_attr.extra = &dummy_extra; +					bgp_attr_dup(&dummy_attr, ri->attr); + +					binfo.peer = ri->peer; +					binfo.attr = &dummy_attr; + +					ret = route_map_apply(rmap, &rn->p, +							      RMAP_BGP, &binfo); +					if (ret == RMAP_DENYMATCH) +						continue; +				} +				if (type == bgp_show_type_neighbor +				    || type == bgp_show_type_flap_neighbor +				    || type == bgp_show_type_damp_neighbor) { +					union sockunion *su = output_arg; + +					if (ri->peer == NULL +					    || ri->peer->su_remote == NULL +					    || !sockunion_same( +						       ri->peer->su_remote, su)) +						continue; +				} +				if (type == bgp_show_type_cidr_only) { +					u_int32_t destination; + +					destination = +						ntohl(rn->p.u.prefix4.s_addr); +					if (IN_CLASSC(destination) +					    && rn->p.prefixlen == 24) +						continue; +					if (IN_CLASSB(destination) +					    && rn->p.prefixlen == 16) +						continue; +					if (IN_CLASSA(destination) +					    && rn->p.prefixlen == 8) +						continue; +				} +				if (type == bgp_show_type_prefix_longer) { +					struct prefix *p = output_arg; + +					if (!prefix_match(p, &rn->p)) +						continue; +				} +				if (type == bgp_show_type_community_all) { +					if (!ri->attr->community) +						continue; +				} +				if (type == bgp_show_type_community) { +					struct community *com = output_arg; + +					if (!ri->attr->community +					    || !community_match( +						       ri->attr->community, +						       com)) +						continue; +				} +				if (type == bgp_show_type_community_exact) { +					struct community *com = output_arg; + +					if (!ri->attr->community +					    || !community_cmp( +						       ri->attr->community, +						       com)) +						continue; +				} +				if (type == bgp_show_type_community_list) { +					struct community_list *list = +						output_arg; + +					if (!community_list_match( +						    ri->attr->community, list)) +						continue; +				} +				if (type +				    == bgp_show_type_community_list_exact) { +					struct community_list *list = +						output_arg; + +					if (!community_list_exact_match( +						    ri->attr->community, list)) +						continue; +				} +				if (type == bgp_show_type_lcommunity) { +					struct lcommunity *lcom = output_arg; + +					if (!ri->attr->extra +					    || !ri->attr->extra->lcommunity +					    || !lcommunity_match( +						       ri->attr->extra +							       ->lcommunity, +						       lcom)) +						continue; +				} +				if (type == bgp_show_type_lcommunity_list) { +					struct community_list *list = +						output_arg; + +					if (!ri->attr->extra +					    || !lcommunity_list_match( +						       ri->attr->extra +							       ->lcommunity, +						       list)) +						continue; +				} +				if (type == bgp_show_type_lcommunity_all) { +					if (!ri->attr->extra +					    || !ri->attr->extra->lcommunity) +						continue; +				} +				if (type == bgp_show_type_dampend_paths +				    || type == bgp_show_type_damp_neighbor) { +					if (!CHECK_FLAG(ri->flags, +							BGP_INFO_DAMPED) +					    || CHECK_FLAG(ri->flags, +							  BGP_INFO_HISTORY)) +						continue; +				} + +				if (!use_json && header) { +					vty_out(vty, +						"BGP table version is %" PRIu64 +						", local router ID is %s%s", +						table->version, +						inet_ntoa(bgp->router_id), +						VTY_NEWLINE); +					vty_out(vty, BGP_SHOW_SCODE_HEADER, +						VTY_NEWLINE, VTY_NEWLINE); +					vty_out(vty, BGP_SHOW_OCODE_HEADER, +						VTY_NEWLINE, VTY_NEWLINE); +					if (type == bgp_show_type_dampend_paths +					    || type == bgp_show_type_damp_neighbor) +						vty_out(vty, +							BGP_SHOW_DAMP_HEADER, +							VTY_NEWLINE); +					else if ( +						type == bgp_show_type_flap_statistics +						|| type == bgp_show_type_flap_neighbor) +						vty_out(vty, +							BGP_SHOW_FLAP_HEADER, +							VTY_NEWLINE); +					else +						vty_out(vty, BGP_SHOW_HEADER, +							VTY_NEWLINE); +					header = 0; +				} + +				if (type == bgp_show_type_dampend_paths +				    || type == bgp_show_type_damp_neighbor) +					damp_route_vty_out( +						vty, &rn->p, ri, display, +						SAFI_UNICAST, use_json, +						json_paths); +				else if (type == bgp_show_type_flap_statistics +					 || type == bgp_show_type_flap_neighbor) +					flap_route_vty_out( +						vty, &rn->p, ri, display, +						SAFI_UNICAST, use_json, +						json_paths); +				else +					route_vty_out(vty, &rn->p, ri, display, +						      SAFI_UNICAST, json_paths); +				display++; +			} + +			if (display) { +				output_count++; +				if (use_json) { +					p = &rn->p; +					sprintf(buf2, "%s/%d", +						inet_ntop(p->family, +							  &p->u.prefix, buf, +							  BUFSIZ), +						p->prefixlen); +					vty_out(vty, "\"%s\": ", buf2); +					vty_out(vty, "%s", +						json_object_to_json_string( +							json_paths)); +					json_object_free(json_paths); +					first = 0; +				} +			} +		} + +	if (use_json) { +		json_object_free(json_paths); +		vty_out(vty, " } }%s", VTY_NEWLINE); +	} else { +		/* No route is displayed */ +		if (output_count == 0) { +			if (type == bgp_show_type_normal) +				vty_out(vty, +					"No BGP prefixes displayed, %ld exist%s", +					total_count, VTY_NEWLINE); +		} else +			vty_out(vty, +				"%sDisplayed  %ld routes and %ld total paths%s", +				VTY_NEWLINE, output_count, total_count, +				VTY_NEWLINE); +	} -  return CMD_SUCCESS; +	return CMD_SUCCESS;  } -static int -bgp_show (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, -          enum bgp_show_type type, void *output_arg, u_char use_json) +static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, +		    enum bgp_show_type type, void *output_arg, u_char use_json)  { -  struct bgp_table *table; +	struct bgp_table *table; -  if (bgp == NULL) -    { -      bgp = bgp_get_default (); -    } +	if (bgp == NULL) { +		bgp = bgp_get_default(); +	} -  if (bgp == NULL) -    { -      if (!use_json) -        vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); -      return CMD_WARNING; -    } -  /* use MPLS and ENCAP specific shows until they are merged */ -  if (safi == SAFI_MPLS_VPN)  -    { -      return bgp_show_mpls_vpn(vty, afi, NULL, type, output_arg, -                               0, use_json); -    } +	if (bgp == NULL) { +		if (!use_json) +			vty_out(vty, "No BGP process is configured%s", +				VTY_NEWLINE); +		return CMD_WARNING; +	} +	/* use MPLS and ENCAP specific shows until they are merged */ +	if (safi == SAFI_MPLS_VPN) { +		return bgp_show_mpls_vpn(vty, afi, NULL, type, output_arg, 0, +					 use_json); +	} -  table = bgp->rib[afi][safi]; +	table = bgp->rib[afi][safi]; -  return bgp_show_table (vty, bgp, table, type, output_arg, -                         use_json); +	return bgp_show_table(vty, bgp, table, type, output_arg, use_json);  } -static void -bgp_show_all_instances_routes_vty (struct vty *vty, afi_t afi, safi_t safi, -                                   u_char use_json) +static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi, +					      safi_t safi, u_char use_json)  { -  struct listnode *node, *nnode; -  struct bgp *bgp; -  int is_first = 1; +	struct listnode *node, *nnode; +	struct bgp *bgp; +	int is_first = 1; -  if (use_json) -    vty_out (vty, "{%s", VTY_NEWLINE); +	if (use_json) +		vty_out(vty, "{%s", VTY_NEWLINE); -  for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) -    { -      if (use_json) -        { -          if (! is_first) -            vty_out (vty, ",%s", VTY_NEWLINE); -          else -            is_first = 0; - -          vty_out(vty, "\"%s\":", (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) -                  ? "Default" : bgp->name); -        } -      else -        { -          vty_out (vty, "%sInstance %s:%s", -                   VTY_NEWLINE, -                   (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) -                   ? "Default" : bgp->name, -                   VTY_NEWLINE); -        } -      bgp_show (vty, bgp, afi, safi, bgp_show_type_normal, NULL, use_json); - -    } +	for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) { +		if (use_json) { +			if (!is_first) +				vty_out(vty, ",%s", VTY_NEWLINE); +			else +				is_first = 0; + +			vty_out(vty, "\"%s\":", +				(bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) +					? "Default" +					: bgp->name); +		} else { +			vty_out(vty, "%sInstance %s:%s", VTY_NEWLINE, +				(bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) +					? "Default" +					: bgp->name, +				VTY_NEWLINE); +		} +		bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL, +			 use_json); +	} -  if (use_json) -    vty_out (vty, "}%s", VTY_NEWLINE); +	if (use_json) +		vty_out(vty, "}%s", VTY_NEWLINE);  }  /* Header of detailed BGP route information */ -static void -route_vty_out_detail_header (struct vty *vty, struct bgp *bgp, -			     struct bgp_node *rn, -                             struct prefix_rd *prd, afi_t afi, safi_t safi, -                             json_object *json) -{ -  struct bgp_info *ri; -  struct prefix *p; -  struct peer *peer; -  struct listnode *node, *nnode; -  char buf1[INET6_ADDRSTRLEN]; -  char buf2[INET6_ADDRSTRLEN]; -  int count = 0; -  int best = 0; -  int suppress = 0; -  int no_export = 0; -  int no_advertise = 0; -  int local_as = 0; -  int first = 1; -  json_object *json_adv_to = NULL; - -  p = &rn->p; - -  if (json) -    { -      json_object_string_add(json, "prefix", inet_ntop (p->family, &p->u.prefix, buf2, INET6_ADDRSTRLEN)); -      json_object_int_add(json, "prefixlen", p->prefixlen); -    } -  else -    { -      if (p->family == AF_ETHERNET) -        prefix2str (p, buf2, INET6_ADDRSTRLEN); -      else -        inet_ntop (p->family, &p->u.prefix, buf2, INET6_ADDRSTRLEN); -      vty_out (vty, "BGP routing table entry for %s%s%s/%d%s", -	       ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) ? -	       prefix_rd2str (prd, buf1, RD_ADDRSTRLEN) : ""), -	       ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN)) ? ":" : "", -	       buf2, -	       p->prefixlen, VTY_NEWLINE); -    } +static void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp, +					struct bgp_node *rn, +					struct prefix_rd *prd, afi_t afi, +					safi_t safi, json_object *json) +{ +	struct bgp_info *ri; +	struct prefix *p; +	struct peer *peer; +	struct listnode *node, *nnode; +	char buf1[INET6_ADDRSTRLEN]; +	char buf2[INET6_ADDRSTRLEN]; +	int count = 0; +	int best = 0; +	int suppress = 0; +	int no_export = 0; +	int no_advertise = 0; +	int local_as = 0; +	int first = 1; +	json_object *json_adv_to = NULL; -  for (ri = rn->info; ri; ri = ri->next) -    { -      count++; -      if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) -	{ -	  best = count; -	  if (ri->extra && ri->extra->suppress) -	    suppress = 1; -	  if (ri->attr->community != NULL) -	    { -	      if (community_include (ri->attr->community, COMMUNITY_NO_ADVERTISE)) -		no_advertise = 1; -	      if (community_include (ri->attr->community, COMMUNITY_NO_EXPORT)) -		no_export = 1; -	      if (community_include (ri->attr->community, COMMUNITY_LOCAL_AS)) -		local_as = 1; -	    } +	p = &rn->p; + +	if (json) { +		json_object_string_add(json, "prefix", +				       inet_ntop(p->family, &p->u.prefix, buf2, +						 INET6_ADDRSTRLEN)); +		json_object_int_add(json, "prefixlen", p->prefixlen); +	} else { +		if (p->family == AF_ETHERNET) +			prefix2str(p, buf2, INET6_ADDRSTRLEN); +		else +			inet_ntop(p->family, &p->u.prefix, buf2, +				  INET6_ADDRSTRLEN); +		vty_out(vty, "BGP routing table entry for %s%s%s/%d%s", +			((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP +			  || safi == SAFI_EVPN) +				 ? prefix_rd2str(prd, buf1, RD_ADDRSTRLEN) +				 : ""), +			((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN)) ? ":" +									 : "", +			buf2, p->prefixlen, VTY_NEWLINE);  	} -    } -  if (!json) -    { -      vty_out (vty, "Paths: (%d available", count); -      if (best) -        { -          vty_out (vty, ", best #%d", best); -          if (safi == SAFI_UNICAST) -            vty_out (vty, ", table %s", -                     (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) -                     ? "Default-IP-Routing-Table" : bgp->name); -        } -      else -        vty_out (vty, ", no best path"); - -      if (no_advertise) -        vty_out (vty, ", not advertised to any peer"); -      else if (no_export) -        vty_out (vty, ", not advertised to EBGP peer"); -      else if (local_as) -        vty_out (vty, ", not advertised outside local AS"); - -      if (suppress) -        vty_out (vty, ", Advertisements suppressed by an aggregate."); -      vty_out (vty, ")%s", VTY_NEWLINE); -    } +	for (ri = rn->info; ri; ri = ri->next) { +		count++; +		if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) { +			best = count; +			if (ri->extra && ri->extra->suppress) +				suppress = 1; +			if (ri->attr->community != NULL) { +				if (community_include(ri->attr->community, +						      COMMUNITY_NO_ADVERTISE)) +					no_advertise = 1; +				if (community_include(ri->attr->community, +						      COMMUNITY_NO_EXPORT)) +					no_export = 1; +				if (community_include(ri->attr->community, +						      COMMUNITY_LOCAL_AS)) +					local_as = 1; +			} +		} +	} -  /* If we are not using addpath then we can display Advertised to and that will -   * show what peers we advertised the bestpath to.  If we are using addpath -   * though then we must display Advertised to on a path-by-path basis. */ -  if (!bgp->addpath_tx_used[afi][safi]) -    { -      for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) -        { -          if (bgp_adj_out_lookup (peer, rn, 0)) -            { -              if (json && !json_adv_to) -                json_adv_to = json_object_new_object(); - -              route_vty_out_advertised_to(vty, peer, &first, -                                          "  Advertised to non peer-group peers:\n ", -                                          json_adv_to); -            } -        } - -      if (json) -        { -          if (json_adv_to) -            { -              json_object_object_add(json, "advertisedTo", json_adv_to); -            } -        } -      else -        { -          if (first) -            vty_out (vty, "  Not advertised to any peer"); -          vty_out (vty, "%s", VTY_NEWLINE); -        } -    } +	if (!json) { +		vty_out(vty, "Paths: (%d available", count); +		if (best) { +			vty_out(vty, ", best #%d", best); +			if (safi == SAFI_UNICAST) +				vty_out(vty, ", table %s", +					(bgp->inst_type +					 == BGP_INSTANCE_TYPE_DEFAULT) +						? "Default-IP-Routing-Table" +						: bgp->name); +		} else +			vty_out(vty, ", no best path"); + +		if (no_advertise) +			vty_out(vty, ", not advertised to any peer"); +		else if (no_export) +			vty_out(vty, ", not advertised to EBGP peer"); +		else if (local_as) +			vty_out(vty, ", not advertised outside local AS"); + +		if (suppress) +			vty_out(vty, +				", Advertisements suppressed by an aggregate."); +		vty_out(vty, ")%s", VTY_NEWLINE); +	} + +	/* If we are not using addpath then we can display Advertised to and +	 * that will +	 * show what peers we advertised the bestpath to.  If we are using +	 * addpath +	 * though then we must display Advertised to on a path-by-path basis. */ +	if (!bgp->addpath_tx_used[afi][safi]) { +		for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { +			if (bgp_adj_out_lookup(peer, rn, 0)) { +				if (json && !json_adv_to) +					json_adv_to = json_object_new_object(); + +				route_vty_out_advertised_to( +					vty, peer, &first, +					"  Advertised to non peer-group peers:\n ", +					json_adv_to); +			} +		} + +		if (json) { +			if (json_adv_to) { +				json_object_object_add(json, "advertisedTo", +						       json_adv_to); +			} +		} else { +			if (first) +				vty_out(vty, "  Not advertised to any peer"); +			vty_out(vty, "%s", VTY_NEWLINE); +		} +	}  }  /* Display specified route of BGP table. */ -static int -bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,  -                         struct bgp_table *rib, const char *ip_str, -                         afi_t afi, safi_t safi, struct prefix_rd *prd, -                         int prefix_check, enum bgp_path_type pathtype, -                         u_char use_json) -{ -  int ret; -  int header; -  int display = 0; -  struct prefix match; -  struct bgp_node *rn; -  struct bgp_node *rm; -  struct bgp_info *ri; -  struct bgp_table *table; -  json_object *json = NULL; -  json_object *json_paths = NULL; - -  /* Check IP address argument. */ -  ret = str2prefix (ip_str, &match); -  if (! ret) -    { -      vty_out (vty, "address is malformed%s", VTY_NEWLINE); -      return CMD_WARNING; -    } - -  match.family = afi2family (afi); +static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp, +				   struct bgp_table *rib, const char *ip_str, +				   afi_t afi, safi_t safi, +				   struct prefix_rd *prd, int prefix_check, +				   enum bgp_path_type pathtype, u_char use_json) +{ +	int ret; +	int header; +	int display = 0; +	struct prefix match; +	struct bgp_node *rn; +	struct bgp_node *rm; +	struct bgp_info *ri; +	struct bgp_table *table; +	json_object *json = NULL; +	json_object *json_paths = NULL; + +	/* Check IP address argument. */ +	ret = str2prefix(ip_str, &match); +	if (!ret) { +		vty_out(vty, "address is malformed%s", VTY_NEWLINE); +		return CMD_WARNING; +	} -  if (use_json) -    { -      json = json_object_new_object(); -      json_paths = json_object_new_array(); -    } +	match.family = afi2family(afi); -  if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) -    { -      for (rn = bgp_table_top (rib); rn; rn = bgp_route_next (rn)) -        { -          if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0) -            continue; - -          if ((table = rn->info) != NULL) -            { -              header = 1; - -              if ((rm = bgp_node_match (table, &match)) != NULL) -                { -                  if (prefix_check && rm->p.prefixlen != match.prefixlen) -                    { -                      bgp_unlock_node (rm); -                      continue; -                    } - -                  for (ri = rm->info; ri; ri = ri->next) -                    { -                      if (header) -                        { -                          route_vty_out_detail_header (vty, bgp, rm, (struct prefix_rd *)&rn->p, -                                                       AFI_IP, safi, json); -                          header = 0; -                        } -                      display++; - -                      if (pathtype == BGP_PATH_ALL || -                          (pathtype == BGP_PATH_BESTPATH && CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) || -                          (pathtype == BGP_PATH_MULTIPATH && -                           (CHECK_FLAG (ri->flags, BGP_INFO_MULTIPATH) || CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)))) -                        route_vty_out_detail (vty, bgp, &rm->p, ri, AFI_IP, safi, json_paths); -                    } - -                  bgp_unlock_node (rm); -                } -            } -        } -    } -  else -    { -      header = 1; - -      if ((rn = bgp_node_match (rib, &match)) != NULL) -        { -          if (! prefix_check || rn->p.prefixlen == match.prefixlen) -            { -              for (ri = rn->info; ri; ri = ri->next) -                { -                  if (header) -                    { -                      route_vty_out_detail_header (vty, bgp, rn, NULL, afi, safi, json); -                      header = 0; -                    } -                  display++; - -                  if (pathtype == BGP_PATH_ALL || -                      (pathtype == BGP_PATH_BESTPATH && CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) || -                      (pathtype == BGP_PATH_MULTIPATH && -                       (CHECK_FLAG (ri->flags, BGP_INFO_MULTIPATH) || CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)))) -                    route_vty_out_detail (vty, bgp, &rn->p, ri, afi, safi, json_paths); -                } -            } - -          bgp_unlock_node (rn); -        } -    } +	if (use_json) { +		json = json_object_new_object(); +		json_paths = json_object_new_array(); +	} -  if (use_json) -    { -      if (display) -        json_object_object_add(json, "paths", json_paths); +	if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) { +		for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) { +			if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0) +				continue; + +			if ((table = rn->info) != NULL) { +				header = 1; + +				if ((rm = bgp_node_match(table, &match)) +				    != NULL) { +					if (prefix_check +					    && rm->p.prefixlen +						       != match.prefixlen) { +						bgp_unlock_node(rm); +						continue; +					} + +					for (ri = rm->info; ri; ri = ri->next) { +						if (header) { +							route_vty_out_detail_header( +								vty, bgp, rm, +								(struct +								 prefix_rd *)&rn +									->p, +								AFI_IP, safi, +								json); +							header = 0; +						} +						display++; + +						if (pathtype == BGP_PATH_ALL +						    || (pathtype +								== BGP_PATH_BESTPATH +							&& CHECK_FLAG( +								   ri->flags, +								   BGP_INFO_SELECTED)) +						    || (pathtype +								== BGP_PATH_MULTIPATH +							&& (CHECK_FLAG( +								    ri->flags, +								    BGP_INFO_MULTIPATH) +							    || CHECK_FLAG( +								       ri->flags, +								       BGP_INFO_SELECTED)))) +							route_vty_out_detail( +								vty, bgp, +								&rm->p, ri, +								AFI_IP, safi, +								json_paths); +					} + +					bgp_unlock_node(rm); +				} +			} +		} +	} else { +		header = 1; + +		if ((rn = bgp_node_match(rib, &match)) != NULL) { +			if (!prefix_check +			    || rn->p.prefixlen == match.prefixlen) { +				for (ri = rn->info; ri; ri = ri->next) { +					if (header) { +						route_vty_out_detail_header( +							vty, bgp, rn, NULL, afi, +							safi, json); +						header = 0; +					} +					display++; + +					if (pathtype == BGP_PATH_ALL +					    || (pathtype == BGP_PATH_BESTPATH +						&& CHECK_FLAG( +							   ri->flags, +							   BGP_INFO_SELECTED)) +					    || (pathtype == BGP_PATH_MULTIPATH +						&& (CHECK_FLAG( +							    ri->flags, +							    BGP_INFO_MULTIPATH) +						    || CHECK_FLAG( +							       ri->flags, +							       BGP_INFO_SELECTED)))) +						route_vty_out_detail( +							vty, bgp, &rn->p, ri, +							afi, safi, json_paths); +				} +			} + +			bgp_unlock_node(rn); +		} +	} -      vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); -      json_object_free(json); -    } -  else -    { -      if (!display) -        { -          vty_out (vty, "%% Network not in table%s", VTY_NEWLINE); -          return CMD_WARNING; -        } -    } +	if (use_json) { +		if (display) +			json_object_object_add(json, "paths", json_paths); + +		vty_out(vty, "%s%s", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY), +			VTY_NEWLINE); +		json_object_free(json); +	} else { +		if (!display) { +			vty_out(vty, "%% Network not in table%s", VTY_NEWLINE); +			return CMD_WARNING; +		} +	} -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  /* Display specified route of Main RIB */ -static int -bgp_show_route (struct vty *vty, struct bgp *bgp, const char *ip_str, -		afi_t afi, safi_t safi, struct prefix_rd *prd, -		int prefix_check, enum bgp_path_type pathtype, -                u_char use_json) -{ -  if (!bgp) -    bgp = bgp_get_default (); - -  return bgp_show_route_in_table (vty, bgp, bgp->rib[afi][safi], ip_str,  -                                  afi, safi, prd, prefix_check, pathtype, -                                  use_json); -} - -static int -bgp_show_lcommunity (struct vty *vty, struct bgp *bgp, int argc, -                     struct cmd_token **argv, afi_t afi, safi_t safi, u_char uj) -{ -  struct lcommunity *lcom; -  struct buffer *b; -  int i; -  char *str; -  int first = 0; - -  b = buffer_new (1024); -  for (i = 0; i < argc; i++) -    { -      if (first) -        buffer_putc (b, ' '); -      else -        { -          if (strmatch (argv[i]->text, "AA:BB:CC")) -            { -              first = 1; -              buffer_putstr (b, argv[i]->arg); -            } -        } -    } -  buffer_putc (b, '\0'); +static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str, +			  afi_t afi, safi_t safi, struct prefix_rd *prd, +			  int prefix_check, enum bgp_path_type pathtype, +			  u_char use_json) +{ +	if (!bgp) +		bgp = bgp_get_default(); + +	return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str, +				       afi, safi, prd, prefix_check, pathtype, +				       use_json); +} + +static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc, +			       struct cmd_token **argv, afi_t afi, safi_t safi, +			       u_char uj) +{ +	struct lcommunity *lcom; +	struct buffer *b; +	int i; +	char *str; +	int first = 0; + +	b = buffer_new(1024); +	for (i = 0; i < argc; i++) { +		if (first) +			buffer_putc(b, ' '); +		else { +			if (strmatch(argv[i]->text, "AA:BB:CC")) { +				first = 1; +				buffer_putstr(b, argv[i]->arg); +			} +		} +	} +	buffer_putc(b, '\0'); -  str = buffer_getstr (b); -  buffer_free (b); +	str = buffer_getstr(b); +	buffer_free(b); -  lcom = lcommunity_str2com (str); -  XFREE (MTYPE_TMP, str); -  if (! lcom) -    { -      vty_out (vty, "%% Large-community malformed%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +	lcom = lcommunity_str2com(str); +	XFREE(MTYPE_TMP, str); +	if (!lcom) { +		vty_out(vty, "%% Large-community malformed%s", VTY_NEWLINE); +		return CMD_WARNING; +	} -  return bgp_show (vty, bgp, afi, safi, bgp_show_type_lcommunity, lcom, uj); +	return bgp_show(vty, bgp, afi, safi, bgp_show_type_lcommunity, lcom, +			uj);  } -static int -bgp_show_lcommunity_list (struct vty *vty, struct bgp *bgp, const char *lcom, -                          afi_t afi, safi_t safi, u_char uj) +static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp, +				    const char *lcom, afi_t afi, safi_t safi, +				    u_char uj)  { -  struct community_list *list; +	struct community_list *list; -  list = community_list_lookup (bgp_clist, lcom, LARGE_COMMUNITY_LIST_MASTER); -  if (list == NULL) -    { -      vty_out (vty, "%% %s is not a valid large-community-list name%s", lcom, -               VTY_NEWLINE); -      return CMD_WARNING; -    } +	list = community_list_lookup(bgp_clist, lcom, +				     LARGE_COMMUNITY_LIST_MASTER); +	if (list == NULL) { +		vty_out(vty, "%% %s is not a valid large-community-list name%s", +			lcom, VTY_NEWLINE); +		return CMD_WARNING; +	} -  return bgp_show (vty, bgp, afi, safi, bgp_show_type_lcommunity_list, list, uj); +	return bgp_show(vty, bgp, afi, safi, bgp_show_type_lcommunity_list, +			list, uj);  }  DEFUN (show_ip_bgp_large_community_list, @@ -8222,33 +8338,35 @@ DEFUN (show_ip_bgp_large_community_list,         "large-community-list name\n"         JSON_STR)  { -  char *vrf = NULL; -  afi_t afi = AFI_IP6; -  safi_t safi = SAFI_UNICAST; -  int idx = 0; - -  if (argv_find (argv, argc, "ip", &idx)) -    afi = AFI_IP; -  if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx)) -    vrf = argv[++idx]->arg; -  if (argv_find (argv, argc, "ipv4", &idx) || argv_find (argv, argc, "ipv6", &idx)) -  { -    afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP; -    if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx)) -      safi = bgp_vty_safi_from_arg (argv[idx]->text); -  } - -  int uj = use_json (argc, argv); - -    struct bgp *bgp = bgp_lookup_by_name (vrf); -  if (bgp == NULL) -   { -     vty_out (vty, "Can't find BGP instance %s%s", vrf, VTY_NEWLINE); -     return CMD_WARNING; -   } - -  argv_find (argv, argc, "large-community-list", &idx); -  return bgp_show_lcommunity_list (vty, bgp, argv[idx+1]->arg, afi, safi, uj); +	char *vrf = NULL; +	afi_t afi = AFI_IP6; +	safi_t safi = SAFI_UNICAST; +	int idx = 0; + +	if (argv_find(argv, argc, "ip", &idx)) +		afi = AFI_IP; +	if (argv_find(argv, argc, "view", &idx) +	    || argv_find(argv, argc, "vrf", &idx)) +		vrf = argv[++idx]->arg; +	if (argv_find(argv, argc, "ipv4", &idx) +	    || argv_find(argv, argc, "ipv6", &idx)) { +		afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP; +		if (argv_find(argv, argc, "unicast", &idx) +		    || argv_find(argv, argc, "multicast", &idx)) +			safi = bgp_vty_safi_from_arg(argv[idx]->text); +	} + +	int uj = use_json(argc, argv); + +	struct bgp *bgp = bgp_lookup_by_name(vrf); +	if (bgp == NULL) { +		vty_out(vty, "Can't find BGP instance %s%s", vrf, VTY_NEWLINE); +		return CMD_WARNING; +	} + +	argv_find(argv, argc, "large-community-list", &idx); +	return bgp_show_lcommunity_list(vty, bgp, argv[idx + 1]->arg, afi, safi, +					uj);  }  DEFUN (show_ip_bgp_large_community,         show_ip_bgp_large_community_cmd, @@ -8266,38 +8384,41 @@ DEFUN (show_ip_bgp_large_community,         "List of large-community numbers\n"         JSON_STR)  { -  char *vrf = NULL; -  afi_t afi = AFI_IP6; -  safi_t safi = SAFI_UNICAST; -  int idx = 0; - -  if (argv_find (argv, argc, "ip", &idx)) -    afi = AFI_IP; -  if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx)) -    vrf = argv[++idx]->arg; -  if (argv_find (argv, argc, "ipv4", &idx) || argv_find (argv, argc, "ipv6", &idx)) -  { -    afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP; -    if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx)) -      safi = bgp_vty_safi_from_arg (argv[idx]->text); -  } - -  int uj = use_json (argc, argv); - -  struct bgp *bgp = bgp_lookup_by_name (vrf); -  if (bgp == NULL) -   { -     vty_out (vty, "Can't find BGP instance %s%s", vrf, VTY_NEWLINE); -     return CMD_WARNING; -   } - -  if (argv_find (argv, argc, "AA:BB:CC", &idx)) -    return bgp_show_lcommunity (vty, bgp, argc, argv, afi, safi, uj); -  else -    return bgp_show (vty, bgp, afi, safi, bgp_show_type_lcommunity_all, NULL, uj); +	char *vrf = NULL; +	afi_t afi = AFI_IP6; +	safi_t safi = SAFI_UNICAST; +	int idx = 0; + +	if (argv_find(argv, argc, "ip", &idx)) +		afi = AFI_IP; +	if (argv_find(argv, argc, "view", &idx) +	    || argv_find(argv, argc, "vrf", &idx)) +		vrf = argv[++idx]->arg; +	if (argv_find(argv, argc, "ipv4", &idx) +	    || argv_find(argv, argc, "ipv6", &idx)) { +		afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP; +		if (argv_find(argv, argc, "unicast", &idx) +		    || argv_find(argv, argc, "multicast", &idx)) +			safi = bgp_vty_safi_from_arg(argv[idx]->text); +	} + +	int uj = use_json(argc, argv); + +	struct bgp *bgp = bgp_lookup_by_name(vrf); +	if (bgp == NULL) { +		vty_out(vty, "Can't find BGP instance %s%s", vrf, VTY_NEWLINE); +		return CMD_WARNING; +	} + +	if (argv_find(argv, argc, "AA:BB:CC", &idx)) +		return bgp_show_lcommunity(vty, bgp, argc, argv, afi, safi, uj); +	else +		return bgp_show(vty, bgp, afi, safi, +				bgp_show_type_lcommunity_all, NULL, uj);  } -static int bgp_table_stats (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi); +static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi, +			   safi_t safi);  /* BGP route print out function. */  DEFUN (show_ip_bgp, @@ -8349,76 +8470,88 @@ DEFUN (show_ip_bgp,         "Display route and more specific routes\n"         JSON_STR)  { -  afi_t afi = AFI_IP6; -  safi_t safi = SAFI_UNICAST; -  int exact_match = 0; -  enum bgp_show_type sh_type = bgp_show_type_normal; -  struct bgp *bgp = NULL; -  int idx = 0; - -  bgp_vty_find_and_parse_afi_safi_bgp (vty, argv, argc, &idx, &afi, &safi, &bgp); -  if (!idx) -    return CMD_WARNING; - -  int uj = use_json (argc, argv); -  if (uj) argc--; - -  if (argv_find(argv, argc, "cidr-only", &idx)) -    return bgp_show (vty, bgp, afi, safi, bgp_show_type_cidr_only, NULL, uj); - -  if (argv_find(argv, argc, "dampening", &idx)) -    { -      if (argv_find (argv, argc, "dampened-paths", &idx)) -        return bgp_show (vty, bgp, afi, safi, bgp_show_type_dampend_paths, NULL, uj); -      else if (argv_find (argv, argc, "flap-statistics", &idx)) -        return bgp_show (vty, bgp, afi, safi, bgp_show_type_flap_statistics, NULL, uj); -      else if (argv_find (argv, argc, "parameters", &idx)) -        return bgp_show_dampening_parameters (vty, afi, safi); -    } - -  if (argv_find(argv, argc, "prefix-list", &idx)) -    return bgp_show_prefix_list (vty, bgp, argv[idx + 1]->arg, afi, safi, bgp_show_type_prefix_list); - -  if (argv_find(argv, argc, "filter-list", &idx)) -    return bgp_show_filter_list (vty, bgp, argv[idx + 1]->arg, afi, safi, bgp_show_type_filter_list); - -  if (argv_find(argv, argc, "statistics", &idx)) -    return bgp_table_stats (vty, bgp, afi, safi); - -  if (argv_find(argv, argc, "route-map", &idx)) -    return bgp_show_route_map (vty, bgp, argv[idx + 1]->arg, afi, safi, bgp_show_type_route_map); - -  if (argv_find(argv, argc, "community", &idx)) -    { -      /* show a specific community */ -      if (argv_find (argv, argc, "local-AS", &idx) || -          argv_find (argv, argc, "no-advertise", &idx) || -          argv_find (argv, argc, "no-export", &idx)) -        { -          if (argv_find (argv, argc, "exact_match", &idx)) -            exact_match = 1; -          return bgp_show_community (vty, bgp, argc, argv, exact_match, afi, safi); -        } -      /* show all communities */ -      else -        return bgp_show (vty, bgp, afi, safi, bgp_show_type_community_all, NULL, uj); -    } +	afi_t afi = AFI_IP6; +	safi_t safi = SAFI_UNICAST; +	int exact_match = 0; +	enum bgp_show_type sh_type = bgp_show_type_normal; +	struct bgp *bgp = NULL; +	int idx = 0; + +	bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, +					    &bgp); +	if (!idx) +		return CMD_WARNING; + +	int uj = use_json(argc, argv); +	if (uj) +		argc--; + +	if (argv_find(argv, argc, "cidr-only", &idx)) +		return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only, +				NULL, uj); + +	if (argv_find(argv, argc, "dampening", &idx)) { +		if (argv_find(argv, argc, "dampened-paths", &idx)) +			return bgp_show(vty, bgp, afi, safi, +					bgp_show_type_dampend_paths, NULL, uj); +		else if (argv_find(argv, argc, "flap-statistics", &idx)) +			return bgp_show(vty, bgp, afi, safi, +					bgp_show_type_flap_statistics, NULL, +					uj); +		else if (argv_find(argv, argc, "parameters", &idx)) +			return bgp_show_dampening_parameters(vty, afi, safi); +	} -  if (argv_find(argv, argc, "community-list", &idx)) -    { -      const char *clist_number_or_name = argv[++idx]->arg; -      if (++idx < argc && strmatch (argv[idx]->text, "exact-match")) -        exact_match = 1; -      return bgp_show_community_list (vty, bgp, clist_number_or_name, exact_match, afi, safi); -    } -  /* prefix-longer */ -  if (argv_find(argv, argc, "A.B.C.D/M", &idx) || argv_find(argv, argc, "X:X::X:X/M", &idx)) -    return bgp_show_prefix_longer (vty, bgp, argv[idx]->arg, afi, safi, bgp_show_type_prefix_longer); +	if (argv_find(argv, argc, "prefix-list", &idx)) +		return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi, +					    safi, bgp_show_type_prefix_list); + +	if (argv_find(argv, argc, "filter-list", &idx)) +		return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi, +					    safi, bgp_show_type_filter_list); + +	if (argv_find(argv, argc, "statistics", &idx)) +		return bgp_table_stats(vty, bgp, afi, safi); + +	if (argv_find(argv, argc, "route-map", &idx)) +		return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi, +					  safi, bgp_show_type_route_map); + +	if (argv_find(argv, argc, "community", &idx)) { +		/* show a specific community */ +		if (argv_find(argv, argc, "local-AS", &idx) +		    || argv_find(argv, argc, "no-advertise", &idx) +		    || argv_find(argv, argc, "no-export", &idx)) { +			if (argv_find(argv, argc, "exact_match", &idx)) +				exact_match = 1; +			return bgp_show_community(vty, bgp, argc, argv, +						  exact_match, afi, safi); +		} +		/* show all communities */ +		else +			return bgp_show(vty, bgp, afi, safi, +					bgp_show_type_community_all, NULL, uj); +	} -  if (safi == SAFI_MPLS_VPN) -    return bgp_show_mpls_vpn (vty, afi, NULL, bgp_show_type_normal, NULL, 0, uj); -  else -    return bgp_show (vty, bgp, afi, safi, sh_type, NULL, uj); +	if (argv_find(argv, argc, "community-list", &idx)) { +		const char *clist_number_or_name = argv[++idx]->arg; +		if (++idx < argc && strmatch(argv[idx]->text, "exact-match")) +			exact_match = 1; +		return bgp_show_community_list(vty, bgp, clist_number_or_name, +					       exact_match, afi, safi); +	} +	/* prefix-longer */ +	if (argv_find(argv, argc, "A.B.C.D/M", &idx) +	    || argv_find(argv, argc, "X:X::X:X/M", &idx)) +		return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi, +					      safi, +					      bgp_show_type_prefix_longer); + +	if (safi == SAFI_MPLS_VPN) +		return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal, +					 NULL, 0, uj); +	else +		return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj);  }  DEFUN (show_ip_bgp_route, @@ -8439,55 +8572,64 @@ DEFUN (show_ip_bgp_route,         "Display only multipaths\n"         JSON_STR)  { -  int prefix_check = 0; +	int prefix_check = 0; -  afi_t afi = AFI_IP6; -  safi_t safi = SAFI_UNICAST; -  char *prefix = NULL; -  struct bgp *bgp = NULL; -  enum bgp_path_type path_type; -  u_char uj = use_json(argc, argv); +	afi_t afi = AFI_IP6; +	safi_t safi = SAFI_UNICAST; +	char *prefix = NULL; +	struct bgp *bgp = NULL; +	enum bgp_path_type path_type; +	u_char uj = use_json(argc, argv); -  int idx = 0; +	int idx = 0; -  bgp_vty_find_and_parse_afi_safi_bgp (vty, argv, argc, &idx, &afi, &safi, &bgp); -  if (!idx) -    return CMD_WARNING; +	bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, +					    &bgp); +	if (!idx) +		return CMD_WARNING; -  if (!bgp) -    { -      vty_out (vty, "Specified 'all' vrf's but this command currently only works per view/vrf%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +	if (!bgp) { +		vty_out(vty, +			"Specified 'all' vrf's but this command currently only works per view/vrf%s", +			VTY_NEWLINE); +		return CMD_WARNING; +	} -  /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */ -  if (argv_find (argv, argc, "A.B.C.D", &idx) || argv_find (argv, argc, "X:X::X:X", &idx)) -    prefix_check = 0; -  else if (argv_find (argv, argc, "A.B.C.D/M", &idx) || argv_find (argv, argc, "X:X::X:X/M", &idx)) -    prefix_check = 1; - -  if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN) && afi != AFI_IP6) -  { -    vty_out (vty, "%% Cannot specify IPv6 address or prefix with IPv4 AFI%s", VTY_NEWLINE); -    return CMD_WARNING; -  } -  if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN) && afi != AFI_IP) -  { -    vty_out (vty, "%% Cannot specify IPv4 address or prefix with IPv6 AFI%s", VTY_NEWLINE); -    return CMD_WARNING; -  } - -  prefix = argv[idx]->arg; - -  /* [<bestpath|multipath>] */ -  if (argv_find (argv, argc, "bestpath", &idx)) -    path_type = BGP_PATH_BESTPATH; -  else if (argv_find (argv, argc, "multipath", &idx)) -    path_type = BGP_PATH_MULTIPATH; -  else -    path_type = BGP_PATH_ALL; +	/* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */ +	if (argv_find(argv, argc, "A.B.C.D", &idx) +	    || argv_find(argv, argc, "X:X::X:X", &idx)) +		prefix_check = 0; +	else if (argv_find(argv, argc, "A.B.C.D/M", &idx) +		 || argv_find(argv, argc, "X:X::X:X/M", &idx)) +		prefix_check = 1; + +	if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN) +	    && afi != AFI_IP6) { +		vty_out(vty, +			"%% Cannot specify IPv6 address or prefix with IPv4 AFI%s", +			VTY_NEWLINE); +		return CMD_WARNING; +	} +	if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN) +	    && afi != AFI_IP) { +		vty_out(vty, +			"%% Cannot specify IPv4 address or prefix with IPv6 AFI%s", +			VTY_NEWLINE); +		return CMD_WARNING; +	} + +	prefix = argv[idx]->arg; -  return bgp_show_route (vty, bgp, prefix, afi, safi, NULL, prefix_check, path_type, uj); +	/* [<bestpath|multipath>] */ +	if (argv_find(argv, argc, "bestpath", &idx)) +		path_type = BGP_PATH_BESTPATH; +	else if (argv_find(argv, argc, "multipath", &idx)) +		path_type = BGP_PATH_MULTIPATH; +	else +		path_type = BGP_PATH_ALL; + +	return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check, +			      path_type, uj);  }  DEFUN (show_ip_bgp_regexp, @@ -8502,23 +8644,25 @@ DEFUN (show_ip_bgp_regexp,         "Display routes matching the AS path regular expression\n"         "A regular-expression to match the BGP AS paths\n")  { -  afi_t afi = AFI_IP6; -  safi_t safi = SAFI_UNICAST; -  struct bgp *bgp = NULL; +	afi_t afi = AFI_IP6; +	safi_t safi = SAFI_UNICAST; +	struct bgp *bgp = NULL; -  int idx = 0; -  bgp_vty_find_and_parse_afi_safi_bgp (vty, argv, argc, &idx, &afi, &safi, &bgp); -  if (!idx) -    return CMD_WARNING; +	int idx = 0; +	bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, +					    &bgp); +	if (!idx) +		return CMD_WARNING; -  // get index of regex -  argv_find (argv, argc, "regexp", &idx); -  idx++; +	// get index of regex +	argv_find(argv, argc, "regexp", &idx); +	idx++; -  char *regstr = argv_concat (argv, argc, idx); -  int rc = bgp_show_regexp (vty, (const char *) regstr, afi, safi, bgp_show_type_regexp); -  XFREE (MTYPE_TMP, regstr); -  return rc; +	char *regstr = argv_concat(argv, argc, idx); +	int rc = bgp_show_regexp(vty, (const char *)regstr, afi, safi, +				 bgp_show_type_regexp); +	XFREE(MTYPE_TMP, regstr); +	return rc;  }  DEFUN (show_ip_bgp_instance_all, @@ -8532,274 +8676,265 @@ DEFUN (show_ip_bgp_instance_all,         BGP_SAFI_HELP_STR         JSON_STR)  { -  afi_t afi = AFI_IP; -  safi_t safi = SAFI_UNICAST; -  struct bgp *bgp = NULL; +	afi_t afi = AFI_IP; +	safi_t safi = SAFI_UNICAST; +	struct bgp *bgp = NULL; -  int idx = 0; -  bgp_vty_find_and_parse_afi_safi_bgp (vty, argv, argc, &idx, &afi, &safi, &bgp); -  if (!idx) -    return CMD_WARNING; +	int idx = 0; +	bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, +					    &bgp); +	if (!idx) +		return CMD_WARNING; -  int uj = use_json (argc, argv); -  if (uj) argc--; +	int uj = use_json(argc, argv); +	if (uj) +		argc--; -  bgp_show_all_instances_routes_vty (vty, afi, safi, uj); -  return CMD_SUCCESS; +	bgp_show_all_instances_routes_vty(vty, afi, safi, uj); +	return CMD_SUCCESS;  } -static int -bgp_show_regexp (struct vty *vty, const char *regstr, afi_t afi, -		 safi_t safi, enum bgp_show_type type) +static int bgp_show_regexp(struct vty *vty, const char *regstr, afi_t afi, +			   safi_t safi, enum bgp_show_type type)  { -  regex_t *regex; -  int rc; -   -  regex = bgp_regcomp (regstr); -  if (! regex) -    { -      vty_out (vty, "Can't compile regexp %s%s", regstr, VTY_NEWLINE); -      return CMD_WARNING; -    } +	regex_t *regex; +	int rc; + +	regex = bgp_regcomp(regstr); +	if (!regex) { +		vty_out(vty, "Can't compile regexp %s%s", regstr, VTY_NEWLINE); +		return CMD_WARNING; +	} -  rc = bgp_show (vty, NULL, afi, safi, type, regex, 0); -  bgp_regex_free (regex); -  return rc; +	rc = bgp_show(vty, NULL, afi, safi, type, regex, 0); +	bgp_regex_free(regex); +	return rc;  } -static int -bgp_show_prefix_list (struct vty *vty, struct bgp *bgp, -                      const char *prefix_list_str, afi_t afi, -		      safi_t safi, enum bgp_show_type type) +static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp, +				const char *prefix_list_str, afi_t afi, +				safi_t safi, enum bgp_show_type type)  { -  struct prefix_list *plist; +	struct prefix_list *plist; -  plist = prefix_list_lookup (afi, prefix_list_str); -  if (plist == NULL) -    { -      vty_out (vty, "%% %s is not a valid prefix-list name%s", -               prefix_list_str, VTY_NEWLINE);	     -      return CMD_WARNING; -    } +	plist = prefix_list_lookup(afi, prefix_list_str); +	if (plist == NULL) { +		vty_out(vty, "%% %s is not a valid prefix-list name%s", +			prefix_list_str, VTY_NEWLINE); +		return CMD_WARNING; +	} -  return bgp_show (vty, bgp, afi, safi, type, plist, 0); +	return bgp_show(vty, bgp, afi, safi, type, plist, 0);  } -static int -bgp_show_filter_list (struct vty *vty, struct bgp *bgp, -                      const char *filter, afi_t afi, -		      safi_t safi, enum bgp_show_type type) +static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp, +				const char *filter, afi_t afi, safi_t safi, +				enum bgp_show_type type)  { -  struct as_list *as_list; +	struct as_list *as_list; -  as_list = as_list_lookup (filter); -  if (as_list == NULL) -    { -      vty_out (vty, "%% %s is not a valid AS-path access-list name%s", filter, VTY_NEWLINE);	     -      return CMD_WARNING; -    } +	as_list = as_list_lookup(filter); +	if (as_list == NULL) { +		vty_out(vty, "%% %s is not a valid AS-path access-list name%s", +			filter, VTY_NEWLINE); +		return CMD_WARNING; +	} -  return bgp_show (vty, bgp, afi, safi, type, as_list, 0); +	return bgp_show(vty, bgp, afi, safi, type, as_list, 0);  } -static int -bgp_show_route_map (struct vty *vty, struct bgp *bgp, -                    const char *rmap_str, afi_t afi, -		    safi_t safi, enum bgp_show_type type) +static int bgp_show_route_map(struct vty *vty, struct bgp *bgp, +			      const char *rmap_str, afi_t afi, safi_t safi, +			      enum bgp_show_type type)  { -  struct route_map *rmap; +	struct route_map *rmap; -  rmap = route_map_lookup_by_name (rmap_str); -  if (! rmap) -    { -      vty_out (vty, "%% %s is not a valid route-map name%s", -	       rmap_str, VTY_NEWLINE);	     -      return CMD_WARNING; -    } +	rmap = route_map_lookup_by_name(rmap_str); +	if (!rmap) { +		vty_out(vty, "%% %s is not a valid route-map name%s", rmap_str, +			VTY_NEWLINE); +		return CMD_WARNING; +	} -  return bgp_show (vty, bgp, afi, safi, type, rmap, 0); +	return bgp_show(vty, bgp, afi, safi, type, rmap, 0);  } -static int -bgp_show_community (struct vty *vty, struct bgp *bgp, int argc, -		    struct cmd_token **argv, int exact, afi_t afi, safi_t safi) +static int bgp_show_community(struct vty *vty, struct bgp *bgp, int argc, +			      struct cmd_token **argv, int exact, afi_t afi, +			      safi_t safi)  { -  struct community *com; -  struct buffer *b; -  int i; -  char *str; -  int first = 0; +	struct community *com; +	struct buffer *b; +	int i; +	char *str; +	int first = 0; -  b = buffer_new (1024); -  for (i = 0; i < argc; i++) -    { -      if (first) -        buffer_putc (b, ' '); -      else -	{ -	  if ((strcmp (argv[i]->arg, "unicast") == 0) || (strcmp (argv[i]->arg, "multicast") == 0)) -	    continue; -	  first = 1; -	} -       -      buffer_putstr (b, argv[i]->arg); -    } -  buffer_putc (b, '\0'); +	b = buffer_new(1024); +	for (i = 0; i < argc; i++) { +		if (first) +			buffer_putc(b, ' '); +		else { +			if ((strcmp(argv[i]->arg, "unicast") == 0) +			    || (strcmp(argv[i]->arg, "multicast") == 0)) +				continue; +			first = 1; +		} -  str = buffer_getstr (b); -  buffer_free (b); +		buffer_putstr(b, argv[i]->arg); +	} +	buffer_putc(b, '\0'); -  com = community_str2com (str); -  XFREE (MTYPE_TMP, str); -  if (! com) -    { -      vty_out (vty, "%% Community malformed: %s", VTY_NEWLINE); -      return CMD_WARNING; -    } +	str = buffer_getstr(b); +	buffer_free(b); -  return bgp_show (vty, bgp, afi, safi, -                   (exact ? bgp_show_type_community_exact : -		    bgp_show_type_community), com, 0); +	com = community_str2com(str); +	XFREE(MTYPE_TMP, str); +	if (!com) { +		vty_out(vty, "%% Community malformed: %s", VTY_NEWLINE); +		return CMD_WARNING; +	} + +	return bgp_show(vty, bgp, afi, safi, +			(exact ? bgp_show_type_community_exact +			       : bgp_show_type_community), +			com, 0);  } -static int -bgp_show_community_list (struct vty *vty, struct bgp *bgp, -                         const char *com, int exact, -			 afi_t afi, safi_t safi) +static int bgp_show_community_list(struct vty *vty, struct bgp *bgp, +				   const char *com, int exact, afi_t afi, +				   safi_t safi)  { -  struct community_list *list; +	struct community_list *list; -  list = community_list_lookup (bgp_clist, com, COMMUNITY_LIST_MASTER); -  if (list == NULL) -    { -      vty_out (vty, "%% %s is not a valid community-list name%s", com, -	       VTY_NEWLINE); -      return CMD_WARNING; -    } +	list = community_list_lookup(bgp_clist, com, COMMUNITY_LIST_MASTER); +	if (list == NULL) { +		vty_out(vty, "%% %s is not a valid community-list name%s", com, +			VTY_NEWLINE); +		return CMD_WARNING; +	} -  return bgp_show (vty, bgp, afi, safi, -                   (exact ? bgp_show_type_community_list_exact : -		    bgp_show_type_community_list), list, 0); +	return bgp_show(vty, bgp, afi, safi, +			(exact ? bgp_show_type_community_list_exact +			       : bgp_show_type_community_list), +			list, 0);  } -static int -bgp_show_prefix_longer (struct vty *vty, struct bgp *bgp, -                        const char *prefix, afi_t afi, -			safi_t safi, enum bgp_show_type type) +static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp, +				  const char *prefix, afi_t afi, safi_t safi, +				  enum bgp_show_type type)  { -  int ret; -  struct prefix *p; +	int ret; +	struct prefix *p; -  p = prefix_new(); +	p = prefix_new(); -  ret = str2prefix (prefix, p); -  if (! ret) -    { -      vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE); -      return CMD_WARNING; -    } - -  ret = bgp_show (vty, bgp, afi, safi, type, p, 0); -  prefix_free(p); -  return ret; -} +	ret = str2prefix(prefix, p); +	if (!ret) { +		vty_out(vty, "%% Malformed Prefix%s", VTY_NEWLINE); +		return CMD_WARNING; +	} -static struct peer * -peer_lookup_in_view (struct vty *vty, struct bgp *bgp, -                     const char *ip_str, u_char use_json) -{ -  int ret; -  struct peer *peer; -  union sockunion su; +	ret = bgp_show(vty, bgp, afi, safi, type, p, 0); +	prefix_free(p); +	return ret; +} + +static struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp, +					const char *ip_str, u_char use_json) +{ +	int ret; +	struct peer *peer; +	union sockunion su; + +	/* Get peer sockunion. */ +	ret = str2sockunion(ip_str, &su); +	if (ret < 0) { +		peer = peer_lookup_by_conf_if(bgp, ip_str); +		if (!peer) { +			peer = peer_lookup_by_hostname(bgp, ip_str); + +			if (!peer) { +				if (use_json) { +					json_object *json_no = NULL; +					json_no = json_object_new_object(); +					json_object_string_add( +						json_no, +						"malformedAddressOrName", +						ip_str); +					vty_out(vty, "%s%s", +						json_object_to_json_string( +							json_no), +						VTY_NEWLINE); +					json_object_free(json_no); +				} else +					vty_out(vty, +						"%% Malformed address or name: %s%s", +						ip_str, VTY_NEWLINE); +				return NULL; +			} +		} +		return peer; +	} -  /* Get peer sockunion. */   -  ret = str2sockunion (ip_str, &su); -  if (ret < 0) -    { -      peer = peer_lookup_by_conf_if (bgp, ip_str); -      if (!peer) -        { -          peer = peer_lookup_by_hostname(bgp, ip_str); - -          if (!peer) -            { -              if (use_json) -                { -                  json_object *json_no = NULL; -                  json_no = json_object_new_object(); -                  json_object_string_add(json_no, "malformedAddressOrName", ip_str); -                  vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE); -                  json_object_free(json_no); -                } -              else -                vty_out (vty, "%% Malformed address or name: %s%s", ip_str, VTY_NEWLINE); -              return NULL; -            } -        } -      return peer; -    } +	/* Peer structure lookup. */ +	peer = peer_lookup(bgp, &su); +	if (!peer) { +		if (use_json) { +			json_object *json_no = NULL; +			json_no = json_object_new_object(); +			json_object_string_add(json_no, "warning", +					       "No such neighbor"); +			vty_out(vty, "%s%s", +				json_object_to_json_string(json_no), +				VTY_NEWLINE); +			json_object_free(json_no); +		} else +			vty_out(vty, "No such neighbor%s", VTY_NEWLINE); +		return NULL; +	} -  /* Peer structure lookup. */ -  peer = peer_lookup (bgp, &su); -  if (! peer) -    { -      if (use_json) -        { -          json_object *json_no = NULL; -          json_no = json_object_new_object(); -          json_object_string_add(json_no, "warning","No such neighbor"); -          vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE); -          json_object_free(json_no); -        } -      else -        vty_out (vty, "No such neighbor%s", VTY_NEWLINE); -      return NULL; -    } -   -  return peer; -} - -enum bgp_stats -{ -  BGP_STATS_MAXBITLEN = 0, -  BGP_STATS_RIB, -  BGP_STATS_PREFIXES, -  BGP_STATS_TOTPLEN, -  BGP_STATS_UNAGGREGATEABLE, -  BGP_STATS_MAX_AGGREGATEABLE, -  BGP_STATS_AGGREGATES, -  BGP_STATS_SPACE, -  BGP_STATS_ASPATH_COUNT, -  BGP_STATS_ASPATH_MAXHOPS, -  BGP_STATS_ASPATH_TOTHOPS, -  BGP_STATS_ASPATH_MAXSIZE, -  BGP_STATS_ASPATH_TOTSIZE, -  BGP_STATS_ASN_HIGHEST, -  BGP_STATS_MAX, +	return peer; +} + +enum bgp_stats { +	BGP_STATS_MAXBITLEN = 0, +	BGP_STATS_RIB, +	BGP_STATS_PREFIXES, +	BGP_STATS_TOTPLEN, +	BGP_STATS_UNAGGREGATEABLE, +	BGP_STATS_MAX_AGGREGATEABLE, +	BGP_STATS_AGGREGATES, +	BGP_STATS_SPACE, +	BGP_STATS_ASPATH_COUNT, +	BGP_STATS_ASPATH_MAXHOPS, +	BGP_STATS_ASPATH_TOTHOPS, +	BGP_STATS_ASPATH_MAXSIZE, +	BGP_STATS_ASPATH_TOTSIZE, +	BGP_STATS_ASN_HIGHEST, +	BGP_STATS_MAX,  }; -static const char *table_stats_strs[] = -{ -  [BGP_STATS_PREFIXES]            = "Total Prefixes", -  [BGP_STATS_TOTPLEN]             = "Average prefix length", -  [BGP_STATS_RIB]                 = "Total Advertisements", -  [BGP_STATS_UNAGGREGATEABLE]     = "Unaggregateable prefixes", -  [BGP_STATS_MAX_AGGREGATEABLE]   = "Maximum aggregateable prefixes", -  [BGP_STATS_AGGREGATES]          = "BGP Aggregate advertisements", -  [BGP_STATS_SPACE]               = "Address space advertised", -  [BGP_STATS_ASPATH_COUNT]        = "Advertisements with paths", -  [BGP_STATS_ASPATH_MAXHOPS]      = "Longest AS-Path (hops)", -  [BGP_STATS_ASPATH_MAXSIZE]      = "Largest AS-Path (bytes)", -  [BGP_STATS_ASPATH_TOTHOPS]      = "Average AS-Path length (hops)", -  [BGP_STATS_ASPATH_TOTSIZE]      = "Average AS-Path size (bytes)", -  [BGP_STATS_ASN_HIGHEST]         = "Highest public ASN", -  [BGP_STATS_MAX] = NULL, +static const char *table_stats_strs[] = { +		[BGP_STATS_PREFIXES] = "Total Prefixes", +		[BGP_STATS_TOTPLEN] = "Average prefix length", +		[BGP_STATS_RIB] = "Total Advertisements", +		[BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes", +		[BGP_STATS_MAX_AGGREGATEABLE] = +			"Maximum aggregateable prefixes", +		[BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements", +		[BGP_STATS_SPACE] = "Address space advertised", +		[BGP_STATS_ASPATH_COUNT] = "Advertisements with paths", +		[BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)", +		[BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)", +		[BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)", +		[BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)", +		[BGP_STATS_ASN_HIGHEST] = "Highest public ASN", +		[BGP_STATS_MAX] = NULL,  }; -struct bgp_table_stats -{ -  struct bgp_table *table; -  unsigned long long counts[BGP_STATS_MAX]; +struct bgp_table_stats { +	struct bgp_table *table; +	unsigned long long counts[BGP_STATS_MAX];  };  #if 0 @@ -8818,43 +8953,40 @@ ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)  }  #endif -static int -bgp_table_stats_walker (struct thread *t) +static int bgp_table_stats_walker(struct thread *t)  { -  struct bgp_node *rn; -  struct bgp_node *top; -  struct bgp_table_stats *ts = THREAD_ARG (t); -  unsigned int space = 0; -   -  if (!(top = bgp_table_top (ts->table))) -    return 0; +	struct bgp_node *rn; +	struct bgp_node *top; +	struct bgp_table_stats *ts = THREAD_ARG(t); +	unsigned int space = 0; -  switch (top->p.family) -    { -      case AF_INET: -        space = IPV4_MAX_BITLEN; -        break; -      case AF_INET6: -        space = IPV6_MAX_BITLEN; -        break; -    } -     -  ts->counts[BGP_STATS_MAXBITLEN] = space; +	if (!(top = bgp_table_top(ts->table))) +		return 0; -  for (rn = top; rn; rn = bgp_route_next (rn)) -    { -      struct bgp_info *ri; -      struct bgp_node *prn = bgp_node_parent_nolock (rn); -      unsigned int rinum = 0; -       -      if (rn == top) -        continue; -       -      if (!rn->info) -        continue; -       -      ts->counts[BGP_STATS_PREFIXES]++; -      ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen; +	switch (top->p.family) { +	case AF_INET: +		space = IPV4_MAX_BITLEN; +		break; +	case AF_INET6: +		space = IPV6_MAX_BITLEN; +		break; +	} + +	ts->counts[BGP_STATS_MAXBITLEN] = space; + +	for (rn = top; rn; rn = bgp_route_next(rn)) { +		struct bgp_info *ri; +		struct bgp_node *prn = bgp_node_parent_nolock(rn); +		unsigned int rinum = 0; + +		if (rn == top) +			continue; + +		if (!rn->info) +			continue; + +		ts->counts[BGP_STATS_PREFIXES]++; +		ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;  #if 0        ts->counts[BGP_STATS_AVGPLEN] @@ -8862,48 +8994,50 @@ bgp_table_stats_walker (struct thread *t)                        ts->counts[BGP_STATS_AVGPLEN],                        rn->p.prefixlen);  #endif -       -      /* check if the prefix is included by any other announcements */ -      while (prn && !prn->info) -        prn = bgp_node_parent_nolock (prn); -       -      if (prn == NULL || prn == top) -        { -          ts->counts[BGP_STATS_UNAGGREGATEABLE]++; -          /* announced address space */ -          if (space) -            ts->counts[BGP_STATS_SPACE] += 1 << (space - rn->p.prefixlen); -        } -      else if (prn->info) -        ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++; -       -      for (ri = rn->info; ri; ri = ri->next) -        { -          rinum++; -          ts->counts[BGP_STATS_RIB]++; -           -          if (ri->attr && -              (CHECK_FLAG (ri->attr->flag, -                           ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE)))) -            ts->counts[BGP_STATS_AGGREGATES]++; -           -          /* as-path stats */ -          if (ri->attr && ri->attr->aspath) -            { -              unsigned int hops = aspath_count_hops (ri->attr->aspath); -              unsigned int size = aspath_size (ri->attr->aspath); -              as_t highest = aspath_highest (ri->attr->aspath); -               -              ts->counts[BGP_STATS_ASPATH_COUNT]++; -               -              if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS]) -                ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops; -               -              if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE]) -                ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size; -               -              ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops; -              ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size; + +		/* check if the prefix is included by any other announcements */ +		while (prn && !prn->info) +			prn = bgp_node_parent_nolock(prn); + +		if (prn == NULL || prn == top) { +			ts->counts[BGP_STATS_UNAGGREGATEABLE]++; +			/* announced address space */ +			if (space) +				ts->counts[BGP_STATS_SPACE] += +					1 << (space - rn->p.prefixlen); +		} else if (prn->info) +			ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++; + +		for (ri = rn->info; ri; ri = ri->next) { +			rinum++; +			ts->counts[BGP_STATS_RIB]++; + +			if (ri->attr +			    && (CHECK_FLAG(ri->attr->flag, +					   ATTR_FLAG_BIT( +						   BGP_ATTR_ATOMIC_AGGREGATE)))) +				ts->counts[BGP_STATS_AGGREGATES]++; + +			/* as-path stats */ +			if (ri->attr && ri->attr->aspath) { +				unsigned int hops = +					aspath_count_hops(ri->attr->aspath); +				unsigned int size = +					aspath_size(ri->attr->aspath); +				as_t highest = aspath_highest(ri->attr->aspath); + +				ts->counts[BGP_STATS_ASPATH_COUNT]++; + +				if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS]) +					ts->counts[BGP_STATS_ASPATH_MAXHOPS] = +						hops; + +				if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE]) +					ts->counts[BGP_STATS_ASPATH_MAXSIZE] = +						size; + +				ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops; +				ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;  #if 0                ts->counts[BGP_STATS_ASPATH_AVGHOPS]                   = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT], @@ -8914,41 +9048,39 @@ bgp_table_stats_walker (struct thread *t)                                ts->counts[BGP_STATS_ASPATH_AVGSIZE],                                size);  #endif -              if (highest > ts->counts[BGP_STATS_ASN_HIGHEST]) -                ts->counts[BGP_STATS_ASN_HIGHEST] = highest; -            } -        } -    } -  return 0; +				if (highest > ts->counts[BGP_STATS_ASN_HIGHEST]) +					ts->counts[BGP_STATS_ASN_HIGHEST] = +						highest; +			} +		} +	} +	return 0;  } -static int -bgp_table_stats (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi) +static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi, +			   safi_t safi)  { -  struct bgp_table_stats ts; -  unsigned int i; -   -  if (!bgp->rib[afi][safi]) -    { -      vty_out (vty, "%% No RIB exist's for the AFI(%d)/SAFI(%d)%s", -	       afi, safi, VTY_NEWLINE); -      return CMD_WARNING; -    } -   -  memset (&ts, 0, sizeof (ts)); -  ts.table = bgp->rib[afi][safi]; -  thread_execute (bm->master, bgp_table_stats_walker, &ts, 0); +	struct bgp_table_stats ts; +	unsigned int i; -  vty_out (vty, "BGP %s RIB statistics%s%s", -           afi_safi_print (afi, safi), VTY_NEWLINE, VTY_NEWLINE); -   -  for (i = 0; i < BGP_STATS_MAX; i++) -    { -      if (!table_stats_strs[i]) -        continue; -       -      switch (i) -        { +	if (!bgp->rib[afi][safi]) { +		vty_out(vty, "%% No RIB exist's for the AFI(%d)/SAFI(%d)%s", +			afi, safi, VTY_NEWLINE); +		return CMD_WARNING; +	} + +	memset(&ts, 0, sizeof(ts)); +	ts.table = bgp->rib[afi][safi]; +	thread_execute(bm->master, bgp_table_stats_walker, &ts, 0); + +	vty_out(vty, "BGP %s RIB statistics%s%s", afi_safi_print(afi, safi), +		VTY_NEWLINE, VTY_NEWLINE); + +	for (i = 0; i < BGP_STATS_MAX; i++) { +		if (!table_stats_strs[i]) +			continue; + +		switch (i) {  #if 0            case BGP_STATS_ASPATH_AVGHOPS:            case BGP_STATS_ASPATH_AVGSIZE: @@ -8958,244 +9090,250 @@ bgp_table_stats (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi)                       (float)ts.counts[i] / (float)TALLY_SIGFIG);              break;  #endif -          case BGP_STATS_ASPATH_TOTHOPS: -          case BGP_STATS_ASPATH_TOTSIZE: -            vty_out (vty, "%-30s: ", table_stats_strs[i]); -            vty_out (vty, "%12.2f", -                     ts.counts[i] ? -                     (float)ts.counts[i] /  -                      (float)ts.counts[BGP_STATS_ASPATH_COUNT] -                     : 0); -            break; -          case BGP_STATS_TOTPLEN: -            vty_out (vty, "%-30s: ", table_stats_strs[i]); -            vty_out (vty, "%12.2f", -                     ts.counts[i] ? -                     (float)ts.counts[i] /  -                      (float)ts.counts[BGP_STATS_PREFIXES] -                     : 0); -            break; -          case BGP_STATS_SPACE: -            vty_out (vty, "%-30s: ", table_stats_strs[i]); -            vty_out (vty, "%12llu%s", ts.counts[i], VTY_NEWLINE); -            if (ts.counts[BGP_STATS_MAXBITLEN] < 9) -              break; -            vty_out (vty, "%30s: ", "%% announced "); -            vty_out (vty, "%12.2f%s",  -                     100 * (float)ts.counts[BGP_STATS_SPACE] /  -                       (float)((uint64_t)1UL << ts.counts[BGP_STATS_MAXBITLEN]), -                       VTY_NEWLINE); -            vty_out (vty, "%30s: ", "/8 equivalent "); -            vty_out (vty, "%12.2f%s",  -                     (float)ts.counts[BGP_STATS_SPACE] /  -                       (float)(1UL << (ts.counts[BGP_STATS_MAXBITLEN] - 8)), -                     VTY_NEWLINE); -            if (ts.counts[BGP_STATS_MAXBITLEN] < 25) -              break; -            vty_out (vty, "%30s: ", "/24 equivalent "); -            vty_out (vty, "%12.2f",  -                     (float)ts.counts[BGP_STATS_SPACE] /  -                       (float)(1UL << (ts.counts[BGP_STATS_MAXBITLEN] - 24))); -            break; -          default: -            vty_out (vty, "%-30s: ", table_stats_strs[i]); -            vty_out (vty, "%12llu", ts.counts[i]); -        } -         -      vty_out (vty, "%s", VTY_NEWLINE); -    } -  return CMD_SUCCESS; -} +		case BGP_STATS_ASPATH_TOTHOPS: +		case BGP_STATS_ASPATH_TOTSIZE: +			vty_out(vty, "%-30s: ", table_stats_strs[i]); +			vty_out(vty, "%12.2f", +				ts.counts[i] +					? (float)ts.counts[i] +						  / (float)ts.counts +							    [BGP_STATS_ASPATH_COUNT] +					: 0); +			break; +		case BGP_STATS_TOTPLEN: +			vty_out(vty, "%-30s: ", table_stats_strs[i]); +			vty_out(vty, "%12.2f", +				ts.counts[i] +					? (float)ts.counts[i] +						  / (float)ts.counts +							    [BGP_STATS_PREFIXES] +					: 0); +			break; +		case BGP_STATS_SPACE: +			vty_out(vty, "%-30s: ", table_stats_strs[i]); +			vty_out(vty, "%12llu%s", ts.counts[i], VTY_NEWLINE); +			if (ts.counts[BGP_STATS_MAXBITLEN] < 9) +				break; +			vty_out(vty, "%30s: ", "%% announced "); +			vty_out(vty, "%12.2f%s", +				100 * (float)ts.counts[BGP_STATS_SPACE] +					/ (float)((uint64_t)1UL +						  << ts.counts +							     [BGP_STATS_MAXBITLEN]), +				VTY_NEWLINE); +			vty_out(vty, "%30s: ", "/8 equivalent "); +			vty_out(vty, "%12.2f%s", +				(float)ts.counts[BGP_STATS_SPACE] +					/ (float)(1UL +						  << (ts.counts +							      [BGP_STATS_MAXBITLEN] +						      - 8)), +				VTY_NEWLINE); +			if (ts.counts[BGP_STATS_MAXBITLEN] < 25) +				break; +			vty_out(vty, "%30s: ", "/24 equivalent "); +			vty_out(vty, "%12.2f", +				(float)ts.counts[BGP_STATS_SPACE] +					/ (float)(1UL +						  << (ts.counts +							      [BGP_STATS_MAXBITLEN] +						      - 24))); +			break; +		default: +			vty_out(vty, "%-30s: ", table_stats_strs[i]); +			vty_out(vty, "%12llu", ts.counts[i]); +		} -enum bgp_pcounts -{ -  PCOUNT_ADJ_IN = 0, -  PCOUNT_DAMPED, -  PCOUNT_REMOVED, -  PCOUNT_HISTORY, -  PCOUNT_STALE, -  PCOUNT_VALID, -  PCOUNT_ALL, -  PCOUNT_COUNTED, -  PCOUNT_PFCNT, /* the figure we display to users */ -  PCOUNT_MAX, +		vty_out(vty, "%s", VTY_NEWLINE); +	} +	return CMD_SUCCESS; +} + +enum bgp_pcounts { +	PCOUNT_ADJ_IN = 0, +	PCOUNT_DAMPED, +	PCOUNT_REMOVED, +	PCOUNT_HISTORY, +	PCOUNT_STALE, +	PCOUNT_VALID, +	PCOUNT_ALL, +	PCOUNT_COUNTED, +	PCOUNT_PFCNT, /* the figure we display to users */ +	PCOUNT_MAX,  }; -static const char *pcount_strs[] = -{ -  [PCOUNT_ADJ_IN]  = "Adj-in", -  [PCOUNT_DAMPED]  = "Damped", -  [PCOUNT_REMOVED] = "Removed", -  [PCOUNT_HISTORY] = "History", -  [PCOUNT_STALE]   = "Stale", -  [PCOUNT_VALID]   = "Valid", -  [PCOUNT_ALL]     = "All RIB", -  [PCOUNT_COUNTED] = "PfxCt counted", -  [PCOUNT_PFCNT]   = "Useable", -  [PCOUNT_MAX]     = NULL, +static const char *pcount_strs[] = { +		[PCOUNT_ADJ_IN] = "Adj-in", +		[PCOUNT_DAMPED] = "Damped", +		[PCOUNT_REMOVED] = "Removed", +		[PCOUNT_HISTORY] = "History", +		[PCOUNT_STALE] = "Stale", +		[PCOUNT_VALID] = "Valid", +		[PCOUNT_ALL] = "All RIB", +		[PCOUNT_COUNTED] = "PfxCt counted", +		[PCOUNT_PFCNT] = "Useable", +		[PCOUNT_MAX] = NULL,  }; -struct peer_pcounts -{ -  unsigned int count[PCOUNT_MAX]; -  const struct peer *peer; -  const struct bgp_table *table; +struct peer_pcounts { +	unsigned int count[PCOUNT_MAX]; +	const struct peer *peer; +	const struct bgp_table *table;  }; -static int -bgp_peer_count_walker (struct thread *t) -{ -  struct bgp_node *rn; -  struct peer_pcounts *pc = THREAD_ARG (t); -  const struct peer *peer = pc->peer; -   -  for (rn = bgp_table_top (pc->table); rn; rn = bgp_route_next (rn)) -    { -      struct bgp_adj_in *ain; -      struct bgp_info *ri; -       -      for (ain = rn->adj_in; ain; ain = ain->next) -        if (ain->peer == peer) -          pc->count[PCOUNT_ADJ_IN]++; - -      for (ri = rn->info; ri; ri = ri->next) -        { -          char buf[SU_ADDRSTRLEN]; -           -          if (ri->peer != peer) -            continue; -           -          pc->count[PCOUNT_ALL]++; -           -          if (CHECK_FLAG (ri->flags, BGP_INFO_DAMPED)) -            pc->count[PCOUNT_DAMPED]++; -          if (CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) -            pc->count[PCOUNT_HISTORY]++; -          if (CHECK_FLAG (ri->flags, BGP_INFO_REMOVED)) -            pc->count[PCOUNT_REMOVED]++; -          if (CHECK_FLAG (ri->flags, BGP_INFO_STALE)) -            pc->count[PCOUNT_STALE]++; -          if (CHECK_FLAG (ri->flags, BGP_INFO_VALID)) -            pc->count[PCOUNT_VALID]++; -          if (!CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE)) -            pc->count[PCOUNT_PFCNT]++; -           -          if (CHECK_FLAG (ri->flags, BGP_INFO_COUNTED)) -            { -              pc->count[PCOUNT_COUNTED]++; -              if (CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE)) -                zlog_warn ("%s [pcount] %s/%d is counted but flags 0x%x", -                           peer->host, -                           inet_ntop(rn->p.family, &rn->p.u.prefix, -                                     buf, SU_ADDRSTRLEN), -                           rn->p.prefixlen, -                           ri->flags); -            } -          else -            { -              if (!CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE)) -                zlog_warn ("%s [pcount] %s/%d not counted but flags 0x%x", -                           peer->host, -                           inet_ntop(rn->p.family, &rn->p.u.prefix, -                                     buf, SU_ADDRSTRLEN), -                           rn->p.prefixlen, -                           ri->flags); -            } -        } -    } -  return 0; +static int bgp_peer_count_walker(struct thread *t) +{ +	struct bgp_node *rn; +	struct peer_pcounts *pc = THREAD_ARG(t); +	const struct peer *peer = pc->peer; + +	for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn)) { +		struct bgp_adj_in *ain; +		struct bgp_info *ri; + +		for (ain = rn->adj_in; ain; ain = ain->next) +			if (ain->peer == peer) +				pc->count[PCOUNT_ADJ_IN]++; + +		for (ri = rn->info; ri; ri = ri->next) { +			char buf[SU_ADDRSTRLEN]; + +			if (ri->peer != peer) +				continue; + +			pc->count[PCOUNT_ALL]++; + +			if (CHECK_FLAG(ri->flags, BGP_INFO_DAMPED)) +				pc->count[PCOUNT_DAMPED]++; +			if (CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)) +				pc->count[PCOUNT_HISTORY]++; +			if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) +				pc->count[PCOUNT_REMOVED]++; +			if (CHECK_FLAG(ri->flags, BGP_INFO_STALE)) +				pc->count[PCOUNT_STALE]++; +			if (CHECK_FLAG(ri->flags, BGP_INFO_VALID)) +				pc->count[PCOUNT_VALID]++; +			if (!CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE)) +				pc->count[PCOUNT_PFCNT]++; + +			if (CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) { +				pc->count[PCOUNT_COUNTED]++; +				if (CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE)) +					zlog_warn( +						"%s [pcount] %s/%d is counted but flags 0x%x", +						peer->host, +						inet_ntop(rn->p.family, +							  &rn->p.u.prefix, buf, +							  SU_ADDRSTRLEN), +						rn->p.prefixlen, ri->flags); +			} else { +				if (!CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE)) +					zlog_warn( +						"%s [pcount] %s/%d not counted but flags 0x%x", +						peer->host, +						inet_ntop(rn->p.family, +							  &rn->p.u.prefix, buf, +							  SU_ADDRSTRLEN), +						rn->p.prefixlen, ri->flags); +			} +		} +	} +	return 0;  } -static int -bgp_peer_counts (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, u_char use_json) +static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi, +			   safi_t safi, u_char use_json)  { -  struct peer_pcounts pcounts = { .peer = peer }; -  unsigned int i; -  json_object *json = NULL; -  json_object *json_loop = NULL; +	struct peer_pcounts pcounts = {.peer = peer}; +	unsigned int i; +	json_object *json = NULL; +	json_object *json_loop = NULL; -  if (use_json) -    { -      json = json_object_new_object(); -      json_loop = json_object_new_object(); -    } -   -  if (!peer || !peer->bgp || !peer->afc[afi][safi] -      || !peer->bgp->rib[afi][safi]) -    { -      if (use_json) -        { -          json_object_string_add(json, "warning", "No such neighbor or address family"); -          vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); -          json_object_free(json); -        } -      else -        vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE); - -      return CMD_WARNING; -    } -   -  memset (&pcounts, 0, sizeof(pcounts)); -  pcounts.peer = peer; -  pcounts.table = peer->bgp->rib[afi][safi]; -   -  /* in-place call via thread subsystem so as to record execution time - *    * stats for the thread-walk (i.e. ensure this can't be blamed on - *       * on just vty_read()). - *          */ -  thread_execute (bm->master, bgp_peer_count_walker, &pcounts, 0); +	if (use_json) { +		json = json_object_new_object(); +		json_loop = json_object_new_object(); +	} -  if (use_json) -    { -      json_object_string_add(json, "prefixCountsFor", peer->host); -      json_object_string_add(json, "multiProtocol", afi_safi_print (afi, safi)); -      json_object_int_add(json, "pfxCounter", peer->pcount[afi][safi]); - -      for (i = 0; i < PCOUNT_MAX; i++) -        json_object_int_add(json_loop, pcount_strs[i], pcounts.count[i]); - -      json_object_object_add(json, "ribTableWalkCounters", json_loop); - -      if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) -        { -          json_object_string_add(json, "pfxctDriftFor", peer->host); -          json_object_string_add(json, "recommended", "Please report this bug, with the above command output"); -        } -      vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); -      json_object_free(json); -    } -  else -    { +	if (!peer || !peer->bgp || !peer->afc[afi][safi] +	    || !peer->bgp->rib[afi][safi]) { +		if (use_json) { +			json_object_string_add( +				json, "warning", +				"No such neighbor or address family"); +			vty_out(vty, "%s%s", json_object_to_json_string(json), +				VTY_NEWLINE); +			json_object_free(json); +		} else +			vty_out(vty, "%% No such neighbor or address family%s", +				VTY_NEWLINE); + +		return CMD_WARNING; +	} -      if (peer->hostname && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) -        { -          vty_out (vty, "Prefix counts for %s/%s, %s%s", -                   peer->hostname, peer->host, afi_safi_print (afi, safi), -                   VTY_NEWLINE); -        } -      else -        { -          vty_out (vty, "Prefix counts for %s, %s%s", -                   peer->host, afi_safi_print (afi, safi), VTY_NEWLINE); -        } - -      vty_out (vty, "PfxCt: %ld%s", peer->pcount[afi][safi], VTY_NEWLINE); -      vty_out (vty, "%sCounts from RIB table walk:%s%s", -               VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); - -      for (i = 0; i < PCOUNT_MAX; i++) -        vty_out (vty, "%20s: %-10d%s", pcount_strs[i], pcounts.count[i], VTY_NEWLINE); - -      if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) -        { -          vty_out (vty, "%s [pcount] PfxCt drift!%s", -                   peer->host, VTY_NEWLINE); -          vty_out (vty, "Please report this bug, with the above command output%s", -                   VTY_NEWLINE); -        } -    } -                -  return CMD_SUCCESS; +	memset(&pcounts, 0, sizeof(pcounts)); +	pcounts.peer = peer; +	pcounts.table = peer->bgp->rib[afi][safi]; + +	/* in-place call via thread subsystem so as to record execution time +       *    * stats for the thread-walk (i.e. ensure this can't be blamed on +       *       * on just vty_read()). +       *          */ +	thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0); + +	if (use_json) { +		json_object_string_add(json, "prefixCountsFor", peer->host); +		json_object_string_add(json, "multiProtocol", +				       afi_safi_print(afi, safi)); +		json_object_int_add(json, "pfxCounter", +				    peer->pcount[afi][safi]); + +		for (i = 0; i < PCOUNT_MAX; i++) +			json_object_int_add(json_loop, pcount_strs[i], +					    pcounts.count[i]); + +		json_object_object_add(json, "ribTableWalkCounters", json_loop); + +		if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) { +			json_object_string_add(json, "pfxctDriftFor", +					       peer->host); +			json_object_string_add( +				json, "recommended", +				"Please report this bug, with the above command output"); +		} +		vty_out(vty, "%s%s", json_object_to_json_string(json), +			VTY_NEWLINE); +		json_object_free(json); +	} else { + +		if (peer->hostname +		    && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) { +			vty_out(vty, "Prefix counts for %s/%s, %s%s", +				peer->hostname, peer->host, +				afi_safi_print(afi, safi), VTY_NEWLINE); +		} else { +			vty_out(vty, "Prefix counts for %s, %s%s", peer->host, +				afi_safi_print(afi, safi), VTY_NEWLINE); +		} + +		vty_out(vty, "PfxCt: %ld%s", peer->pcount[afi][safi], +			VTY_NEWLINE); +		vty_out(vty, "%sCounts from RIB table walk:%s%s", VTY_NEWLINE, +			VTY_NEWLINE, VTY_NEWLINE); + +		for (i = 0; i < PCOUNT_MAX; i++) +			vty_out(vty, "%20s: %-10d%s", pcount_strs[i], +				pcounts.count[i], VTY_NEWLINE); + +		if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) { +			vty_out(vty, "%s [pcount] PfxCt drift!%s", peer->host, +				VTY_NEWLINE); +			vty_out(vty, +				"Please report this bug, with the above command output%s", +				VTY_NEWLINE); +		} +	} + +	return CMD_SUCCESS;  }  DEFUN (show_ip_bgp_instance_neighbor_prefix_counts, @@ -9218,25 +9356,27 @@ DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,         "Display detailed prefix count information\n"         JSON_STR)  { -  afi_t afi = AFI_IP6; -  safi_t safi = SAFI_UNICAST; -  struct peer *peer; -  int idx = 0; -  struct bgp *bgp = NULL; +	afi_t afi = AFI_IP6; +	safi_t safi = SAFI_UNICAST; +	struct peer *peer; +	int idx = 0; +	struct bgp *bgp = NULL; -  bgp_vty_find_and_parse_afi_safi_bgp (vty, argv, argc, &idx, &afi, &safi, &bgp); -  if (!idx) -    return CMD_WARNING; +	bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, +					    &bgp); +	if (!idx) +		return CMD_WARNING; -  int uj = use_json (argc, argv); -  if (uj) argc--; +	int uj = use_json(argc, argv); +	if (uj) +		argc--; -  argv_find (argv, argc, "neighbors", &idx); -  peer = peer_lookup_in_view (vty, bgp, argv[idx+1]->arg, uj); -  if (! peer) -    return CMD_WARNING; +	argv_find(argv, argc, "neighbors", &idx); +	peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj); +	if (!peer) +		return CMD_WARNING; -  return bgp_peer_counts (vty, peer, AFI_IP, SAFI_UNICAST, uj); +	return bgp_peer_counts(vty, peer, AFI_IP, SAFI_UNICAST, uj);  }  #ifdef KEEP_OLD_VPN_COMMANDS @@ -9255,15 +9395,15 @@ DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,         "Display detailed prefix count information\n"         JSON_STR)  { -  int idx_peer = 6; -  struct peer *peer; -  u_char uj = use_json(argc, argv); +	int idx_peer = 6; +	struct peer *peer; +	u_char uj = use_json(argc, argv); -  peer = peer_lookup_in_view (vty, NULL, argv[idx_peer]->arg, uj); -  if (! peer) -    return CMD_WARNING; -   -  return bgp_peer_counts (vty, peer, AFI_IP, SAFI_MPLS_VPN, uj); +	peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj); +	if (!peer) +		return CMD_WARNING; + +	return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);  }  DEFUN (show_ip_bgp_vpn_all_route_prefix, @@ -9278,26 +9418,25 @@ DEFUN (show_ip_bgp_vpn_all_route_prefix,         "Network in the BGP routing table to display\n"         JSON_STR)  { -  int idx = 0; -  char *network = NULL; -  struct bgp *bgp = bgp_get_default(); -  if (!bgp) -    { -      vty_out (vty, "Can't find default instance%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +	int idx = 0; +	char *network = NULL; +	struct bgp *bgp = bgp_get_default(); +	if (!bgp) { +		vty_out(vty, "Can't find default instance%s", VTY_NEWLINE); +		return CMD_WARNING; +	} -  if (argv_find (argv, argc, "A.B.C.D", &idx)) -    network = argv[idx]->arg; -  else if (argv_find (argv, argc, "A.B.C.D/M", &idx)) -    network = argv[idx]->arg; -  else -    { -      vty_out (vty, "Unable to figure out Network%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +	if (argv_find(argv, argc, "A.B.C.D", &idx)) +		network = argv[idx]->arg; +	else if (argv_find(argv, argc, "A.B.C.D/M", &idx)) +		network = argv[idx]->arg; +	else { +		vty_out(vty, "Unable to figure out Network%s", VTY_NEWLINE); +		return CMD_WARNING; +	} -  return bgp_show_route (vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0, BGP_PATH_ALL, use_json(argc, argv)); +	return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0, +			      BGP_PATH_ALL, use_json(argc, argv));  }  #endif /* KEEP_OLD_VPN_COMMANDS */ @@ -9314,259 +9453,305 @@ DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix,         "Network in the BGP routing table to display\n"         JSON_STR)  { -  int idx = 0; -  char *network = NULL; - -  if (argv_find (argv, argc, "A.B.C.D", &idx)) -    network = argv[idx]->arg; -  else if (argv_find (argv, argc, "A.B.C.D/M", &idx)) -    network = argv[idx]->arg; -  else -    { -      vty_out (vty, "Unable to figure out Network%s", VTY_NEWLINE); -      return CMD_WARNING; -    } -  return bgp_show_route (vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL, 0, BGP_PATH_ALL, use_json(argc, argv)); -} - - static void -show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, -                int in, const char *rmap_name, u_char use_json, json_object *json) -{ -  struct bgp_table *table; -  struct bgp_adj_in *ain; -  struct bgp_adj_out *adj; -  unsigned long output_count; -  unsigned long filtered_count; -  struct bgp_node *rn; -  int header1 = 1; -  struct bgp *bgp; -  int header2 = 1; -  struct attr attr; -  struct attr_extra extra; -  int ret; -  struct update_subgroup *subgrp; -  json_object *json_scode = NULL; -  json_object *json_ocode = NULL; -  json_object *json_ar = NULL; -  struct peer_af *paf; - -  if (use_json) -    { -      json_scode = json_object_new_object(); -      json_ocode = json_object_new_object(); -      json_ar = json_object_new_object(); - -      json_object_string_add(json_scode, "suppressed", "s"); -      json_object_string_add(json_scode, "damped", "d"); -      json_object_string_add(json_scode, "history", "h"); -      json_object_string_add(json_scode, "valid", "*"); -      json_object_string_add(json_scode, "best", ">"); -      json_object_string_add(json_scode, "multipath", "="); -      json_object_string_add(json_scode, "internal", "i"); -      json_object_string_add(json_scode, "ribFailure", "r"); -      json_object_string_add(json_scode, "stale", "S"); -      json_object_string_add(json_scode, "removed", "R"); - -      json_object_string_add(json_ocode, "igp", "i"); -      json_object_string_add(json_ocode, "egp", "e"); -      json_object_string_add(json_ocode, "incomplete", "?"); -    } - -  bgp = peer->bgp; - -  if (! bgp) -    { -      if (use_json) -        { -          json_object_string_add(json, "alert", "no BGP"); -          vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); -          json_object_free(json); -        } -      else -        vty_out (vty, "%% No bgp%s", VTY_NEWLINE); -      return; -    } +	int idx = 0; +	char *network = NULL; -  table = bgp->rib[afi][safi]; +	if (argv_find(argv, argc, "A.B.C.D", &idx)) +		network = argv[idx]->arg; +	else if (argv_find(argv, argc, "A.B.C.D/M", &idx)) +		network = argv[idx]->arg; +	else { +		vty_out(vty, "Unable to figure out Network%s", VTY_NEWLINE); +		return CMD_WARNING; +	} +	return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL, 0, +			      BGP_PATH_ALL, use_json(argc, argv)); +} + +static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, +			   safi_t safi, int in, const char *rmap_name, +			   u_char use_json, json_object *json) +{ +	struct bgp_table *table; +	struct bgp_adj_in *ain; +	struct bgp_adj_out *adj; +	unsigned long output_count; +	unsigned long filtered_count; +	struct bgp_node *rn; +	int header1 = 1; +	struct bgp *bgp; +	int header2 = 1; +	struct attr attr; +	struct attr_extra extra; +	int ret; +	struct update_subgroup *subgrp; +	json_object *json_scode = NULL; +	json_object *json_ocode = NULL; +	json_object *json_ar = NULL; +	struct peer_af *paf; + +	if (use_json) { +		json_scode = json_object_new_object(); +		json_ocode = json_object_new_object(); +		json_ar = json_object_new_object(); + +		json_object_string_add(json_scode, "suppressed", "s"); +		json_object_string_add(json_scode, "damped", "d"); +		json_object_string_add(json_scode, "history", "h"); +		json_object_string_add(json_scode, "valid", "*"); +		json_object_string_add(json_scode, "best", ">"); +		json_object_string_add(json_scode, "multipath", "="); +		json_object_string_add(json_scode, "internal", "i"); +		json_object_string_add(json_scode, "ribFailure", "r"); +		json_object_string_add(json_scode, "stale", "S"); +		json_object_string_add(json_scode, "removed", "R"); + +		json_object_string_add(json_ocode, "igp", "i"); +		json_object_string_add(json_ocode, "egp", "e"); +		json_object_string_add(json_ocode, "incomplete", "?"); +	} -  output_count = filtered_count = 0; -  subgrp = peer_subgroup(peer, afi, safi); +	bgp = peer->bgp; -  if (!in && subgrp && CHECK_FLAG (subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) -    { -      if (use_json) -        { -          json_object_int_add(json, "bgpTableVersion", table->version); -          json_object_string_add(json, "bgpLocalRouterId", inet_ntoa (bgp->router_id)); -          json_object_object_add(json, "bgpStatusCodes", json_scode); -          json_object_object_add(json, "bgpOriginCodes", json_ocode); -          json_object_string_add(json, "bgpOriginatingDefaultNetwork", "0.0.0.0"); -        } -      else -        { -          vty_out (vty, "BGP table version is %" PRIu64 ", local router ID is %s%s", table->version, inet_ntoa (bgp->router_id), VTY_NEWLINE); -          vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE); -          vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE); - -          vty_out (vty, "Originating default network 0.0.0.0%s%s", -                   VTY_NEWLINE, VTY_NEWLINE); -        } -      header1 = 0; -    } - -  attr.extra = &extra; -  for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) -    { -      if (in) -        { -          for (ain = rn->adj_in; ain; ain = ain->next) -            { -              if (ain->peer == peer) -                { -                  if (header1) -                    { -                      if (use_json) -                        { -                          json_object_int_add(json, "bgpTableVersion", 0); -                          json_object_string_add(json, "bgpLocalRouterId", inet_ntoa (bgp->router_id)); -                          json_object_object_add(json, "bgpStatusCodes", json_scode); -                          json_object_object_add(json, "bgpOriginCodes", json_ocode); -                        } -                      else -                        { -                          vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE); -                          vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE); -                          vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE); -                        } -                      header1 = 0; -                    } -                  if (header2) -                    { -                      if (!use_json) -                        vty_out (vty, BGP_SHOW_HEADER, VTY_NEWLINE); -                      header2 = 0; -                    } -                  if (ain->attr) -                    { -                      bgp_attr_dup(&attr, ain->attr); -                      if (bgp_input_modifier(peer, &rn->p, &attr, afi, safi, rmap_name) != RMAP_DENY) -                        { -                          route_vty_out_tmp (vty, &rn->p, &attr, safi, use_json, json_ar); -                          output_count++; -                        } -                      else -                        filtered_count++; -                    } -                } -            } -        } -      else -        { -          for (adj = rn->adj_out; adj; adj = adj->next) -            SUBGRP_FOREACH_PEER(adj->subgroup, paf) -              if (paf->peer == peer) -                { -                  if (header1) -                    { -                      if (use_json) -                        { -                          json_object_int_add(json, "bgpTableVersion", table->version); -                          json_object_string_add(json, "bgpLocalRouterId", inet_ntoa (bgp->router_id)); -                          json_object_object_add(json, "bgpStatusCodes", json_scode); -                          json_object_object_add(json, "bgpOriginCodes", json_ocode); -                        } -                      else -                        { -                          vty_out (vty, "BGP table version is %" PRIu64 ", local router ID is %s%s", table->version, -                                   inet_ntoa (bgp->router_id), VTY_NEWLINE); -                          vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE); -                          vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE); -                        } -                      header1 = 0; -                    } - -                  if (header2) -                    { -                      if (!use_json) -                        vty_out (vty, BGP_SHOW_HEADER, VTY_NEWLINE); -                      header2 = 0; -                    } - -                  if (adj->attr) -                    { -                      bgp_attr_dup(&attr, adj->attr); -                      ret = bgp_output_modifier(peer, &rn->p, &attr, afi, safi, rmap_name); -                      if (ret != RMAP_DENY) -                        { -                          route_vty_out_tmp (vty, &rn->p, &attr, safi, use_json, json_ar); -                          output_count++; -                        } -                      else -                        filtered_count++; -                    } -                } -        } -    } -  if (use_json) -    json_object_object_add(json, "advertisedRoutes", json_ar); +	if (!bgp) { +		if (use_json) { +			json_object_string_add(json, "alert", "no BGP"); +			vty_out(vty, "%s%s", json_object_to_json_string(json), +				VTY_NEWLINE); +			json_object_free(json); +		} else +			vty_out(vty, "%% No bgp%s", VTY_NEWLINE); +		return; +	} -  if (output_count != 0) -    { -      if (use_json) -        json_object_int_add(json, "totalPrefixCounter", output_count); -      else -        vty_out (vty, "%sTotal number of prefixes %ld%s", -                 VTY_NEWLINE, output_count, VTY_NEWLINE); -    } -  if (use_json) -    { -      vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); -      json_object_free(json); -    } +	table = bgp->rib[afi][safi]; + +	output_count = filtered_count = 0; +	subgrp = peer_subgroup(peer, afi, safi); + +	if (!in && subgrp +	    && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) { +		if (use_json) { +			json_object_int_add(json, "bgpTableVersion", +					    table->version); +			json_object_string_add(json, "bgpLocalRouterId", +					       inet_ntoa(bgp->router_id)); +			json_object_object_add(json, "bgpStatusCodes", +					       json_scode); +			json_object_object_add(json, "bgpOriginCodes", +					       json_ocode); +			json_object_string_add(json, +					       "bgpOriginatingDefaultNetwork", +					       "0.0.0.0"); +		} else { +			vty_out(vty, "BGP table version is %" PRIu64 +				     ", local router ID is %s%s", +				table->version, inet_ntoa(bgp->router_id), +				VTY_NEWLINE); +			vty_out(vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, +				VTY_NEWLINE); +			vty_out(vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, +				VTY_NEWLINE); + +			vty_out(vty, "Originating default network 0.0.0.0%s%s", +				VTY_NEWLINE, VTY_NEWLINE); +		} +		header1 = 0; +	} +	attr.extra = &extra; +	for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { +		if (in) { +			for (ain = rn->adj_in; ain; ain = ain->next) { +				if (ain->peer == peer) { +					if (header1) { +						if (use_json) { +							json_object_int_add( +								json, +								"bgpTableVersion", +								0); +							json_object_string_add( +								json, +								"bgpLocalRouterId", +								inet_ntoa( +									bgp->router_id)); +							json_object_object_add( +								json, +								"bgpStatusCodes", +								json_scode); +							json_object_object_add( +								json, +								"bgpOriginCodes", +								json_ocode); +						} else { +							vty_out(vty, +								"BGP table version is 0, local router ID is %s%s", +								inet_ntoa( +									bgp->router_id), +								VTY_NEWLINE); +							vty_out(vty, +								BGP_SHOW_SCODE_HEADER, +								VTY_NEWLINE, +								VTY_NEWLINE); +							vty_out(vty, +								BGP_SHOW_OCODE_HEADER, +								VTY_NEWLINE, +								VTY_NEWLINE); +						} +						header1 = 0; +					} +					if (header2) { +						if (!use_json) +							vty_out(vty, +								BGP_SHOW_HEADER, +								VTY_NEWLINE); +						header2 = 0; +					} +					if (ain->attr) { +						bgp_attr_dup(&attr, ain->attr); +						if (bgp_input_modifier( +							    peer, &rn->p, &attr, +							    afi, safi, +							    rmap_name) +						    != RMAP_DENY) { +							route_vty_out_tmp( +								vty, &rn->p, +								&attr, safi, +								use_json, +								json_ar); +							output_count++; +						} else +							filtered_count++; +					} +				} +			} +		} else { +			for (adj = rn->adj_out; adj; adj = adj->next) +				SUBGRP_FOREACH_PEER(adj->subgroup, paf) +			if (paf->peer == peer) { +				if (header1) { +					if (use_json) { +						json_object_int_add( +							json, "bgpTableVersion", +							table->version); +						json_object_string_add( +							json, +							"bgpLocalRouterId", +							inet_ntoa( +								bgp->router_id)); +						json_object_object_add( +							json, "bgpStatusCodes", +							json_scode); +						json_object_object_add( +							json, "bgpOriginCodes", +							json_ocode); +					} else { +						vty_out(vty, +							"BGP table version is %" PRIu64 +							", local router ID is %s%s", +							table->version, +							inet_ntoa( +								bgp->router_id), +							VTY_NEWLINE); +						vty_out(vty, +							BGP_SHOW_SCODE_HEADER, +							VTY_NEWLINE, +							VTY_NEWLINE); +						vty_out(vty, +							BGP_SHOW_OCODE_HEADER, +							VTY_NEWLINE, +							VTY_NEWLINE); +					} +					header1 = 0; +				} + +				if (header2) { +					if (!use_json) +						vty_out(vty, BGP_SHOW_HEADER, +							VTY_NEWLINE); +					header2 = 0; +				} + +				if (adj->attr) { +					bgp_attr_dup(&attr, adj->attr); +					ret = bgp_output_modifier( +						peer, &rn->p, &attr, afi, safi, +						rmap_name); +					if (ret != RMAP_DENY) { +						route_vty_out_tmp(vty, &rn->p, +								  &attr, safi, +								  use_json, +								  json_ar); +						output_count++; +					} else +						filtered_count++; +				} +			} +		} +	} +	if (use_json) +		json_object_object_add(json, "advertisedRoutes", json_ar); + +	if (output_count != 0) { +		if (use_json) +			json_object_int_add(json, "totalPrefixCounter", +					    output_count); +		else +			vty_out(vty, "%sTotal number of prefixes %ld%s", +				VTY_NEWLINE, output_count, VTY_NEWLINE); +	} +	if (use_json) { +		vty_out(vty, "%s%s", json_object_to_json_string(json), +			VTY_NEWLINE); +		json_object_free(json); +	}  } -static int -peer_adj_routes (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, -                 int in, const char *rmap_name, u_char use_json) +static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi, +			   safi_t safi, int in, const char *rmap_name, +			   u_char use_json)  { -  json_object *json = NULL; +	json_object *json = NULL; -  if (use_json) -    json = json_object_new_object(); +	if (use_json) +		json = json_object_new_object(); -  if (!peer || !peer->afc[afi][safi]) -    { -      if (use_json) -        { -          json_object_string_add(json, "warning", "No such neighbor or address family"); -          vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); -          json_object_free(json); -        } -      else -        vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE); - -      return CMD_WARNING; -    } +	if (!peer || !peer->afc[afi][safi]) { +		if (use_json) { +			json_object_string_add( +				json, "warning", +				"No such neighbor or address family"); +			vty_out(vty, "%s%s", json_object_to_json_string(json), +				VTY_NEWLINE); +			json_object_free(json); +		} else +			vty_out(vty, "%% No such neighbor or address family%s", +				VTY_NEWLINE); -  if (in && !CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)) -    { -      if (use_json) -        { -          json_object_string_add(json, "warning", "Inbound soft reconfiguration not enabled"); -          vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); -          json_object_free(json); -        } -      else -        vty_out (vty, "%% Inbound soft reconfiguration not enabled%s", VTY_NEWLINE); - -      return CMD_WARNING; -    } +		return CMD_WARNING; +	} + +	if (in +	    && !CHECK_FLAG(peer->af_flags[afi][safi], +			   PEER_FLAG_SOFT_RECONFIG)) { +		if (use_json) { +			json_object_string_add( +				json, "warning", +				"Inbound soft reconfiguration not enabled"); +			vty_out(vty, "%s%s", json_object_to_json_string(json), +				VTY_NEWLINE); +			json_object_free(json); +		} else +			vty_out(vty, +				"%% Inbound soft reconfiguration not enabled%s", +				VTY_NEWLINE); + +		return CMD_WARNING; +	} -  show_adj_route (vty, peer, afi, safi, in, rmap_name, use_json, json); +	show_adj_route(vty, peer, afi, safi, in, rmap_name, use_json, json); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_bgp_instance_neighbor_advertised_route, @@ -9589,39 +9774,41 @@ DEFUN (show_ip_bgp_instance_neighbor_advertised_route,         "Name of the route map\n"         JSON_STR)  { -  afi_t afi = AFI_IP6; -  safi_t safi = SAFI_UNICAST; -  char *rmap_name = NULL; -  char *peerstr = NULL; -  int rcvd = 0; -  struct bgp *bgp = NULL; -  struct peer *peer; +	afi_t afi = AFI_IP6; +	safi_t safi = SAFI_UNICAST; +	char *rmap_name = NULL; +	char *peerstr = NULL; +	int rcvd = 0; +	struct bgp *bgp = NULL; +	struct peer *peer; -  int idx = 0; +	int idx = 0; -  bgp_vty_find_and_parse_afi_safi_bgp (vty, argv, argc, &idx, &afi, &safi, &bgp); -  if (!idx) -    return CMD_WARNING; +	bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, +					    &bgp); +	if (!idx) +		return CMD_WARNING; -  int uj = use_json (argc, argv); -  if (uj) argc--; +	int uj = use_json(argc, argv); +	if (uj) +		argc--; -  /* neighbors <A.B.C.D|X:X::X:X|WORD> */ -  argv_find (argv, argc, "neighbors", &idx); -  peerstr = argv[++idx]->arg; +	/* neighbors <A.B.C.D|X:X::X:X|WORD> */ +	argv_find(argv, argc, "neighbors", &idx); +	peerstr = argv[++idx]->arg; -  peer = peer_lookup_in_view (vty, bgp, peerstr, uj); -  if (! peer)  -    return CMD_WARNING; +	peer = peer_lookup_in_view(vty, bgp, peerstr, uj); +	if (!peer) +		return CMD_WARNING; -  if (argv_find (argv, argc, "received-routes", &idx)) -    rcvd = 1; -  if (argv_find (argv, argc, "advertised-routes", &idx)) -    rcvd = 0; -  if (argv_find (argv, argc, "route-map", &idx)) -    rmap_name = argv[++idx]->arg; +	if (argv_find(argv, argc, "received-routes", &idx)) +		rcvd = 1; +	if (argv_find(argv, argc, "advertised-routes", &idx)) +		rcvd = 0; +	if (argv_find(argv, argc, "route-map", &idx)) +		rmap_name = argv[++idx]->arg; -  return peer_adj_routes (vty, peer, afi, safi, rcvd, rmap_name, uj); +	return peer_adj_routes(vty, peer, afi, safi, rcvd, rmap_name, uj);  }  DEFUN (show_ip_bgp_neighbor_received_prefix_filter, @@ -9641,96 +9828,93 @@ DEFUN (show_ip_bgp_neighbor_received_prefix_filter,         "Display the prefixlist filter\n"         JSON_STR)  { -  afi_t afi = AFI_IP6; -  safi_t safi = SAFI_UNICAST; -  char *peerstr = NULL; - -  char name[BUFSIZ]; -  union sockunion su; -  struct peer *peer; -  int count, ret; - -  int idx = 0; - -  /* show [ip] bgp */ -  if (argv_find (argv, argc, "ip", &idx)) -    afi = AFI_IP; -  /* [<ipv4|ipv6> [unicast]] */ -  if (argv_find (argv, argc, "ipv4", &idx)) -    afi = AFI_IP; -  if (argv_find (argv, argc, "ipv6", &idx)) -    afi = AFI_IP6; -  /* neighbors <A.B.C.D|X:X::X:X|WORD> */ -  argv_find (argv, argc, "neighbors", &idx); -  peerstr = argv[++idx]->arg; - -  u_char uj = use_json(argc, argv); - -  ret = str2sockunion (peerstr, &su); -  if (ret < 0) -    { -      peer = peer_lookup_by_conf_if (NULL, peerstr); -      if (! peer) -        { -          if (uj) -            vty_out (vty, "{}%s", VTY_NEWLINE); -          else -            vty_out (vty, "%% Malformed address or name: %s%s", peerstr, VTY_NEWLINE); -          return CMD_WARNING; -        } -    } -  else -    { -      peer = peer_lookup (NULL, &su); -      if (! peer) -        { -          if (uj) -            vty_out (vty, "{}%s", VTY_NEWLINE); -          else -            vty_out (vty, "No peer%s", VTY_NEWLINE); -          return CMD_WARNING; -        } -    } - -  sprintf (name, "%s.%d.%d", peer->host, afi, safi); -  count =  prefix_bgp_show_prefix_list (NULL, afi, name, uj); -  if (count) -    { -      if (!uj) -        vty_out (vty, "Address Family: %s%s", afi_safi_print(afi, safi), VTY_NEWLINE); -      prefix_bgp_show_prefix_list (vty, afi, name, uj); -    } -  else -    { -      if (uj) -        vty_out (vty, "{}%s", VTY_NEWLINE); -      else -        vty_out (vty, "No functional output%s", VTY_NEWLINE); -    } +	afi_t afi = AFI_IP6; +	safi_t safi = SAFI_UNICAST; +	char *peerstr = NULL; + +	char name[BUFSIZ]; +	union sockunion su; +	struct peer *peer; +	int count, ret; + +	int idx = 0; + +	/* show [ip] bgp */ +	if (argv_find(argv, argc, "ip", &idx)) +		afi = AFI_IP; +	/* [<ipv4|ipv6> [unicast]] */ +	if (argv_find(argv, argc, "ipv4", &idx)) +		afi = AFI_IP; +	if (argv_find(argv, argc, "ipv6", &idx)) +		afi = AFI_IP6; +	/* neighbors <A.B.C.D|X:X::X:X|WORD> */ +	argv_find(argv, argc, "neighbors", &idx); +	peerstr = argv[++idx]->arg; + +	u_char uj = use_json(argc, argv); + +	ret = str2sockunion(peerstr, &su); +	if (ret < 0) { +		peer = peer_lookup_by_conf_if(NULL, peerstr); +		if (!peer) { +			if (uj) +				vty_out(vty, "{}%s", VTY_NEWLINE); +			else +				vty_out(vty, +					"%% Malformed address or name: %s%s", +					peerstr, VTY_NEWLINE); +			return CMD_WARNING; +		} +	} else { +		peer = peer_lookup(NULL, &su); +		if (!peer) { +			if (uj) +				vty_out(vty, "{}%s", VTY_NEWLINE); +			else +				vty_out(vty, "No peer%s", VTY_NEWLINE); +			return CMD_WARNING; +		} +	} -  return CMD_SUCCESS; -} +	sprintf(name, "%s.%d.%d", peer->host, afi, safi); +	count = prefix_bgp_show_prefix_list(NULL, afi, name, uj); +	if (count) { +		if (!uj) +			vty_out(vty, "Address Family: %s%s", +				afi_safi_print(afi, safi), VTY_NEWLINE); +		prefix_bgp_show_prefix_list(vty, afi, name, uj); +	} else { +		if (uj) +			vty_out(vty, "{}%s", VTY_NEWLINE); +		else +			vty_out(vty, "No functional output%s", VTY_NEWLINE); +	} -static int -bgp_show_neighbor_route (struct vty *vty, struct peer *peer, afi_t afi, -			 safi_t safi, enum bgp_show_type type, u_char use_json) -{ -  if (! peer || ! peer->afc[afi][safi]) -    { -      if (use_json) -        { -          json_object *json_no = NULL; -          json_no = json_object_new_object(); -          json_object_string_add(json_no, "warning", "No such neighbor or address family"); -          vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE); -          json_object_free(json_no); -        } -      else -        vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +	return CMD_SUCCESS; +} + +static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer, +				   afi_t afi, safi_t safi, +				   enum bgp_show_type type, u_char use_json) +{ +	if (!peer || !peer->afc[afi][safi]) { +		if (use_json) { +			json_object *json_no = NULL; +			json_no = json_object_new_object(); +			json_object_string_add( +				json_no, "warning", +				"No such neighbor or address family"); +			vty_out(vty, "%s%s", +				json_object_to_json_string(json_no), +				VTY_NEWLINE); +			json_object_free(json_no); +		} else +			vty_out(vty, "%% No such neighbor or address family%s", +				VTY_NEWLINE); +		return CMD_WARNING; +	} -  return bgp_show (vty, peer->bgp, afi, safi, type, &peer->su, use_json); +	return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json);  }  DEFUN (show_ip_bgp_neighbor_routes, @@ -9752,52 +9936,52 @@ DEFUN (show_ip_bgp_neighbor_routes,         "Display routes learned from neighbor\n"         JSON_STR)  { -  char *peerstr = NULL; -  struct bgp *bgp = NULL; -  afi_t afi = AFI_IP6; -  safi_t safi = SAFI_UNICAST; -  struct peer *peer; -  enum bgp_show_type sh_type = bgp_show_type_neighbor; +	char *peerstr = NULL; +	struct bgp *bgp = NULL; +	afi_t afi = AFI_IP6; +	safi_t safi = SAFI_UNICAST; +	struct peer *peer; +	enum bgp_show_type sh_type = bgp_show_type_neighbor; -  int idx = 0; +	int idx = 0; -  bgp_vty_find_and_parse_afi_safi_bgp (vty, argv, argc, &idx, &afi, &safi, &bgp); -  if (!idx) -    return CMD_WARNING; +	bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, +					    &bgp); +	if (!idx) +		return CMD_WARNING; -  int uj = use_json (argc, argv); -  if (uj) argc--; +	int uj = use_json(argc, argv); +	if (uj) +		argc--; -  /* neighbors <A.B.C.D|X:X::X:X|WORD> */ -  argv_find (argv, argc, "neighbors", &idx); -  peerstr = argv[++idx]->arg; +	/* neighbors <A.B.C.D|X:X::X:X|WORD> */ +	argv_find(argv, argc, "neighbors", &idx); +	peerstr = argv[++idx]->arg; -  peer = peer_lookup_in_view (vty, bgp, peerstr, uj); -  if (! peer) -    { -      vty_out (vty, "No such neighbor%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +	peer = peer_lookup_in_view(vty, bgp, peerstr, uj); +	if (!peer) { +		vty_out(vty, "No such neighbor%s", VTY_NEWLINE); +		return CMD_WARNING; +	} -  if (argv_find (argv, argc, "flap-statistics", &idx)) -    sh_type = bgp_show_type_flap_neighbor; -  else if (argv_find (argv, argc, "dampened-routes", &idx)) -    sh_type = bgp_show_type_damp_neighbor; -  else if (argv_find (argv, argc, "routes", &idx)) -    sh_type = bgp_show_type_neighbor; +	if (argv_find(argv, argc, "flap-statistics", &idx)) +		sh_type = bgp_show_type_flap_neighbor; +	else if (argv_find(argv, argc, "dampened-routes", &idx)) +		sh_type = bgp_show_type_damp_neighbor; +	else if (argv_find(argv, argc, "routes", &idx)) +		sh_type = bgp_show_type_neighbor; -  return bgp_show_neighbor_route (vty, peer, afi, safi, sh_type, uj); +	return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);  }  struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX]; -struct bgp_distance -{ -  /* Distance value for the IP source prefix. */ -  u_char distance; +struct bgp_distance { +	/* Distance value for the IP source prefix. */ +	u_char distance; -  /* Name of the access-list to be matched. */ -  char *access_list; +	/* Name of the access-list to be matched. */ +	char *access_list;  };  DEFUN (show_bgp_afi_vpn_rd_route, @@ -9813,197 +9997,180 @@ DEFUN (show_bgp_afi_vpn_rd_route,         "Network in the BGP routing table to display\n"         JSON_STR)  { -  int ret; -  struct prefix_rd prd; -  afi_t afi = AFI_MAX; -  int idx = 0; +	int ret; +	struct prefix_rd prd; +	afi_t afi = AFI_MAX; +	int idx = 0; -  argv_find_and_parse_afi (argv, argc, &idx, &afi); -  ret = str2prefix_rd (argv[5]->arg, &prd); -  if (! ret) -    { -      vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE); -      return CMD_WARNING; -    } -  return bgp_show_route (vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd, 0, BGP_PATH_ALL, use_json (argc, argv)); +	argv_find_and_parse_afi(argv, argc, &idx, &afi); +	ret = str2prefix_rd(argv[5]->arg, &prd); +	if (!ret) { +		vty_out(vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE); +		return CMD_WARNING; +	} +	return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd, +			      0, BGP_PATH_ALL, use_json(argc, argv));  } -static struct bgp_distance * -bgp_distance_new (void) +static struct bgp_distance *bgp_distance_new(void)  { -  return XCALLOC (MTYPE_BGP_DISTANCE, sizeof (struct bgp_distance)); +	return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));  } -static void -bgp_distance_free (struct bgp_distance *bdistance) +static void bgp_distance_free(struct bgp_distance *bdistance)  { -  XFREE (MTYPE_BGP_DISTANCE, bdistance); +	XFREE(MTYPE_BGP_DISTANCE, bdistance);  } -static int -bgp_distance_set (struct vty *vty, const char *distance_str,  -                  const char *ip_str, const char *access_list_str) +static int bgp_distance_set(struct vty *vty, const char *distance_str, +			    const char *ip_str, const char *access_list_str)  { -  int ret; -  afi_t afi; -  safi_t safi; -  struct prefix p; -  u_char distance; -  struct bgp_node *rn; -  struct bgp_distance *bdistance; +	int ret; +	afi_t afi; +	safi_t safi; +	struct prefix p; +	u_char distance; +	struct bgp_node *rn; +	struct bgp_distance *bdistance; -  afi = bgp_node_afi (vty); -  safi = bgp_node_safi (vty); +	afi = bgp_node_afi(vty); +	safi = bgp_node_safi(vty); -  ret = str2prefix (ip_str, &p); -  if (ret == 0) -    { -      vty_out (vty, "Malformed prefix%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +	ret = str2prefix(ip_str, &p); +	if (ret == 0) { +		vty_out(vty, "Malformed prefix%s", VTY_NEWLINE); +		return CMD_WARNING; +	} -  distance = atoi (distance_str); +	distance = atoi(distance_str); -  /* Get BGP distance node. */ -  rn = bgp_node_get (bgp_distance_table[afi][safi], (struct prefix *) &p); -  if (rn->info) -    { -      bdistance = rn->info; -      bgp_unlock_node (rn); -    } -  else -    { -      bdistance = bgp_distance_new (); -      rn->info = bdistance; -    } +	/* Get BGP distance node. */ +	rn = bgp_node_get(bgp_distance_table[afi][safi], (struct prefix *)&p); +	if (rn->info) { +		bdistance = rn->info; +		bgp_unlock_node(rn); +	} else { +		bdistance = bgp_distance_new(); +		rn->info = bdistance; +	} -  /* Set distance value. */ -  bdistance->distance = distance; +	/* Set distance value. */ +	bdistance->distance = distance; -  /* Reset access-list configuration. */ -  if (bdistance->access_list) -    { -      XFREE(MTYPE_AS_LIST, bdistance->access_list); -      bdistance->access_list = NULL; -    } -  if (access_list_str) -    bdistance->access_list = XSTRDUP(MTYPE_AS_LIST, access_list_str); +	/* Reset access-list configuration. */ +	if (bdistance->access_list) { +		XFREE(MTYPE_AS_LIST, bdistance->access_list); +		bdistance->access_list = NULL; +	} +	if (access_list_str) +		bdistance->access_list = +			XSTRDUP(MTYPE_AS_LIST, access_list_str); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  } -static int -bgp_distance_unset (struct vty *vty, const char *distance_str,  -                    const char *ip_str, const char *access_list_str) +static int bgp_distance_unset(struct vty *vty, const char *distance_str, +			      const char *ip_str, const char *access_list_str)  { -  int ret; -  afi_t afi; -  safi_t safi; -  struct prefix p; -  int distance; -  struct bgp_node *rn; -  struct bgp_distance *bdistance; +	int ret; +	afi_t afi; +	safi_t safi; +	struct prefix p; +	int distance; +	struct bgp_node *rn; +	struct bgp_distance *bdistance; -  afi = bgp_node_afi (vty); -  safi = bgp_node_safi (vty); +	afi = bgp_node_afi(vty); +	safi = bgp_node_safi(vty); -  ret = str2prefix (ip_str, &p); -  if (ret == 0) -    { -      vty_out (vty, "Malformed prefix%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +	ret = str2prefix(ip_str, &p); +	if (ret == 0) { +		vty_out(vty, "Malformed prefix%s", VTY_NEWLINE); +		return CMD_WARNING; +	} -  rn = bgp_node_lookup (bgp_distance_table[afi][safi], (struct prefix *)&p); -  if (! rn) -    { -      vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +	rn = bgp_node_lookup(bgp_distance_table[afi][safi], +			     (struct prefix *)&p); +	if (!rn) { +		vty_out(vty, "Can't find specified prefix%s", VTY_NEWLINE); +		return CMD_WARNING; +	} -  bdistance = rn->info; -  distance = atoi(distance_str); +	bdistance = rn->info; +	distance = atoi(distance_str); -  if (bdistance->distance != distance) -    { -       vty_out (vty, "Distance does not match configured%s", VTY_NEWLINE); -       return CMD_WARNING; -    } +	if (bdistance->distance != distance) { +		vty_out(vty, "Distance does not match configured%s", +			VTY_NEWLINE); +		return CMD_WARNING; +	} -  if (bdistance->access_list) -    XFREE(MTYPE_AS_LIST, bdistance->access_list); -  bgp_distance_free (bdistance); +	if (bdistance->access_list) +		XFREE(MTYPE_AS_LIST, bdistance->access_list); +	bgp_distance_free(bdistance); -  rn->info = NULL; -  bgp_unlock_node (rn); -  bgp_unlock_node (rn); +	rn->info = NULL; +	bgp_unlock_node(rn); +	bgp_unlock_node(rn); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  /* Apply BGP information to distance method. */ -u_char -bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, afi_t afi, -		    safi_t safi, struct bgp *bgp) -{ -  struct bgp_node *rn; -  struct prefix q; -  struct peer *peer; -  struct bgp_distance *bdistance; -  struct access_list *alist; -  struct bgp_static *bgp_static; - -  if (! bgp) -    return 0; - -  peer = rinfo->peer; - -  /* Check source address. */ -  sockunion2hostprefix (&peer->su, &q); -  rn = bgp_node_match (bgp_distance_table[afi][safi], &q); -  if (rn) -    { -      bdistance = rn->info; -      bgp_unlock_node (rn); - -      if (bdistance->access_list) -	{ -	  alist = access_list_lookup (afi, bdistance->access_list); -	  if (alist && access_list_apply (alist, p) == FILTER_PERMIT) -	    return bdistance->distance; +u_char bgp_distance_apply(struct prefix *p, struct bgp_info *rinfo, afi_t afi, +			  safi_t safi, struct bgp *bgp) +{ +	struct bgp_node *rn; +	struct prefix q; +	struct peer *peer; +	struct bgp_distance *bdistance; +	struct access_list *alist; +	struct bgp_static *bgp_static; + +	if (!bgp) +		return 0; + +	peer = rinfo->peer; + +	/* Check source address. */ +	sockunion2hostprefix(&peer->su, &q); +	rn = bgp_node_match(bgp_distance_table[afi][safi], &q); +	if (rn) { +		bdistance = rn->info; +		bgp_unlock_node(rn); + +		if (bdistance->access_list) { +			alist = access_list_lookup(afi, bdistance->access_list); +			if (alist +			    && access_list_apply(alist, p) == FILTER_PERMIT) +				return bdistance->distance; +		} else +			return bdistance->distance;  	} -      else -	return bdistance->distance; -    } -  /* Backdoor check. */ -  rn = bgp_node_lookup (bgp->route[afi][safi], p); -  if (rn) -    { -      bgp_static = rn->info; -      bgp_unlock_node (rn); +	/* Backdoor check. */ +	rn = bgp_node_lookup(bgp->route[afi][safi], p); +	if (rn) { +		bgp_static = rn->info; +		bgp_unlock_node(rn); -      if (bgp_static->backdoor) -	{ -	  if (bgp->distance_local[afi][safi]) -	    return bgp->distance_local[afi][safi]; -	  else -	    return ZEBRA_IBGP_DISTANCE_DEFAULT; +		if (bgp_static->backdoor) { +			if (bgp->distance_local[afi][safi]) +				return bgp->distance_local[afi][safi]; +			else +				return ZEBRA_IBGP_DISTANCE_DEFAULT; +		}  	} -    } -  if (peer->sort == BGP_PEER_EBGP) -    { -      if (bgp->distance_ebgp[afi][safi]) -	return bgp->distance_ebgp[afi][safi]; -      return ZEBRA_EBGP_DISTANCE_DEFAULT; -    } -  else -    { -      if (bgp->distance_ibgp[afi][safi]) -	return bgp->distance_ibgp[afi][safi]; -      return ZEBRA_IBGP_DISTANCE_DEFAULT; -    } +	if (peer->sort == BGP_PEER_EBGP) { +		if (bgp->distance_ebgp[afi][safi]) +			return bgp->distance_ebgp[afi][safi]; +		return ZEBRA_EBGP_DISTANCE_DEFAULT; +	} else { +		if (bgp->distance_ibgp[afi][safi]) +			return bgp->distance_ibgp[afi][safi]; +		return ZEBRA_IBGP_DISTANCE_DEFAULT; +	}  }  DEFUN (bgp_distance, @@ -10015,20 +10182,20 @@ DEFUN (bgp_distance,         "Distance for routes internal to the AS\n"         "Distance for local routes\n")  { -  VTY_DECLVAR_CONTEXT(bgp, bgp); -  int idx_number = 2; -  int idx_number_2 = 3; -  int idx_number_3 = 4; -  afi_t afi; -  safi_t safi; +	VTY_DECLVAR_CONTEXT(bgp, bgp); +	int idx_number = 2; +	int idx_number_2 = 3; +	int idx_number_3 = 4; +	afi_t afi; +	safi_t safi; -  afi = bgp_node_afi (vty); -  safi = bgp_node_safi (vty); +	afi = bgp_node_afi(vty); +	safi = bgp_node_safi(vty); -  bgp->distance_ebgp[afi][safi] = atoi (argv[idx_number]->arg); -  bgp->distance_ibgp[afi][safi] = atoi (argv[idx_number_2]->arg); -  bgp->distance_local[afi][safi] = atoi (argv[idx_number_3]->arg); -  return CMD_SUCCESS; +	bgp->distance_ebgp[afi][safi] = atoi(argv[idx_number]->arg); +	bgp->distance_ibgp[afi][safi] = atoi(argv[idx_number_2]->arg); +	bgp->distance_local[afi][safi] = atoi(argv[idx_number_3]->arg); +	return CMD_SUCCESS;  }  DEFUN (no_bgp_distance, @@ -10041,17 +10208,17 @@ DEFUN (no_bgp_distance,         "Distance for routes internal to the AS\n"         "Distance for local routes\n")  { -  VTY_DECLVAR_CONTEXT(bgp, bgp); -  afi_t afi; -  safi_t safi; +	VTY_DECLVAR_CONTEXT(bgp, bgp); +	afi_t afi; +	safi_t safi; -  afi = bgp_node_afi (vty); -  safi = bgp_node_safi (vty); +	afi = bgp_node_afi(vty); +	safi = bgp_node_safi(vty); -  bgp->distance_ebgp[afi][safi] = 0; -  bgp->distance_ibgp[afi][safi] = 0; -  bgp->distance_local[afi][safi] = 0; -  return CMD_SUCCESS; +	bgp->distance_ebgp[afi][safi] = 0; +	bgp->distance_ibgp[afi][safi] = 0; +	bgp->distance_local[afi][safi] = 0; +	return CMD_SUCCESS;  } @@ -10062,10 +10229,11 @@ DEFUN (bgp_distance_source,         "Administrative distance\n"         "IP source prefix\n")  { -  int idx_number = 1; -  int idx_ipv4_prefixlen = 2; -  bgp_distance_set (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, NULL); -  return CMD_SUCCESS; +	int idx_number = 1; +	int idx_ipv4_prefixlen = 2; +	bgp_distance_set(vty, argv[idx_number]->arg, +			 argv[idx_ipv4_prefixlen]->arg, NULL); +	return CMD_SUCCESS;  }  DEFUN (no_bgp_distance_source, @@ -10076,10 +10244,11 @@ DEFUN (no_bgp_distance_source,         "Administrative distance\n"         "IP source prefix\n")  { -  int idx_number = 2; -  int idx_ipv4_prefixlen = 3; -  bgp_distance_unset (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, NULL); -  return CMD_SUCCESS; +	int idx_number = 2; +	int idx_ipv4_prefixlen = 3; +	bgp_distance_unset(vty, argv[idx_number]->arg, +			   argv[idx_ipv4_prefixlen]->arg, NULL); +	return CMD_SUCCESS;  }  DEFUN (bgp_distance_source_access_list, @@ -10090,11 +10259,12 @@ DEFUN (bgp_distance_source_access_list,         "IP source prefix\n"         "Access list name\n")  { -  int idx_number = 1; -  int idx_ipv4_prefixlen = 2; -  int idx_word = 3; -  bgp_distance_set (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg); -  return CMD_SUCCESS; +	int idx_number = 1; +	int idx_ipv4_prefixlen = 2; +	int idx_word = 3; +	bgp_distance_set(vty, argv[idx_number]->arg, +			 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg); +	return CMD_SUCCESS;  }  DEFUN (no_bgp_distance_source_access_list, @@ -10106,11 +10276,12 @@ DEFUN (no_bgp_distance_source_access_list,         "IP source prefix\n"         "Access list name\n")  { -  int idx_number = 2; -  int idx_ipv4_prefixlen = 3; -  int idx_word = 4; -  bgp_distance_unset (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg); -  return CMD_SUCCESS; +	int idx_number = 2; +	int idx_ipv4_prefixlen = 3; +	int idx_word = 4; +	bgp_distance_unset(vty, argv[idx_number]->arg, +			   argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg); +	return CMD_SUCCESS;  }  DEFUN (ipv6_bgp_distance_source, @@ -10120,8 +10291,8 @@ DEFUN (ipv6_bgp_distance_source,         "Administrative distance\n"         "IP source prefix\n")  { -  bgp_distance_set (vty, argv[1]->arg, argv[2]->arg, NULL); -  return CMD_SUCCESS; +	bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL); +	return CMD_SUCCESS;  }  DEFUN (no_ipv6_bgp_distance_source, @@ -10132,8 +10303,8 @@ DEFUN (no_ipv6_bgp_distance_source,         "Administrative distance\n"         "IP source prefix\n")  { -  bgp_distance_unset (vty, argv[2]->arg, argv[3]->arg, NULL); -  return CMD_SUCCESS; +	bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL); +	return CMD_SUCCESS;  }  DEFUN (ipv6_bgp_distance_source_access_list, @@ -10144,8 +10315,8 @@ DEFUN (ipv6_bgp_distance_source_access_list,         "IP source prefix\n"         "Access list name\n")  { -  bgp_distance_set (vty, argv[1]->arg, argv[2]->arg, argv[3]->arg); -  return CMD_SUCCESS; +	bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg); +	return CMD_SUCCESS;  }  DEFUN (no_ipv6_bgp_distance_source_access_list, @@ -10157,8 +10328,8 @@ DEFUN (no_ipv6_bgp_distance_source_access_list,         "IP source prefix\n"         "Access list name\n")  { -  bgp_distance_unset (vty, argv[2]->arg, argv[3]->arg, argv[4]->arg); -  return CMD_SUCCESS; +	bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg); +	return CMD_SUCCESS;  }  DEFUN (bgp_damp_set, @@ -10171,38 +10342,35 @@ DEFUN (bgp_damp_set,         "Value to start suppressing a route\n"         "Maximum duration to suppress a stable route\n")  { -  VTY_DECLVAR_CONTEXT(bgp, bgp); -  int idx_half_life = 2; -  int idx_reuse = 3; -  int idx_suppress = 4; -  int idx_max_suppress = 5; -  int half = DEFAULT_HALF_LIFE * 60; -  int reuse = DEFAULT_REUSE; -  int suppress = DEFAULT_SUPPRESS; -  int max = 4 * half; - -  if (argc == 6) -    { -      half = atoi (argv[idx_half_life]->arg) * 60; -      reuse = atoi (argv[idx_reuse]->arg); -      suppress = atoi (argv[idx_suppress]->arg); -      max = atoi (argv[idx_max_suppress]->arg) * 60; -    } -  else if (argc == 3) -    { -      half = atoi (argv[idx_half_life]->arg) * 60; -      max = 4 * half; -    } +	VTY_DECLVAR_CONTEXT(bgp, bgp); +	int idx_half_life = 2; +	int idx_reuse = 3; +	int idx_suppress = 4; +	int idx_max_suppress = 5; +	int half = DEFAULT_HALF_LIFE * 60; +	int reuse = DEFAULT_REUSE; +	int suppress = DEFAULT_SUPPRESS; +	int max = 4 * half; + +	if (argc == 6) { +		half = atoi(argv[idx_half_life]->arg) * 60; +		reuse = atoi(argv[idx_reuse]->arg); +		suppress = atoi(argv[idx_suppress]->arg); +		max = atoi(argv[idx_max_suppress]->arg) * 60; +	} else if (argc == 3) { +		half = atoi(argv[idx_half_life]->arg) * 60; +		max = 4 * half; +	} -  if (suppress < reuse) -    { -      vty_out (vty, "Suppress value cannot be less than reuse value %s", -                    VTY_NEWLINE); -      return 0; -    } +	if (suppress < reuse) { +		vty_out(vty, +			"Suppress value cannot be less than reuse value %s", +			VTY_NEWLINE); +		return 0; +	} -  return bgp_damp_enable (bgp, bgp_node_afi (vty), bgp_node_safi (vty), -			  half, reuse, suppress, max); +	return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half, +			       reuse, suppress, max);  }  DEFUN (bgp_damp_unset, @@ -10216,110 +10384,106 @@ DEFUN (bgp_damp_unset,         "Value to start suppressing a route\n"         "Maximum duration to suppress a stable route\n")  { -  VTY_DECLVAR_CONTEXT(bgp, bgp); -  return bgp_damp_disable (bgp, bgp_node_afi (vty), bgp_node_safi (vty)); +	VTY_DECLVAR_CONTEXT(bgp, bgp); +	return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));  }  /* Display specified route of BGP table. */ -static int -bgp_clear_damp_route (struct vty *vty, const char *view_name,  -                      const char *ip_str, afi_t afi, safi_t safi,  -                      struct prefix_rd *prd, int prefix_check) -{ -  int ret; -  struct prefix match; -  struct bgp_node *rn; -  struct bgp_node *rm; -  struct bgp_info *ri; -  struct bgp_info *ri_temp; -  struct bgp *bgp; -  struct bgp_table *table; - -  /* BGP structure lookup. */ -  if (view_name) -    { -      bgp = bgp_lookup_by_name (view_name); -      if (bgp == NULL) -	{ -	  vty_out (vty, "%% Can't find BGP instance %s%s", view_name, VTY_NEWLINE); -	  return CMD_WARNING; -	} -    } -  else -    { -      bgp = bgp_get_default (); -      if (bgp == NULL) -	{ -	  vty_out (vty, "%% No BGP process is configured%s", VTY_NEWLINE); -	  return CMD_WARNING; +static int bgp_clear_damp_route(struct vty *vty, const char *view_name, +				const char *ip_str, afi_t afi, safi_t safi, +				struct prefix_rd *prd, int prefix_check) +{ +	int ret; +	struct prefix match; +	struct bgp_node *rn; +	struct bgp_node *rm; +	struct bgp_info *ri; +	struct bgp_info *ri_temp; +	struct bgp *bgp; +	struct bgp_table *table; + +	/* BGP structure lookup. */ +	if (view_name) { +		bgp = bgp_lookup_by_name(view_name); +		if (bgp == NULL) { +			vty_out(vty, "%% Can't find BGP instance %s%s", +				view_name, VTY_NEWLINE); +			return CMD_WARNING; +		} +	} else { +		bgp = bgp_get_default(); +		if (bgp == NULL) { +			vty_out(vty, "%% No BGP process is configured%s", +				VTY_NEWLINE); +			return CMD_WARNING; +		}  	} -    } - -  /* Check IP address argument. */ -  ret = str2prefix (ip_str, &match); -  if (! ret) -    { -      vty_out (vty, "%% address is malformed%s", VTY_NEWLINE); -      return CMD_WARNING; -    } -  match.family = afi2family (afi); +	/* Check IP address argument. */ +	ret = str2prefix(ip_str, &match); +	if (!ret) { +		vty_out(vty, "%% address is malformed%s", VTY_NEWLINE); +		return CMD_WARNING; +	} -  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN)) -    { -      for (rn = bgp_table_top (bgp->rib[AFI_IP][safi]); rn; rn = bgp_route_next (rn)) -        { -          if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0) -            continue; - -	  if ((table = rn->info) != NULL) -	    if ((rm = bgp_node_match (table, &match)) != NULL) -              { -                if (! prefix_check || rm->p.prefixlen == match.prefixlen) -                  { -                    ri = rm->info; -                    while (ri) -                      { -                        if (ri->extra && ri->extra->damp_info) -                          { -                            ri_temp = ri->next; -                            bgp_damp_info_free (ri->extra->damp_info, 1); -                            ri = ri_temp; -                          } -                        else -                          ri = ri->next; -                      } -                  } - -                bgp_unlock_node (rm); -              } -        } -    } -  else -    { -      if ((rn = bgp_node_match (bgp->rib[afi][safi], &match)) != NULL) -        { -          if (! prefix_check || rn->p.prefixlen == match.prefixlen) -            { -              ri = rn->info; -              while (ri) -                { -                  if (ri->extra && ri->extra->damp_info) -                    { -                      ri_temp = ri->next; -                      bgp_damp_info_free (ri->extra->damp_info, 1); -                      ri = ri_temp; -                    } -                  else -                    ri = ri->next; -                } -            } - -          bgp_unlock_node (rn); -        } -    } +	match.family = afi2family(afi); + +	if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) +	    || (safi == SAFI_EVPN)) { +		for (rn = bgp_table_top(bgp->rib[AFI_IP][safi]); rn; +		     rn = bgp_route_next(rn)) { +			if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0) +				continue; + +			if ((table = rn->info) != NULL) +				if ((rm = bgp_node_match(table, &match)) +				    != NULL) { +					if (!prefix_check +					    || rm->p.prefixlen +						       == match.prefixlen) { +						ri = rm->info; +						while (ri) { +							if (ri->extra +							    && ri->extra +								       ->damp_info) { +								ri_temp = +									ri->next; +								bgp_damp_info_free( +									ri->extra +										->damp_info, +									1); +								ri = ri_temp; +							} else +								ri = ri->next; +						} +					} + +					bgp_unlock_node(rm); +				} +		} +	} else { +		if ((rn = bgp_node_match(bgp->rib[afi][safi], &match)) +		    != NULL) { +			if (!prefix_check +			    || rn->p.prefixlen == match.prefixlen) { +				ri = rn->info; +				while (ri) { +					if (ri->extra && ri->extra->damp_info) { +						ri_temp = ri->next; +						bgp_damp_info_free( +							ri->extra->damp_info, +							1); +						ri = ri_temp; +					} else +						ri = ri->next; +				} +			} + +			bgp_unlock_node(rn); +		} +	} -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (clear_ip_bgp_dampening, @@ -10330,8 +10494,8 @@ DEFUN (clear_ip_bgp_dampening,         BGP_STR         "Clear route flap dampening information\n")  { -  bgp_damp_info_clean (); -  return CMD_SUCCESS; +	bgp_damp_info_clean(); +	return CMD_SUCCESS;  }  DEFUN (clear_ip_bgp_dampening_prefix, @@ -10343,9 +10507,9 @@ DEFUN (clear_ip_bgp_dampening_prefix,         "Clear route flap dampening information\n"         "IPv4 prefix\n")  { -  int idx_ipv4_prefixlen = 4; -  return bgp_clear_damp_route (vty, NULL, argv[idx_ipv4_prefixlen]->arg, AFI_IP, -			       SAFI_UNICAST, NULL, 1); +	int idx_ipv4_prefixlen = 4; +	return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg, +				    AFI_IP, SAFI_UNICAST, NULL, 1);  }  DEFUN (clear_ip_bgp_dampening_address, @@ -10357,9 +10521,9 @@ DEFUN (clear_ip_bgp_dampening_address,         "Clear route flap dampening information\n"         "Network to clear damping information\n")  { -  int idx_ipv4 = 4; -  return bgp_clear_damp_route (vty, NULL, argv[idx_ipv4]->arg, AFI_IP, -			       SAFI_UNICAST, NULL, 0); +	int idx_ipv4 = 4; +	return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP, +				    SAFI_UNICAST, NULL, 0);  }  DEFUN (clear_ip_bgp_dampening_address_mask, @@ -10372,425 +10536,455 @@ DEFUN (clear_ip_bgp_dampening_address_mask,         "Network to clear damping information\n"         "Network mask\n")  { -  int idx_ipv4 = 4; -  int idx_ipv4_2 = 5; -  int ret; -  char prefix_str[BUFSIZ]; +	int idx_ipv4 = 4; +	int idx_ipv4_2 = 5; +	int ret; +	char prefix_str[BUFSIZ]; -  ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, prefix_str); -  if (! ret) -    { -      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +	ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, +				     prefix_str); +	if (!ret) { +		vty_out(vty, "%% Inconsistent address and mask%s", VTY_NEWLINE); +		return CMD_WARNING; +	} -  return bgp_clear_damp_route (vty, NULL, prefix_str, AFI_IP, -			       SAFI_UNICAST, NULL, 0); +	return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST, +				    NULL, 0);  }  /* also used for encap safi */ -static int -bgp_config_write_network_vpn (struct vty *vty, struct bgp *bgp, -				afi_t afi, safi_t safi, int *write) -{ -  struct bgp_node *prn; -  struct bgp_node *rn; -  struct bgp_table *table; -  struct prefix *p; -  struct prefix_rd *prd; -  struct bgp_static *bgp_static; -  u_int32_t label; -  char buf[SU_ADDRSTRLEN]; -  char rdbuf[RD_ADDRSTRLEN]; -   -  /* Network configuration. */ -  for (prn = bgp_table_top (bgp->route[afi][safi]); prn; prn = bgp_route_next (prn)) -    if ((table = prn->info) != NULL) -      for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))  -	if ((bgp_static = rn->info) != NULL) -	  { -	    p = &rn->p; -	    prd = (struct prefix_rd *) &prn->p; - -	    /* "address-family" display.  */ -	    bgp_config_write_family_header (vty, afi, safi, write); - -	    /* "network" configuration display.  */ -	    prefix_rd2str (prd, rdbuf, RD_ADDRSTRLEN); -	    label = decode_label (bgp_static->tag); - -	    vty_out (vty, "  network %s/%d rd %s", -		     inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),  -		     p->prefixlen, rdbuf); -	    if (safi == SAFI_MPLS_VPN) -	      vty_out (vty, " label %u", label); - -            if (bgp_static->rmap.name) -              vty_out (vty, " route-map %s", bgp_static->rmap.name); -            else -              { -                if (bgp_static->backdoor) -                  vty_out (vty, " backdoor"); -              } -	    vty_out (vty, "%s", VTY_NEWLINE); -	  } -  return 0; -} - -static int -bgp_config_write_network_evpn (struct vty *vty, struct bgp *bgp, -                               afi_t afi, safi_t safi, int *write) -{ -  struct bgp_node *prn; -  struct bgp_node *rn; -  struct bgp_table *table; -  struct prefix *p; -  struct prefix_rd *prd; -  struct bgp_static *bgp_static; -  char buf[PREFIX_STRLEN]; -  char buf2[SU_ADDRSTRLEN]; -  char rdbuf[RD_ADDRSTRLEN]; - -  /* Network configuration. */ -  for (prn = bgp_table_top (bgp->route[afi][safi]); prn; prn = bgp_route_next (prn)) -    if ((table = prn->info) != NULL) -      for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))  -	if ((bgp_static = rn->info) != NULL) -	  { -            char *macrouter = NULL; -            char *esi = NULL; - -            if(bgp_static->router_mac) -              macrouter = prefix_mac2str(bgp_static->router_mac, NULL, 0); -            if(bgp_static->eth_s_id) -              esi = esi2str(bgp_static->eth_s_id); -	    p = &rn->p; -	    prd = (struct prefix_rd *) &prn->p; - -	    /* "address-family" display.  */ -	    bgp_config_write_family_header (vty, afi, safi, write); - -	    /* "network" configuration display.  */ -	    prefix_rd2str (prd, rdbuf, RD_ADDRSTRLEN); - -            inet_ntop (AF_INET, &bgp_static->igpnexthop, buf2, SU_ADDRSTRLEN); - -            prefix2str (p, buf, sizeof (buf)), -	    vty_out (vty, " network %s rd %s ethtag %u tag %u esi %s gwip %s routermac %s", -		     buf, rdbuf, p->u.prefix_evpn.eth_tag, -                     decode_label (bgp_static->tag), esi, buf2 , macrouter); -	    vty_out (vty, "%s", VTY_NEWLINE); -            if (macrouter) -              XFREE (MTYPE_TMP, macrouter); -            if (esi) -              XFREE (MTYPE_TMP, esi); -	  } -  return 0; +static int bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp, +					afi_t afi, safi_t safi, int *write) +{ +	struct bgp_node *prn; +	struct bgp_node *rn; +	struct bgp_table *table; +	struct prefix *p; +	struct prefix_rd *prd; +	struct bgp_static *bgp_static; +	u_int32_t label; +	char buf[SU_ADDRSTRLEN]; +	char rdbuf[RD_ADDRSTRLEN]; + +	/* Network configuration. */ +	for (prn = bgp_table_top(bgp->route[afi][safi]); prn; +	     prn = bgp_route_next(prn)) +		if ((table = prn->info) != NULL) +			for (rn = bgp_table_top(table); rn; +			     rn = bgp_route_next(rn)) +				if ((bgp_static = rn->info) != NULL) { +					p = &rn->p; +					prd = (struct prefix_rd *)&prn->p; + +					/* "address-family" display.  */ +					bgp_config_write_family_header( +						vty, afi, safi, write); + +					/* "network" configuration display.  */ +					prefix_rd2str(prd, rdbuf, +						      RD_ADDRSTRLEN); +					label = decode_label(bgp_static->tag); + +					vty_out(vty, "  network %s/%d rd %s", +						inet_ntop(p->family, +							  &p->u.prefix, buf, +							  SU_ADDRSTRLEN), +						p->prefixlen, rdbuf); +					if (safi == SAFI_MPLS_VPN) +						vty_out(vty, " label %u", +							label); + +					if (bgp_static->rmap.name) +						vty_out(vty, " route-map %s", +							bgp_static->rmap.name); +					else { +						if (bgp_static->backdoor) +							vty_out(vty, +								" backdoor"); +					} +					vty_out(vty, "%s", VTY_NEWLINE); +				} +	return 0; +} + +static int bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp, +					 afi_t afi, safi_t safi, int *write) +{ +	struct bgp_node *prn; +	struct bgp_node *rn; +	struct bgp_table *table; +	struct prefix *p; +	struct prefix_rd *prd; +	struct bgp_static *bgp_static; +	char buf[PREFIX_STRLEN]; +	char buf2[SU_ADDRSTRLEN]; +	char rdbuf[RD_ADDRSTRLEN]; + +	/* Network configuration. */ +	for (prn = bgp_table_top(bgp->route[afi][safi]); prn; +	     prn = bgp_route_next(prn)) +		if ((table = prn->info) != NULL) +			for (rn = bgp_table_top(table); rn; +			     rn = bgp_route_next(rn)) +				if ((bgp_static = rn->info) != NULL) { +					char *macrouter = NULL; +					char *esi = NULL; + +					if (bgp_static->router_mac) +						macrouter = prefix_mac2str( +							bgp_static->router_mac, +							NULL, 0); +					if (bgp_static->eth_s_id) +						esi = esi2str( +							bgp_static->eth_s_id); +					p = &rn->p; +					prd = (struct prefix_rd *)&prn->p; + +					/* "address-family" display.  */ +					bgp_config_write_family_header( +						vty, afi, safi, write); + +					/* "network" configuration display.  */ +					prefix_rd2str(prd, rdbuf, +						      RD_ADDRSTRLEN); + +					inet_ntop(AF_INET, +						  &bgp_static->igpnexthop, buf2, +						  SU_ADDRSTRLEN); + +					prefix2str(p, buf, sizeof(buf)), +						vty_out(vty, +							" network %s rd %s ethtag %u tag %u esi %s gwip %s routermac %s", +							buf, rdbuf, +							p->u.prefix_evpn +								.eth_tag, +							decode_label( +								bgp_static +									->tag), +							esi, buf2, macrouter); +					vty_out(vty, "%s", VTY_NEWLINE); +					if (macrouter) +						XFREE(MTYPE_TMP, macrouter); +					if (esi) +						XFREE(MTYPE_TMP, esi); +				} +	return 0;  }  /* Configuration of static route announcement and aggregate     information. */ -int -bgp_config_write_network (struct vty *vty, struct bgp *bgp, -			  afi_t afi, safi_t safi, int *write) -{ -  struct bgp_node *rn; -  struct prefix *p; -  struct bgp_static *bgp_static; -  struct bgp_aggregate *bgp_aggregate; -  char buf[SU_ADDRSTRLEN]; -   -  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) -    return bgp_config_write_network_vpn (vty, bgp, afi, safi, write); - -  if (afi == AFI_L2VPN && safi == SAFI_EVPN) -    return bgp_config_write_network_evpn (vty, bgp, afi, safi, write); - -  /* Network configuration. */ -  for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn))  -    if ((bgp_static = rn->info) != NULL) -      { -	p = &rn->p; - -	/* "address-family" display.  */ -	bgp_config_write_family_header (vty, afi, safi, write); - -	/* "network" configuration display.  */ -	if (bgp_option_check (BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) -	  { -	    u_int32_t destination;  -	    struct in_addr netmask; - -	    destination = ntohl (p->u.prefix4.s_addr); -	    masklen2ip (p->prefixlen, &netmask); -	    vty_out (vty, "  network %s", -		     inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN)); - -	    if ((IN_CLASSC (destination) && p->prefixlen == 24) -		|| (IN_CLASSB (destination) && p->prefixlen == 16) -		|| (IN_CLASSA (destination) && p->prefixlen == 8) -		|| p->u.prefix4.s_addr == 0) -	      { -		/* Natural mask is not display. */ -	      } -	    else -	      vty_out (vty, " mask %s", inet_ntoa (netmask)); -	  } -	else -	  { -	    vty_out (vty, "  network %s/%d", -		     inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),  -		     p->prefixlen); -	  } - -	if (bgp_static->rmap.name) -	  vty_out (vty, " route-map %s", bgp_static->rmap.name); -	else  -	  { -	    if (bgp_static->backdoor) -	      vty_out (vty, " backdoor"); -          } - -	vty_out (vty, "%s", VTY_NEWLINE); -      } - -  /* Aggregate-address configuration. */ -  for (rn = bgp_table_top (bgp->aggregate[afi][safi]); rn; rn = bgp_route_next (rn)) -    if ((bgp_aggregate = rn->info) != NULL) -      { -	p = &rn->p; - -	/* "address-family" display.  */ -	bgp_config_write_family_header (vty, afi, safi, write); +int bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi, +			     safi_t safi, int *write) +{ +	struct bgp_node *rn; +	struct prefix *p; +	struct bgp_static *bgp_static; +	struct bgp_aggregate *bgp_aggregate; +	char buf[SU_ADDRSTRLEN]; + +	if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) +		return bgp_config_write_network_vpn(vty, bgp, afi, safi, write); + +	if (afi == AFI_L2VPN && safi == SAFI_EVPN) +		return bgp_config_write_network_evpn(vty, bgp, afi, safi, +						     write); + +	/* Network configuration. */ +	for (rn = bgp_table_top(bgp->route[afi][safi]); rn; +	     rn = bgp_route_next(rn)) +		if ((bgp_static = rn->info) != NULL) { +			p = &rn->p; + +			/* "address-family" display.  */ +			bgp_config_write_family_header(vty, afi, safi, write); + +			/* "network" configuration display.  */ +			if (bgp_option_check(BGP_OPT_CONFIG_CISCO) +			    && afi == AFI_IP) { +				u_int32_t destination; +				struct in_addr netmask; + +				destination = ntohl(p->u.prefix4.s_addr); +				masklen2ip(p->prefixlen, &netmask); +				vty_out(vty, "  network %s", +					inet_ntop(p->family, &p->u.prefix, buf, +						  SU_ADDRSTRLEN)); + +				if ((IN_CLASSC(destination) +				     && p->prefixlen == 24) +				    || (IN_CLASSB(destination) +					&& p->prefixlen == 16) +				    || (IN_CLASSA(destination) +					&& p->prefixlen == 8) +				    || p->u.prefix4.s_addr == 0) { +					/* Natural mask is not display. */ +				} else +					vty_out(vty, " mask %s", +						inet_ntoa(netmask)); +			} else { +				vty_out(vty, "  network %s/%d", +					inet_ntop(p->family, &p->u.prefix, buf, +						  SU_ADDRSTRLEN), +					p->prefixlen); +			} + +			if (bgp_static->rmap.name) +				vty_out(vty, " route-map %s", +					bgp_static->rmap.name); +			else { +				if (bgp_static->backdoor) +					vty_out(vty, " backdoor"); +			} + +			vty_out(vty, "%s", VTY_NEWLINE); +		} -	if (bgp_option_check (BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) -	  { -	    struct in_addr netmask; +	/* Aggregate-address configuration. */ +	for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn; +	     rn = bgp_route_next(rn)) +		if ((bgp_aggregate = rn->info) != NULL) { +			p = &rn->p; + +			/* "address-family" display.  */ +			bgp_config_write_family_header(vty, afi, safi, write); + +			if (bgp_option_check(BGP_OPT_CONFIG_CISCO) +			    && afi == AFI_IP) { +				struct in_addr netmask; + +				masklen2ip(p->prefixlen, &netmask); +				vty_out(vty, "  aggregate-address %s %s", +					inet_ntop(p->family, &p->u.prefix, buf, +						  SU_ADDRSTRLEN), +					inet_ntoa(netmask)); +			} else { +				vty_out(vty, "  aggregate-address %s/%d", +					inet_ntop(p->family, &p->u.prefix, buf, +						  SU_ADDRSTRLEN), +					p->prefixlen); +			} + +			if (bgp_aggregate->as_set) +				vty_out(vty, " as-set"); + +			if (bgp_aggregate->summary_only) +				vty_out(vty, " summary-only"); + +			vty_out(vty, "%s", VTY_NEWLINE); +		} -	    masklen2ip (p->prefixlen, &netmask); -	    vty_out (vty, "  aggregate-address %s %s", -		     inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), -		     inet_ntoa (netmask)); -	  } -	else -	  { -	    vty_out (vty, "  aggregate-address %s/%d", -		     inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), -		     p->prefixlen); -	  } - -	if (bgp_aggregate->as_set) -	  vty_out (vty, " as-set"); -	 -	if (bgp_aggregate->summary_only) -	  vty_out (vty, " summary-only"); - -	vty_out (vty, "%s", VTY_NEWLINE); -      } - -  return 0; -} - -int -bgp_config_write_distance (struct vty *vty, struct bgp *bgp, afi_t afi, -			   safi_t safi, int *write) -{ -  struct bgp_node *rn; -  struct bgp_distance *bdistance; - -  /* Distance configuration. */ -  if (bgp->distance_ebgp[afi][safi] -      && bgp->distance_ibgp[afi][safi] -      && bgp->distance_local[afi][safi] -      && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT -	  || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT -	  || bgp->distance_local[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT)) -    { -      bgp_config_write_family_header (vty, afi, safi, write); -      vty_out (vty, "  distance bgp %d %d %d%s", -	       bgp->distance_ebgp[afi][safi], bgp->distance_ibgp[afi][safi], -	       bgp->distance_local[afi][safi], VTY_NEWLINE); -    } +	return 0; +} -  for (rn = bgp_table_top (bgp_distance_table[afi][safi]); rn; -       rn = bgp_route_next (rn)) -    if ((bdistance = rn->info) != NULL) -      { -	char buf[PREFIX_STRLEN]; +int bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi, +			      safi_t safi, int *write) +{ +	struct bgp_node *rn; +	struct bgp_distance *bdistance; + +	/* Distance configuration. */ +	if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi] +	    && bgp->distance_local[afi][safi] +	    && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT +		|| bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT +		|| bgp->distance_local[afi][safi] +			   != ZEBRA_IBGP_DISTANCE_DEFAULT)) { +		bgp_config_write_family_header(vty, afi, safi, write); +		vty_out(vty, "  distance bgp %d %d %d%s", +			bgp->distance_ebgp[afi][safi], +			bgp->distance_ibgp[afi][safi], +			bgp->distance_local[afi][safi], VTY_NEWLINE); +	} -	bgp_config_write_family_header (vty, afi, safi, write); -	vty_out (vty, "  distance %d %s %s%s", bdistance->distance, -		 prefix2str (&rn->p, buf, sizeof (buf)), -		 bdistance->access_list ? bdistance->access_list : "", -		 VTY_NEWLINE); -      } +	for (rn = bgp_table_top(bgp_distance_table[afi][safi]); rn; +	     rn = bgp_route_next(rn)) +		if ((bdistance = rn->info) != NULL) { +			char buf[PREFIX_STRLEN]; + +			bgp_config_write_family_header(vty, afi, safi, write); +			vty_out(vty, "  distance %d %s %s%s", +				bdistance->distance, +				prefix2str(&rn->p, buf, sizeof(buf)), +				bdistance->access_list ? bdistance->access_list +						       : "", +				VTY_NEWLINE); +		} -  return *write; +	return *write;  }  /* Allocate routing table structure and install commands. */ -void -bgp_route_init (void) -{ -  afi_t afi; -  safi_t safi; - -  /* Init BGP distance table. */ -  for (afi = AFI_IP; afi < AFI_MAX; afi++) -    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) -      bgp_distance_table[afi][safi] = bgp_table_init (afi, safi); - -  /* IPv4 BGP commands. */ -  install_element (BGP_NODE, &bgp_table_map_cmd); -  install_element (BGP_NODE, &bgp_network_cmd); -  install_element (BGP_NODE, &bgp_network_mask_cmd); -  install_element (BGP_NODE, &bgp_network_mask_natural_cmd); -  install_element (BGP_NODE, &bgp_network_route_map_cmd); -  install_element (BGP_NODE, &bgp_network_mask_route_map_cmd); -  install_element (BGP_NODE, &bgp_network_mask_natural_route_map_cmd); -  install_element (BGP_NODE, &bgp_network_backdoor_cmd); -  install_element (BGP_NODE, &bgp_network_mask_backdoor_cmd); -  install_element (BGP_NODE, &bgp_network_mask_natural_backdoor_cmd); -  install_element (BGP_NODE, &no_bgp_table_map_cmd); -  install_element (BGP_NODE, &no_bgp_network_cmd); -  install_element (BGP_NODE, &no_bgp_network_mask_cmd); -  install_element (BGP_NODE, &no_bgp_network_mask_natural_cmd); - -  install_element (BGP_NODE, &aggregate_address_cmd); -  install_element (BGP_NODE, &aggregate_address_mask_cmd); -  install_element (BGP_NODE, &no_aggregate_address_cmd); -  install_element (BGP_NODE, &no_aggregate_address_mask_cmd); - -  /* IPv4 unicast configuration.  */ -  install_element (BGP_IPV4_NODE, &bgp_table_map_cmd); -  install_element (BGP_IPV4_NODE, &bgp_network_cmd); -  install_element (BGP_IPV4_NODE, &bgp_network_mask_cmd); -  install_element (BGP_IPV4_NODE, &bgp_network_mask_natural_cmd); -  install_element (BGP_IPV4_NODE, &bgp_network_route_map_cmd); -  install_element (BGP_IPV4_NODE, &bgp_network_mask_route_map_cmd); -  install_element (BGP_IPV4_NODE, &bgp_network_mask_natural_route_map_cmd); -  install_element (BGP_IPV4_NODE, &no_bgp_table_map_cmd); -  install_element (BGP_IPV4_NODE, &no_bgp_network_cmd); -  install_element (BGP_IPV4_NODE, &no_bgp_network_mask_cmd); -  install_element (BGP_IPV4_NODE, &no_bgp_network_mask_natural_cmd); -   -  install_element (BGP_IPV4_NODE, &aggregate_address_cmd); -  install_element (BGP_IPV4_NODE, &aggregate_address_mask_cmd); -  install_element (BGP_IPV4_NODE, &no_aggregate_address_cmd); -  install_element (BGP_IPV4_NODE, &no_aggregate_address_mask_cmd); - -  /* IPv4 multicast configuration.  */ -  install_element (BGP_IPV4M_NODE, &bgp_table_map_cmd); -  install_element (BGP_IPV4M_NODE, &bgp_network_cmd); -  install_element (BGP_IPV4M_NODE, &bgp_network_mask_cmd); -  install_element (BGP_IPV4M_NODE, &bgp_network_mask_natural_cmd); -  install_element (BGP_IPV4M_NODE, &bgp_network_route_map_cmd); -  install_element (BGP_IPV4M_NODE, &bgp_network_mask_route_map_cmd); -  install_element (BGP_IPV4M_NODE, &bgp_network_mask_natural_route_map_cmd); -  install_element (BGP_IPV4M_NODE, &no_bgp_table_map_cmd); -  install_element (BGP_IPV4M_NODE, &no_bgp_network_cmd); -  install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_cmd); -  install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_natural_cmd); -  install_element (BGP_IPV4M_NODE, &aggregate_address_cmd); -  install_element (BGP_IPV4M_NODE, &aggregate_address_mask_cmd); -  install_element (BGP_IPV4M_NODE, &no_aggregate_address_cmd); -  install_element (BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd); - -  install_element (VIEW_NODE, &show_ip_bgp_instance_all_cmd); -  install_element (VIEW_NODE, &show_ip_bgp_cmd); -  install_element (VIEW_NODE, &show_ip_bgp_route_cmd); -  install_element (VIEW_NODE, &show_ip_bgp_regexp_cmd); - -  install_element (VIEW_NODE, &show_ip_bgp_instance_neighbor_advertised_route_cmd); -  install_element (VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd); -  install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd); +void bgp_route_init(void) +{ +	afi_t afi; +	safi_t safi; + +	/* Init BGP distance table. */ +	for (afi = AFI_IP; afi < AFI_MAX; afi++) +		for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) +			bgp_distance_table[afi][safi] = +				bgp_table_init(afi, safi); + +	/* IPv4 BGP commands. */ +	install_element(BGP_NODE, &bgp_table_map_cmd); +	install_element(BGP_NODE, &bgp_network_cmd); +	install_element(BGP_NODE, &bgp_network_mask_cmd); +	install_element(BGP_NODE, &bgp_network_mask_natural_cmd); +	install_element(BGP_NODE, &bgp_network_route_map_cmd); +	install_element(BGP_NODE, &bgp_network_mask_route_map_cmd); +	install_element(BGP_NODE, &bgp_network_mask_natural_route_map_cmd); +	install_element(BGP_NODE, &bgp_network_backdoor_cmd); +	install_element(BGP_NODE, &bgp_network_mask_backdoor_cmd); +	install_element(BGP_NODE, &bgp_network_mask_natural_backdoor_cmd); +	install_element(BGP_NODE, &no_bgp_table_map_cmd); +	install_element(BGP_NODE, &no_bgp_network_cmd); +	install_element(BGP_NODE, &no_bgp_network_mask_cmd); +	install_element(BGP_NODE, &no_bgp_network_mask_natural_cmd); + +	install_element(BGP_NODE, &aggregate_address_cmd); +	install_element(BGP_NODE, &aggregate_address_mask_cmd); +	install_element(BGP_NODE, &no_aggregate_address_cmd); +	install_element(BGP_NODE, &no_aggregate_address_mask_cmd); + +	/* IPv4 unicast configuration.  */ +	install_element(BGP_IPV4_NODE, &bgp_table_map_cmd); +	install_element(BGP_IPV4_NODE, &bgp_network_cmd); +	install_element(BGP_IPV4_NODE, &bgp_network_mask_cmd); +	install_element(BGP_IPV4_NODE, &bgp_network_mask_natural_cmd); +	install_element(BGP_IPV4_NODE, &bgp_network_route_map_cmd); +	install_element(BGP_IPV4_NODE, &bgp_network_mask_route_map_cmd); +	install_element(BGP_IPV4_NODE, &bgp_network_mask_natural_route_map_cmd); +	install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd); +	install_element(BGP_IPV4_NODE, &no_bgp_network_cmd); +	install_element(BGP_IPV4_NODE, &no_bgp_network_mask_cmd); +	install_element(BGP_IPV4_NODE, &no_bgp_network_mask_natural_cmd); + +	install_element(BGP_IPV4_NODE, &aggregate_address_cmd); +	install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd); +	install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd); +	install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd); + +	/* IPv4 multicast configuration.  */ +	install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd); +	install_element(BGP_IPV4M_NODE, &bgp_network_cmd); +	install_element(BGP_IPV4M_NODE, &bgp_network_mask_cmd); +	install_element(BGP_IPV4M_NODE, &bgp_network_mask_natural_cmd); +	install_element(BGP_IPV4M_NODE, &bgp_network_route_map_cmd); +	install_element(BGP_IPV4M_NODE, &bgp_network_mask_route_map_cmd); +	install_element(BGP_IPV4M_NODE, +			&bgp_network_mask_natural_route_map_cmd); +	install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd); +	install_element(BGP_IPV4M_NODE, &no_bgp_network_cmd); +	install_element(BGP_IPV4M_NODE, &no_bgp_network_mask_cmd); +	install_element(BGP_IPV4M_NODE, &no_bgp_network_mask_natural_cmd); +	install_element(BGP_IPV4M_NODE, &aggregate_address_cmd); +	install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd); +	install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd); +	install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd); + +	install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd); +	install_element(VIEW_NODE, &show_ip_bgp_cmd); +	install_element(VIEW_NODE, &show_ip_bgp_route_cmd); +	install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd); + +	install_element(VIEW_NODE, +			&show_ip_bgp_instance_neighbor_advertised_route_cmd); +	install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd); +	install_element(VIEW_NODE, +			&show_ip_bgp_neighbor_received_prefix_filter_cmd);  #ifdef KEEP_OLD_VPN_COMMANDS -  install_element (VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd); +	install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);  #endif /* KEEP_OLD_VPN_COMMANDS */ -  install_element (VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd); -  install_element (VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd); -   - /* BGP dampening clear commands */ -  install_element (ENABLE_NODE, &clear_ip_bgp_dampening_cmd); -  install_element (ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd); +	install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd); +	install_element(VIEW_NODE, +			&show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd); + +	/* BGP dampening clear commands */ +	install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd); +	install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd); -  install_element (ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd); -  install_element (ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd); +	install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd); +	install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd); -  /* prefix count */ -  install_element (ENABLE_NODE, &show_ip_bgp_instance_neighbor_prefix_counts_cmd); +	/* prefix count */ +	install_element(ENABLE_NODE, +			&show_ip_bgp_instance_neighbor_prefix_counts_cmd);  #ifdef KEEP_OLD_VPN_COMMANDS -  install_element (ENABLE_NODE, &show_ip_bgp_vpn_neighbor_prefix_counts_cmd); +	install_element(ENABLE_NODE, +			&show_ip_bgp_vpn_neighbor_prefix_counts_cmd);  #endif /* KEEP_OLD_VPN_COMMANDS */ -  /* New config IPv6 BGP commands.  */ -  install_element (BGP_IPV6_NODE, &bgp_table_map_cmd); -  install_element (BGP_IPV6_NODE, &ipv6_bgp_network_cmd); -  install_element (BGP_IPV6_NODE, &ipv6_bgp_network_route_map_cmd); -  install_element (BGP_IPV6_NODE, &no_bgp_table_map_cmd); -  install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_cmd); - -  install_element (BGP_IPV6_NODE, &ipv6_aggregate_address_cmd); -  install_element (BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd); - -  install_element (BGP_IPV6M_NODE, &ipv6_bgp_network_cmd); -  install_element (BGP_IPV6M_NODE, &no_ipv6_bgp_network_cmd); - -  install_element (BGP_NODE, &bgp_distance_cmd); -  install_element (BGP_NODE, &no_bgp_distance_cmd); -  install_element (BGP_NODE, &bgp_distance_source_cmd); -  install_element (BGP_NODE, &no_bgp_distance_source_cmd); -  install_element (BGP_NODE, &bgp_distance_source_access_list_cmd); -  install_element (BGP_NODE, &no_bgp_distance_source_access_list_cmd); -  install_element (BGP_IPV4_NODE, &bgp_distance_cmd); -  install_element (BGP_IPV4_NODE, &no_bgp_distance_cmd); -  install_element (BGP_IPV4_NODE, &bgp_distance_source_cmd); -  install_element (BGP_IPV4_NODE, &no_bgp_distance_source_cmd); -  install_element (BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd); -  install_element (BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd); -  install_element (BGP_IPV4M_NODE, &bgp_distance_cmd); -  install_element (BGP_IPV4M_NODE, &no_bgp_distance_cmd); -  install_element (BGP_IPV4M_NODE, &bgp_distance_source_cmd); -  install_element (BGP_IPV4M_NODE, &no_bgp_distance_source_cmd); -  install_element (BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd); -  install_element (BGP_IPV4M_NODE, &no_bgp_distance_source_access_list_cmd); -  install_element (BGP_IPV6_NODE, &bgp_distance_cmd); -  install_element (BGP_IPV6_NODE, &no_bgp_distance_cmd); -  install_element (BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd); -  install_element (BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd); -  install_element (BGP_IPV6_NODE, &ipv6_bgp_distance_source_access_list_cmd); -  install_element (BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_access_list_cmd); -  install_element (BGP_IPV6M_NODE, &bgp_distance_cmd); -  install_element (BGP_IPV6M_NODE, &no_bgp_distance_cmd); -  install_element (BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd); -  install_element (BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd); -  install_element (BGP_IPV6M_NODE, &ipv6_bgp_distance_source_access_list_cmd); -  install_element (BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_access_list_cmd); - -  install_element (BGP_NODE, &bgp_damp_set_cmd); -  install_element (BGP_NODE, &bgp_damp_unset_cmd); -  install_element (BGP_IPV4_NODE, &bgp_damp_set_cmd); -  install_element (BGP_IPV4_NODE, &bgp_damp_unset_cmd); - -  /* IPv4 Multicast Mode */ -  install_element (BGP_IPV4M_NODE, &bgp_damp_set_cmd); -  install_element (BGP_IPV4M_NODE, &bgp_damp_unset_cmd); - -  /* Large Communities */ -  install_element (VIEW_NODE, &show_ip_bgp_large_community_list_cmd); -  install_element (VIEW_NODE, &show_ip_bgp_large_community_cmd); -} - -void -bgp_route_finish (void) -{ -  afi_t afi; -  safi_t safi; - -  for (afi = AFI_IP; afi < AFI_MAX; afi++) -    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) -      { -	bgp_table_unlock (bgp_distance_table[afi][safi]); -	bgp_distance_table[afi][safi] = NULL; -      } +	/* New config IPv6 BGP commands.  */ +	install_element(BGP_IPV6_NODE, &bgp_table_map_cmd); +	install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd); +	install_element(BGP_IPV6_NODE, &ipv6_bgp_network_route_map_cmd); +	install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd); +	install_element(BGP_IPV6_NODE, &no_ipv6_bgp_network_cmd); + +	install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd); +	install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd); + +	install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd); +	install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_network_cmd); + +	install_element(BGP_NODE, &bgp_distance_cmd); +	install_element(BGP_NODE, &no_bgp_distance_cmd); +	install_element(BGP_NODE, &bgp_distance_source_cmd); +	install_element(BGP_NODE, &no_bgp_distance_source_cmd); +	install_element(BGP_NODE, &bgp_distance_source_access_list_cmd); +	install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd); +	install_element(BGP_IPV4_NODE, &bgp_distance_cmd); +	install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd); +	install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd); +	install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd); +	install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd); +	install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd); +	install_element(BGP_IPV4M_NODE, &bgp_distance_cmd); +	install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd); +	install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd); +	install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd); +	install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd); +	install_element(BGP_IPV4M_NODE, +			&no_bgp_distance_source_access_list_cmd); +	install_element(BGP_IPV6_NODE, &bgp_distance_cmd); +	install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd); +	install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd); +	install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd); +	install_element(BGP_IPV6_NODE, +			&ipv6_bgp_distance_source_access_list_cmd); +	install_element(BGP_IPV6_NODE, +			&no_ipv6_bgp_distance_source_access_list_cmd); +	install_element(BGP_IPV6M_NODE, &bgp_distance_cmd); +	install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd); +	install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd); +	install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd); +	install_element(BGP_IPV6M_NODE, +			&ipv6_bgp_distance_source_access_list_cmd); +	install_element(BGP_IPV6M_NODE, +			&no_ipv6_bgp_distance_source_access_list_cmd); + +	install_element(BGP_NODE, &bgp_damp_set_cmd); +	install_element(BGP_NODE, &bgp_damp_unset_cmd); +	install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd); +	install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd); + +	/* IPv4 Multicast Mode */ +	install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd); +	install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd); + +	/* Large Communities */ +	install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd); +	install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd); +} + +void bgp_route_finish(void) +{ +	afi_t afi; +	safi_t safi; + +	for (afi = AFI_IP; afi < AFI_MAX; afi++) +		for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { +			bgp_table_unlock(bgp_distance_table[afi][safi]); +			bgp_distance_table[afi][safi] = NULL; +		}  }  | 
