]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #2179 from qlyoung/fix-maximum-prefix-override
authorRuss White <russ@riw.us>
Wed, 9 May 2018 00:07:32 +0000 (20:07 -0400)
committerGitHub <noreply@github.com>
Wed, 9 May 2018 00:07:32 +0000 (20:07 -0400)
bgpd: fix maximum-prefix + peer-group

bgpd/bgpd.c
bgpd/bgpd.h

index a331fad5d4a242397050bf1438a2c3df959745d8..32a1ea5a5fe7ef7c8cb64717862a3650ef1cf670 100644 (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))
+       /* 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;
 }
index 470fd108501f6ce1d79fc254b6633814439709e7..d9ce77a55accbaa90ad48bb3b09156c9782a07bd 100644 (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. */