]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgpd.c
Merge pull request #12114 from opensourcerouting/feature/bgp_aigp_attribute
[mirror_frr.git] / bgpd / bgpd.c
index 2c0d88d643b81e9ed46ba2b7ca39df6d9d6febe8..8273c78f1e5b23715c489331fa526ce250173370 100644 (file)
@@ -92,6 +92,7 @@
 #include "bgpd/bgp_evpn_private.h"
 #include "bgpd/bgp_evpn_mh.h"
 #include "bgpd/bgp_mac.h"
+#include "bgpd/bgp_orr.h"
 
 DEFINE_MTYPE_STATIC(BGPD, PEER_TX_SHUTDOWN_MSG, "Peer shutdown message (TX)");
 DEFINE_MTYPE_STATIC(BGPD, BGP_EVPN_INFO, "BGP EVPN instance information");
@@ -551,6 +552,21 @@ void bgp_timers_unset(struct bgp *bgp)
        bgp->default_delayopen = BGP_DEFAULT_DELAYOPEN;
 }
 
+void bgp_tcp_keepalive_set(struct bgp *bgp, uint16_t keepalive_idle,
+                          uint16_t keepalive_intvl, uint16_t keepalive_probes)
+{
+       bgp->tcp_keepalive_idle = keepalive_idle;
+       bgp->tcp_keepalive_intvl = keepalive_intvl;
+       bgp->tcp_keepalive_probes = keepalive_probes;
+}
+
+void bgp_tcp_keepalive_unset(struct bgp *bgp)
+{
+       bgp->tcp_keepalive_idle = 0;
+       bgp->tcp_keepalive_intvl = 0;
+       bgp->tcp_keepalive_probes = 0;
+}
+
 /* BGP confederation configuration.  */
 void bgp_confederation_id_set(struct bgp *bgp, as_t as)
 {
@@ -997,9 +1013,15 @@ void peer_af_flag_inherit(struct peer *peer, afi_t afi, safi_t safi,
 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)
@@ -1010,8 +1032,8 @@ static inline enum bgp_peer_sort peer_calc_sort(struct peer *peer)
 
                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 {
@@ -1028,17 +1050,17 @@ static inline enum bgp_peer_sort peer_calc_sort(struct peer *peer)
 
        /* 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;
@@ -1056,8 +1078,7 @@ static inline enum bgp_peer_sort peer_calc_sort(struct peer *peer)
                            && (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;
@@ -1073,9 +1094,8 @@ static inline enum bgp_peer_sort peer_calc_sort(struct peer *peer)
                        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);
        }
 }
@@ -1820,6 +1840,8 @@ bool bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi)
 /* Change peer's AS number.  */
 void peer_as_change(struct peer *peer, as_t as, int as_specified)
 {
+       afi_t afi;
+       safi_t safi;
        enum bgp_peer_sort origtype, newtype;
 
        /* Stop peer. */
@@ -1858,6 +1880,11 @@ void peer_as_change(struct peer *peer, as_t as, int as_specified)
 
        /* reflector-client reset */
        if (newtype != BGP_PEER_IBGP) {
+
+               FOREACH_AFI_SAFI (afi, safi)
+                       UNSET_FLAG(peer->af_flags[afi][safi],
+                                  PEER_FLAG_ORR_GROUP);
+
                UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_UNICAST],
                           PEER_FLAG_REFLECTOR_CLIENT);
                UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_MULTICAST],
@@ -1885,14 +1912,6 @@ void peer_as_change(struct peer *peer, as_t as, int as_specified)
                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,
@@ -2760,6 +2779,21 @@ void peer_notify_unconfig(struct peer *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;
@@ -3018,17 +3052,6 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer,
                        /* 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);
@@ -3182,6 +3205,7 @@ static struct bgp *bgp_create(as_t *as, const char *name,
        bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
        bgp->default_subgroup_pkt_queue_max =
                BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX;
+       bgp_tcp_keepalive_unset(bgp);
        bgp_timers_unset(bgp);
        bgp->default_min_holdtime = 0;
        bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
@@ -3617,6 +3641,7 @@ int bgp_delete(struct bgp *bgp)
 
        hook_call(bgp_inst_delete, bgp);
 
+       THREAD_OFF(bgp->t_condition_check);
        THREAD_OFF(bgp->t_startup);
        THREAD_OFF(bgp->t_maxmed_onstartup);
        THREAD_OFF(bgp->t_update_delay);
@@ -3632,7 +3657,12 @@ int bgp_delete(struct bgp *bgp)
                gr_info = &bgp->gr_info[afi][safi];
                if (!gr_info)
                        continue;
+               t = gr_info->t_select_deferral;
+               if (t) {
+                       void *info = THREAD_ARG(t);
 
+                       XFREE(MTYPE_TMP, info);
+               }
                THREAD_OFF(gr_info->t_select_deferral);
 
                t = gr_info->t_route_select;
@@ -3670,11 +3700,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);
@@ -3715,6 +3742,17 @@ int bgp_delete(struct bgp *bgp)
                bgp->vpn_policy[afi].import_redirect_rtlist = NULL;
        }
 
+       /* Free any memory allocated to holding routemap references */
+       for (afi = 0; afi < AFI_MAX; ++afi) {
+               for (enum vpn_policy_direction dir = 0;
+                    dir < BGP_VPN_POLICY_DIR_MAX; ++dir) {
+                       if (bgp->vpn_policy[afi].rmap_name[dir])
+                               XFREE(MTYPE_ROUTE_MAP_NAME,
+                                     bgp->vpn_policy[afi].rmap_name[dir]);
+                       bgp->vpn_policy[afi].rmap[dir] = NULL;
+               }
+       }
+
        /* Deregister from Zebra, if needed */
        if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
                if (BGP_DEBUG(zebra, ZEBRA))
@@ -3820,6 +3858,8 @@ void bgp_free(struct bgp *bgp)
                        ecommunity_free(&bgp->vpn_policy[afi].rtlist[dir]);
        }
 
+       bgp_orr_cleanup(bgp);
+
        XFREE(MTYPE_BGP, bgp->name);
        XFREE(MTYPE_BGP, bgp->name_pretty);
        XFREE(MTYPE_BGP, bgp->snmp_stats);
@@ -4232,15 +4272,16 @@ static const struct peer_flag_action peer_flag_action_list[] = {
        {PEER_FLAG_TIMER_CONNECT, 0, peer_change_none},
        {PEER_FLAG_TIMER_DELAYOPEN, 0, peer_change_none},
        {PEER_FLAG_PASSWORD, 0, peer_change_none},
-       {PEER_FLAG_LOCAL_AS, 0, peer_change_none},
-       {PEER_FLAG_LOCAL_AS_NO_PREPEND, 0, peer_change_none},
-       {PEER_FLAG_LOCAL_AS_REPLACE_AS, 0, peer_change_none},
+       {PEER_FLAG_LOCAL_AS, 0, peer_change_reset},
+       {PEER_FLAG_LOCAL_AS_NO_PREPEND, 0, peer_change_reset},
+       {PEER_FLAG_LOCAL_AS_REPLACE_AS, 0, peer_change_reset},
        {PEER_FLAG_UPDATE_SOURCE, 0, peer_change_none},
        {PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE, 0, peer_change_none},
        {PEER_FLAG_EXTENDED_OPT_PARAMS, 0, peer_change_reset},
        {PEER_FLAG_ROLE_STRICT_MODE, 0, peer_change_reset},
        {PEER_FLAG_ROLE, 0, peer_change_reset},
        {PEER_FLAG_PORT, 0, peer_change_reset},
+       {PEER_FLAG_AIGP, 0, peer_change_none},
        {0, 0, 0}};
 
 static const struct peer_flag_action peer_af_flag_action_list[] = {
@@ -4273,6 +4314,7 @@ static const struct peer_flag_action peer_af_flag_action_list[] = {
        {PEER_FLAG_WEIGHT, 0, peer_change_reset_in},
        {PEER_FLAG_DISABLE_ADDPATH_RX, 0, peer_change_reset},
        {PEER_FLAG_SOO, 0, peer_change_reset},
+       {PEER_FLAG_ACCEPT_OWN, 0, peer_change_reset},
        {0, 0, 0}};
 
 /* Proper action set. */
@@ -4603,6 +4645,11 @@ static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
        if (flag & PEER_FLAG_REFLECTOR_CLIENT && ptype != BGP_PEER_IBGP)
                return BGP_ERR_NOT_INTERNAL_PEER;
 
+       /* Do not remove reflector client when ORR is configured on this peer */
+       if (flag & PEER_FLAG_REFLECTOR_CLIENT && !set &&
+           peer_orr_rrclient_check(peer, afi, safi))
+               return BGP_ERR_PEER_ORR_CONFIGURED;
+
        /* Special check for remove-private-AS.  */
        if (flag & PEER_FLAG_REMOVE_PRIVATE_AS && ptype == BGP_PEER_IBGP)
                return BGP_ERR_REMOVE_PRIVATE_AS;
@@ -5459,8 +5506,8 @@ void peer_tcp_mss_unset(struct peer *peer)
  * 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));
@@ -6092,17 +6139,10 @@ int peer_local_as_set(struct peer *peer, as_t as, bool no_prepend,
        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);
@@ -6118,20 +6158,11 @@ int peer_local_as_set(struct peer *peer, as_t as, bool 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)) {
-               /* Send notification or reset peer depending on state. */
-               if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
-                       peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
-                       bgp_notify_send(peer, BGP_NOTIFY_CEASE,
-                                       BGP_NOTIFY_CEASE_CONFIG_CHANGE);
-               } else
-                       bgp_session_reset(peer);
-
-               /* Skip peer-group mechanics for regular peers. */
+       if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
                return 0;
-       }
 
        /*
         * Set flag and configuration on all peer-group members, unless they are
@@ -6160,14 +6191,6 @@ int peer_local_as_set(struct peer *peer, as_t as, bool no_prepend,
                COND_FLAG(member->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS,
                          replace_as);
                member->change_local_as = as;
-
-               /* Send notification or stop peer depending on state. */
-               if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
-                       member->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
-                       bgp_notify_send(member, BGP_NOTIFY_CEASE,
-                                       BGP_NOTIFY_CEASE_CONFIG_CHANGE);
-               } else
-                       BGP_EVENT_ADD(member, BGP_Stop);
        }
 
        return 0;
@@ -7202,166 +7225,6 @@ int peer_unsuppress_map_unset(struct peer *peer, afi_t afi, safi_t safi)
        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);
-
-               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))
@@ -8006,6 +7869,7 @@ void bgp_master_init(struct thread_master *master, const int buffer_size,
        bm->socket_buffer = buffer_size;
        bm->wait_for_fib = false;
        bm->tcp_dscp = IPTOS_PREC_INTERNETCONTROL;
+       bm->inq_limit = BM_DEFAULT_INQ_LIMIT;
 
        bgp_mac_init();
        /* init the rd id space.
@@ -8231,11 +8095,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)