bgpd: fix maximum-prefix + peer-group

Attribute set on peer was being overridden when set on the peer-group.

This commit also adds a parallel flags array that indicates whether a
particular flag is sourced from the peer-group or is peer-specific. It
assumes the default state of all flags is unset. This looks to be true
except in the case of PEER_FLAG_SEND_COMMUNITY,
PEER_FLAG_SEND_EXT_COMMUNITY, and PEER_FLAG_SEND_LARGE_COMMUNITY; these
flags are set by default except when the user specifies to use
config-type = cisco. However the flag field can merely be flipped to
mean the negation of those options in a future commit.

Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
This commit is contained in:
Quentin Young 2018-05-07 13:25:10 -04:00
parent e8f95403e4
commit 04e1c5bb4a
2 changed files with 93 additions and 48 deletions

View File

@ -5947,39 +5947,63 @@ int peer_maximum_prefix_set(struct peer *peer, afi_t afi, safi_t safi,
struct peer_group *group;
struct listnode *node, *nnode;
/* apply configuration and set flags */
SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
peer->pmax[afi][safi] = max;
peer->pmax_threshold[afi][safi] = threshold;
peer->pmax_restart[afi][safi] = restart;
if (warning)
SET_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_MAX_PREFIX_WARNING);
else
UNSET_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_MAX_PREFIX_WARNING);
peer->pmax[afi][safi] = max;
peer->pmax_threshold[afi][safi] = threshold;
peer->pmax_restart[afi][safi] = restart;
/* if handling a peer-group, apply to all children */
if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
group = peer->group;
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
SET_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_MAX_PREFIX);
peer->pmax[afi][safi] = max;
peer->pmax_threshold[afi][safi] = threshold;
peer->pmax_restart[afi][safi] = restart;
if (warning)
/*
* If peer configuration is user-set, it overrides
* peer-group config.
*/
if (!CHECK_FLAG(peer->af_flags_override[afi][safi],
PEER_FLAG_MAX_PREFIX)) {
SET_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_MAX_PREFIX_WARNING);
else
UNSET_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_MAX_PREFIX_WARNING);
PEER_FLAG_MAX_PREFIX);
peer->pmax[afi][safi] = max;
peer->pmax_threshold[afi][safi] = threshold;
peer->pmax_restart[afi][safi] = restart;
}
if (!CHECK_FLAG(peer->af_flags_override[afi][safi],
PEER_FLAG_MAX_PREFIX_WARNING)) {
if (warning)
SET_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_MAX_PREFIX_WARNING);
else
UNSET_FLAG(
peer->af_flags[afi][safi],
PEER_FLAG_MAX_PREFIX_WARNING);
}
if ((peer->status == Established)
&& (peer->afc[afi][safi]))
bgp_maximum_prefix_overflow(peer, afi, safi, 1);
}
} else {
/* if not handling a peer-group, set the override flags */
if ((peer->status == Established) && (peer->afc[afi][safi]))
bgp_maximum_prefix_overflow(peer, afi, safi, 1);
SET_FLAG(peer->af_flags_override[afi][safi],
PEER_FLAG_MAX_PREFIX);
if (warning)
SET_FLAG(peer->af_flags_override[afi][safi],
PEER_FLAG_MAX_PREFIX_WARNING);
else
UNSET_FLAG(peer->af_flags_override[afi][safi],
PEER_FLAG_MAX_PREFIX_WARNING);
}
return 0;
@ -5990,49 +6014,49 @@ int peer_maximum_prefix_unset(struct peer *peer, afi_t afi, safi_t safi)
struct peer_group *group;
struct listnode *node, *nnode;
/* apply peer-group config */
if (peer_group_active(peer)) {
if (CHECK_FLAG(peer->group->conf->af_flags[afi][safi],
PEER_FLAG_MAX_PREFIX))
SET_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_MAX_PREFIX);
else
UNSET_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_MAX_PREFIX);
if (CHECK_FLAG(peer->group->conf->af_flags[afi][safi],
PEER_FLAG_MAX_PREFIX_WARNING))
SET_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_MAX_PREFIX_WARNING);
else
UNSET_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_MAX_PREFIX_WARNING);
peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
peer->pmax_threshold[afi][safi] =
peer->group->conf->pmax_threshold[afi][safi];
peer->pmax_restart[afi][safi] =
peer->group->conf->pmax_restart[afi][safi];
return 0;
}
UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
peer->pmax[afi][safi] = 0;
peer->pmax_threshold[afi][safi] = 0;
peer->pmax_restart[afi][safi] = 0;
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
return 0;
/* if not handling a peer-group, unset override flags */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
UNSET_FLAG(peer->af_flags_override[afi][safi],
PEER_FLAG_MAX_PREFIX);
UNSET_FLAG(peer->af_flags_override[afi][safi],
PEER_FLAG_MAX_PREFIX_WARNING);
/* if peer is part of a peer-group, apply peer-group config */
if (peer_group_active(peer)) {
peer->pmax[afi][safi] =
peer->group->conf->pmax[afi][safi];
peer->pmax_threshold[afi][safi] =
peer->group->conf->pmax_threshold[afi][safi];
peer->pmax_restart[afi][safi] =
peer->group->conf->pmax_restart[afi][safi];
}
return 0;
}
/*
* If this peer is a peer-group, set all peers in the group unless they
* have overrides for our config.
*/
group = peer->group;
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
UNSET_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_MAX_PREFIX_WARNING);
peer->pmax[afi][safi] = 0;
peer->pmax_threshold[afi][safi] = 0;
peer->pmax_restart[afi][safi] = 0;
if (!CHECK_FLAG(peer->af_flags_override[afi][safi],
PEER_FLAG_MAX_PREFIX_WARNING))
UNSET_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_MAX_PREFIX_WARNING);
if (!CHECK_FLAG(peer->af_flags_override[afi][safi],
PEER_FLAG_MAX_PREFIX)) {
UNSET_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_MAX_PREFIX);
peer->pmax[afi][safi] = 0;
peer->pmax_threshold[afi][safi] = 0;
peer->pmax_restart[afi][safi] = 0;
}
}
return 0;
}

View File

@ -836,7 +836,28 @@ struct peer {
/* NSF mode (graceful restart) */
uint8_t nsf[AFI_MAX][SAFI_MAX];
/* Per AF configuration flags. */
/* Peer Per AF flags */
/*
* Parallel array to af_flags that indicates whether each flag
* originates from a peer-group or if it is config that is specific to
* this individual peer. If a flag is set independent of the
* peer-group the same bit should be set here. If this peer is a
* peer-group, this memory region should be all zeros. The assumption
* is that the default state for all flags is unset.
*
* Notes:
* - if a flag for an individual peer is unset, the corresponding
* override flag is unset and the peer is considered to be back in
* sync with the peer-group.
* - This does *not* contain the flag values, rather it contains
* whether the flag at the same position in af_flags is
* *peer-specific*.
*/
uint32_t af_flags_override[AFI_MAX][SAFI_MAX];
/*
* Effective flags, computed by applying peer-group flags and then
* overriding with individual flags
*/
uint32_t af_flags[AFI_MAX][SAFI_MAX];
#define PEER_FLAG_SEND_COMMUNITY (1 << 0) /* send-community */
#define PEER_FLAG_SEND_EXT_COMMUNITY (1 << 1) /* send-community ext. */