]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #12034 from opensourcerouting/fix/gr_hard_notification
authorRuss White <russ@riw.us>
Thu, 6 Oct 2022 14:05:11 +0000 (10:05 -0400)
committerGitHub <noreply@github.com>
Thu, 6 Oct 2022 14:05:11 +0000 (10:05 -0400)
bgpd: Do not send Deconfig/Shutdown message when restarting

1  2 
bgpd/bgpd.c

diff --combined bgpd/bgpd.c
index 6b56ec21b086ec82de1059293434f65bab10b41d,7840f5e0b88912bcb3a2440a128a1a48f54e9690..5a9ec1bbdc7551c2b9464ff526d86aff234c62b9
@@@ -997,15 -997,9 +997,15 @@@ void peer_af_flag_inherit(struct peer *
  static inline enum bgp_peer_sort peer_calc_sort(struct peer *peer)
  {
        struct bgp *bgp;
 +      as_t local_as;
  
        bgp = peer->bgp;
  
 +      if (peer->change_local_as)
 +              local_as = peer->change_local_as;
 +      else
 +              local_as = peer->local_as;
 +
        /* Peer-group */
        if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
                if (peer->as_type == AS_INTERNAL)
  
                else if (peer->as_type == AS_SPECIFIED && peer->as) {
                        assert(bgp);
 -                      return (bgp->as == peer->as ? BGP_PEER_IBGP
 -                                                  : BGP_PEER_EBGP);
 +                      return (local_as == peer->as ? BGP_PEER_IBGP
 +                                                   : BGP_PEER_EBGP);
                }
  
                else {
  
        /* Normal peer */
        if (bgp && CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
 -              if (peer->local_as == 0)
 +              if (local_as == 0)
                        return BGP_PEER_INTERNAL;
  
 -              if (peer->local_as == peer->as) {
 +              if (local_as == peer->as) {
                        if (bgp->as == bgp->confed_id) {
 -                              if (peer->local_as == bgp->as)
 +                              if (local_as == bgp->as)
                                        return BGP_PEER_IBGP;
                                else
                                        return BGP_PEER_EBGP;
                        } else {
 -                              if (peer->local_as == bgp->confed_id)
 +                              if (local_as == bgp->confed_id)
                                        return BGP_PEER_EBGP;
                                else
                                        return BGP_PEER_IBGP;
                            && (peer->group->conf->as_type != AS_UNSPECIFIED)) {
                                if (peer->group->conf->as_type
                                    == AS_SPECIFIED) {
 -                                      if (peer->local_as
 -                                          == peer->group->conf->as)
 +                                      if (local_as == peer->group->conf->as)
                                                return BGP_PEER_IBGP;
                                        else
                                                return BGP_PEER_EBGP;
                        return (peer->as_type == AS_INTERNAL ? BGP_PEER_IBGP
                                                             : BGP_PEER_EBGP);
  
 -              return (peer->local_as == 0
 -                              ? BGP_PEER_INTERNAL
 -                              : peer->local_as == peer->as ? BGP_PEER_IBGP
 +              return (local_as == 0 ? BGP_PEER_INTERNAL
 +                                    : local_as == peer->as ? BGP_PEER_IBGP
                                                             : BGP_PEER_EBGP);
        }
  }
@@@ -1889,6 -1885,14 +1889,6 @@@ void peer_as_change(struct peer *peer, 
                UNSET_FLAG(peer->af_flags[AFI_L2VPN][SAFI_EVPN],
                           PEER_FLAG_REFLECTOR_CLIENT);
        }
 -
 -      /* local-as reset */
 -      if (newtype != BGP_PEER_EBGP) {
 -              peer->change_local_as = 0;
 -              peer_flag_unset(peer, PEER_FLAG_LOCAL_AS);
 -              peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND);
 -              peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS);
 -      }
  }
  
  /* If peer does not exist, create new one.  If peer already exists,
@@@ -2756,6 -2760,21 +2756,21 @@@ void peer_notify_unconfig(struct peer *
                                BGP_NOTIFY_CEASE_PEER_UNCONFIG);
  }
  
+ static void peer_notify_shutdown(struct peer *peer)
+ {
+       if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)) {
+               if (bgp_debug_neighbor_events(peer))
+                       zlog_debug(
+                               "%pBP configured Graceful-Restart, skipping shutdown notification",
+                               peer);
+               return;
+       }
+       if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
+               bgp_notify_send(peer, BGP_NOTIFY_CEASE,
+                               BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
+ }
  void peer_group_notify_unconfig(struct peer_group *group)
  {
        struct peer *peer, *other;
@@@ -3014,6 -3033,17 +3029,6 @@@ int peer_group_bind(struct bgp *bgp, un
                        /* ebgp-multihop reset */
                        if (gtype == BGP_PEER_IBGP)
                                group->conf->ttl = MAXTTL;
 -
 -                      /* local-as reset */
 -                      if (gtype != BGP_PEER_EBGP) {
 -                              group->conf->change_local_as = 0;
 -                              peer_flag_unset(group->conf,
 -                                              PEER_FLAG_LOCAL_AS);
 -                              peer_flag_unset(group->conf,
 -                                              PEER_FLAG_LOCAL_AS_NO_PREPEND);
 -                              peer_flag_unset(group->conf,
 -                                              PEER_FLAG_LOCAL_AS_REPLACE_AS);
 -                      }
                }
  
                SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
@@@ -3661,11 -3691,8 +3676,8 @@@ int bgp_delete(struct bgp *bgp
        }
  
        /* Inform peers we're going down. */
-       for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) {
-               if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
-                       bgp_notify_send(peer, BGP_NOTIFY_CEASE,
-                                       BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
-       }
+       for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer))
+               peer_notify_shutdown(peer);
  
        /* Delete static routes (networks). */
        bgp_static_delete(bgp);
@@@ -5461,8 -5488,8 +5473,8 @@@ void peer_tcp_mss_unset(struct peer *pe
   * being used by a peer has changed (AF specific). Automatically
   * initiates inbound or outbound processing as needed.
   */
 -static void peer_on_policy_change(struct peer *peer, afi_t afi, safi_t safi,
 -                                int outbound)
 +void peer_on_policy_change(struct peer *peer, afi_t afi, safi_t safi,
 +                         int outbound)
  {
        if (outbound) {
                update_group_adjust_peer(peer_af_find(peer, afi, safi));
@@@ -6094,10 -6121,17 +6106,10 @@@ int peer_local_as_set(struct peer *peer
        struct bgp *bgp = peer->bgp;
        struct peer *member;
        struct listnode *node, *nnode;
 -      enum bgp_peer_sort ptype = peer_sort(peer);
 -
 -      if (ptype != BGP_PEER_EBGP && ptype != BGP_PEER_INTERNAL)
 -              return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
  
        if (bgp->as == as)
                return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
  
 -      if (peer->as == as)
 -              return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
 -
        /* Save previous flag states. */
        old_no_prepend =
                !!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
            && old_replace_as == replace_as)
                return 0;
        peer->change_local_as = as;
 +      (void)peer_sort(peer);
  
        /* Check if handling a regular peer. */
        if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
@@@ -7198,6 -7231,169 +7210,6 @@@ int peer_unsuppress_map_unset(struct pe
        return 0;
  }
  
 -static void peer_advertise_map_filter_update(struct peer *peer, afi_t afi,
 -                                           safi_t safi, const char *amap_name,
 -                                           struct route_map *amap,
 -                                           const char *cmap_name,
 -                                           struct route_map *cmap,
 -                                           bool condition, bool set)
 -{
 -      struct bgp_filter *filter;
 -      bool filter_exists = false;
 -
 -      filter = &peer->filter[afi][safi];
 -
 -      /* advertise-map is already configured. */
 -      if (filter->advmap.aname) {
 -              filter_exists = true;
 -              XFREE(MTYPE_BGP_FILTER_NAME, filter->advmap.aname);
 -              XFREE(MTYPE_BGP_FILTER_NAME, filter->advmap.cname);
 -      }
 -
 -      route_map_counter_decrement(filter->advmap.amap);
 -
 -      /* Removed advertise-map configuration */
 -      if (!set) {
 -              memset(&filter->advmap, 0, sizeof(filter->advmap));
 -
 -              /* decrement condition_filter_count delete timer if
 -               * this is the last advertise-map to be removed.
 -               */
 -              if (filter_exists)
 -                      bgp_conditional_adv_disable(peer, afi, safi);
 -
 -              /* Process peer route updates. */
 -              peer_on_policy_change(peer, afi, safi, 1);
 -
 -              return;
 -      }
 -
 -      /* Update filter data with newly configured values. */
 -      filter->advmap.aname = XSTRDUP(MTYPE_BGP_FILTER_NAME, amap_name);
 -      filter->advmap.cname = XSTRDUP(MTYPE_BGP_FILTER_NAME, cmap_name);
 -      filter->advmap.amap = amap;
 -      filter->advmap.cmap = cmap;
 -      filter->advmap.condition = condition;
 -      route_map_counter_increment(filter->advmap.amap);
 -      peer->advmap_config_change[afi][safi] = true;
 -
 -      /* Increment condition_filter_count and/or create timer. */
 -      if (!filter_exists) {
 -              filter->advmap.update_type = UPDATE_TYPE_ADVERTISE;
 -              bgp_conditional_adv_enable(peer, afi, safi);
 -      }
 -
 -      /* Process peer route updates. */
 -      peer_on_policy_change(peer, afi, safi, 1);
 -}
 -
 -/* Set advertise-map to the peer. */
 -int peer_advertise_map_set(struct peer *peer, afi_t afi, safi_t safi,
 -                         const char *advertise_name,
 -                         struct route_map *advertise_map,
 -                         const char *condition_name,
 -                         struct route_map *condition_map, bool condition)
 -{
 -      struct peer *member;
 -      struct listnode *node, *nnode;
 -
 -      /* Set configuration on peer. */
 -      peer_advertise_map_filter_update(peer, afi, safi, advertise_name,
 -                                       advertise_map, condition_name,
 -                                       condition_map, condition, true);
 -
 -      /* Check if handling a regular peer & Skip peer-group mechanics. */
 -      if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
 -              /* Set override-flag and process peer route updates. */
 -              SET_FLAG(peer->filter_override[afi][safi][RMAP_OUT],
 -                       PEER_FT_ADVERTISE_MAP);
 -              return 0;
 -      }
 -
 -      /*
 -       * Set configuration on all peer-group members, unless they are
 -       * explicitly overriding peer-group configuration.
 -       */
 -      for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
 -              /* Skip peers with overridden configuration. */
 -              if (CHECK_FLAG(member->filter_override[afi][safi][RMAP_OUT],
 -                             PEER_FT_ADVERTISE_MAP))
 -                      continue;
 -
 -              /* Set configuration on peer-group member. */
 -              peer_advertise_map_filter_update(
 -                      member, afi, safi, advertise_name, advertise_map,
 -                      condition_name, condition_map, condition, true);
 -      }
 -
 -      return 0;
 -}
 -
 -/* Unset advertise-map from the peer. */
 -int peer_advertise_map_unset(struct peer *peer, afi_t afi, safi_t safi,
 -                           const char *advertise_name,
 -                           struct route_map *advertise_map,
 -                           const char *condition_name,
 -                           struct route_map *condition_map, bool condition)
 -{
 -      struct peer *member;
 -      struct listnode *node, *nnode;
 -
 -      /* advertise-map is not configured */
 -      if (!peer->filter[afi][safi].advmap.aname)
 -              return 0;
 -
 -      /* Unset override-flag unconditionally. */
 -      UNSET_FLAG(peer->filter_override[afi][safi][RMAP_OUT],
 -                 PEER_FT_ADVERTISE_MAP);
 -
 -      /* Inherit configuration from peer-group if peer is member. */
 -      if (peer_group_active(peer)) {
 -              PEER_STR_ATTR_INHERIT(peer, peer->group,
 -                                    filter[afi][safi].advmap.aname,
 -                                    MTYPE_BGP_FILTER_NAME);
 -              PEER_ATTR_INHERIT(peer, peer->group,
 -                                filter[afi][safi].advmap.amap);
 -      } else
 -              peer_advertise_map_filter_update(
 -                      peer, afi, safi, advertise_name, advertise_map,
 -                      condition_name, condition_map, condition, false);
 -
 -      /* Check if handling a regular peer and skip peer-group mechanics. */
 -      if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
 -              /* Process peer route updates. */
 -              if (BGP_DEBUG(update, UPDATE_OUT))
 -                      zlog_debug("%s: Send normal update to %s for %s",
 -                                 __func__, peer->host,
 -                                 get_afi_safi_str(afi, safi, false));
 -
 -              return 0;
 -      }
 -
 -      /*
 -       * Remove configuration on all peer-group members, unless they are
 -       * explicitly overriding peer-group configuration.
 -       */
 -      for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
 -              /* Skip peers with overridden configuration. */
 -              if (CHECK_FLAG(member->filter_override[afi][safi][RMAP_OUT],
 -                             PEER_FT_ADVERTISE_MAP))
 -                      continue;
 -              /* Remove configuration on peer-group member. */
 -              peer_advertise_map_filter_update(
 -                      member, afi, safi, advertise_name, advertise_map,
 -                      condition_name, condition_map, condition, false);
 -
 -              /* Process peer route updates. */
 -              if (BGP_DEBUG(update, UPDATE_OUT))
 -                      zlog_debug("%s: Send normal update to %s for %s ",
 -                                 __func__, member->host,
 -                                 get_afi_safi_str(afi, safi, false));
 -      }
 -
 -      return 0;
 -}
 -
  static bool peer_maximum_prefix_clear_overflow(struct peer *peer)
  {
        if (!CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
@@@ -8067,11 -8263,18 +8079,18 @@@ void bgp_terminate(void
        /* reverse bgp_master_init */
        for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
                bgp_close_vrf_socket(bgp);
-               for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
-                       if (peer_established(peer) || peer->status == OpenSent
-                           || peer->status == OpenConfirm)
+               for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+                       if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)) {
+                               if (bgp_debug_neighbor_events(peer))
+                                       zlog_debug(
+                                               "%pBP configured Graceful-Restart, skipping unconfig notification",
+                                               peer);
+                               continue;
+                       }
+                       if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
                                bgp_notify_send(peer, BGP_NOTIFY_CEASE,
                                                BGP_NOTIFY_CEASE_PEER_UNCONFIG);
+               }
        }
  
        if (bm->listen_sockets)