From 04e1c5bb4a8a09d7a3bfaf0e4deb3955fa4f7fe0 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Mon, 7 May 2018 13:25:10 -0400 Subject: [PATCH] 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 --- bgpd/bgpd.c | 116 +++++++++++++++++++++++++++++++--------------------- bgpd/bgpd.h | 23 ++++++++++- 2 files changed, 92 insertions(+), 47 deletions(-) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index a331fad5d4..32a1ea5a5f 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -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)) + /* 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; } diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 470fd10850..d9ce77a55a 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -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. */ -- 2.39.5