]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_route.c
Merge pull request #7274 from donaldsharp/bgp_best_is_a_path
[mirror_frr.git] / bgpd / bgp_route.c
index 84fc1d9c84bedf0fcf4e6e40caa87d9779886225..9fb9ce644e617f849336d3537b7b87cd9434ce89 100644 (file)
@@ -70,6 +70,7 @@
 #include "bgpd/bgp_addpath.h"
 #include "bgpd/bgp_mac.h"
 #include "bgpd/bgp_network.h"
+#include "bgpd/bgp_trace.h"
 
 #ifdef ENABLE_BGP_VNC
 #include "bgpd/rfapi/rfapi_backend.h"
@@ -84,6 +85,9 @@
 #include "bgpd/bgp_flowspec.h"
 #include "bgpd/bgp_flowspec_util.h"
 #include "bgpd/bgp_pbr.h"
+#include "northbound.h"
+#include "northbound_cli.h"
+#include "bgpd/bgp_nb.h"
 
 #ifndef VTYSH_EXTRACT_PL
 #include "bgpd/bgp_route_clippy.c"
@@ -115,6 +119,14 @@ DEFINE_HOOK(bgp_process,
             struct peer *peer, bool withdraw),
            (bgp, afi, safi, bn, peer, withdraw))
 
+/** Test if path is suppressed. */
+static bool bgp_path_suppressed(struct bgp_path_info *pi)
+{
+       if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
+               return false;
+
+       return listcount(pi->extra->aggr_suppressors) > 0;
+}
 
 struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
                                  safi_t safi, const struct prefix *p,
@@ -216,7 +228,7 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
                        unsigned refcount;
 
                        bpi = bgp_path_info_lock(bpi);
-                       refcount = bpi->net->lock - 1;
+                       refcount = bgp_dest_get_lock_count(bpi->net) - 1;
                        bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
                        if (!refcount)
                                bpi->net = NULL;
@@ -314,8 +326,8 @@ static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
        if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
                if (BGP_DEBUG(update, UPDATE_OUT))
                        zlog_debug(
-                               "Route %pRN is in workqueue and being processed, not deferred.",
-                               bgp_dest_to_rnode(dest));
+                               "Route %pBD is in workqueue and being processed, not deferred.",
+                               dest);
 
                return 0;
        }
@@ -365,7 +377,7 @@ static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
                                        bgp->gr_info[afi][safi].route_list,
                                        dest);
                        if (BGP_DEBUG(update, UPDATE_OUT))
-                               zlog_debug("DEFER route %pRN, dest %p, node %p",
+                               zlog_debug("DEFER route %pBD, dest %p, node %p",
                                           dest, dest, dest->rt_node);
                        return 0;
                }
@@ -724,18 +736,18 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
                        *reason = bgp_path_selection_evpn_lower_ip;
                        if (debug)
                                zlog_debug(
-                                       "%s: %s wins over %s due to same MM seq %u and lower IP %s",
+                                       "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
                                        pfx_buf, new_buf, exist_buf, new_mm_seq,
-                                       inet_ntoa(new->attr->nexthop));
+                                       &new->attr->nexthop);
                        return 1;
                }
                if (nh_cmp > 0) {
                        *reason = bgp_path_selection_evpn_lower_ip;
                        if (debug)
                                zlog_debug(
-                                       "%s: %s loses to %s due to same MM seq %u and higher IP %s",
+                                       "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
                                        pfx_buf, new_buf, exist_buf, new_mm_seq,
-                                       inet_ntoa(new->attr->nexthop));
+                                       &new->attr->nexthop);
                        return 0;
                }
        }
@@ -1292,6 +1304,7 @@ static enum filter_type bgp_input_filter(struct peer *peer,
                                         safi_t safi)
 {
        struct bgp_filter *filter;
+       enum filter_type ret = FILTER_PERMIT;
 
        filter = &peer->filter[afi][safi];
 
@@ -1303,26 +1316,43 @@ static enum filter_type bgp_input_filter(struct peer *peer,
        if (DISTRIBUTE_IN_NAME(filter)) {
                FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
 
-               if (access_list_apply(DISTRIBUTE_IN(filter), p) == FILTER_DENY)
-                       return FILTER_DENY;
+               if (access_list_apply(DISTRIBUTE_IN(filter), p)
+                   == FILTER_DENY) {
+                       ret = FILTER_DENY;
+                       goto done;
+               }
        }
 
        if (PREFIX_LIST_IN_NAME(filter)) {
                FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
 
-               if (prefix_list_apply(PREFIX_LIST_IN(filter), p) == PREFIX_DENY)
-                       return FILTER_DENY;
+               if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
+                   == PREFIX_DENY) {
+                       ret = FILTER_DENY;
+                       goto done;
+               }
        }
 
        if (FILTER_LIST_IN_NAME(filter)) {
                FILTER_EXIST_WARN(FILTER_LIST, as, filter);
 
                if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
-                   == AS_FILTER_DENY)
-                       return FILTER_DENY;
+                   == AS_FILTER_DENY) {
+                       ret = FILTER_DENY;
+                       goto done;
+               }
        }
 
-       return FILTER_PERMIT;
+done:
+       if (frrtrace_enabled(frr_bgp, input_filter)) {
+               char pfxprint[PREFIX2STR_BUFFER];
+
+               prefix2str(p, pfxprint, sizeof(pfxprint));
+               frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
+                        ret == FILTER_PERMIT ? "permit" : "deny");
+       }
+
+       return ret;
 #undef FILTER_EXIST_WARN
 }
 
@@ -1332,6 +1362,7 @@ static enum filter_type bgp_output_filter(struct peer *peer,
                                          safi_t safi)
 {
        struct bgp_filter *filter;
+       enum filter_type ret = FILTER_PERMIT;
 
        filter = &peer->filter[afi][safi];
 
@@ -1343,27 +1374,43 @@ static enum filter_type bgp_output_filter(struct peer *peer,
        if (DISTRIBUTE_OUT_NAME(filter)) {
                FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
 
-               if (access_list_apply(DISTRIBUTE_OUT(filter), p) == FILTER_DENY)
-                       return FILTER_DENY;
+               if (access_list_apply(DISTRIBUTE_OUT(filter), p)
+                   == FILTER_DENY) {
+                       ret = FILTER_DENY;
+                       goto done;
+               }
        }
 
        if (PREFIX_LIST_OUT_NAME(filter)) {
                FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
 
                if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
-                   == PREFIX_DENY)
-                       return FILTER_DENY;
+                   == PREFIX_DENY) {
+                       ret = FILTER_DENY;
+                       goto done;
+               }
        }
 
        if (FILTER_LIST_OUT_NAME(filter)) {
                FILTER_EXIST_WARN(FILTER_LIST, as, filter);
 
                if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
-                   == AS_FILTER_DENY)
-                       return FILTER_DENY;
+                   == AS_FILTER_DENY) {
+                       ret = FILTER_DENY;
+                       goto done;
+               }
+       }
+
+       if (frrtrace_enabled(frr_bgp, output_filter)) {
+               char pfxprint[PREFIX2STR_BUFFER];
+
+               prefix2str(p, pfxprint, sizeof(pfxprint));
+               frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
+                        ret == FILTER_PERMIT ? "permit" : "deny");
        }
 
-       return FILTER_PERMIT;
+done:
+       return ret;
 #undef FILTER_EXIST_WARN
 }
 
@@ -1617,7 +1664,34 @@ void bgp_attr_add_gshut_community(struct attr *attr)
 }
 
 
-static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
+/* Notify BGP Conditional advertisement scanner process. */
+void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
+{
+       struct peer *temp_peer;
+       struct peer *peer = SUBGRP_PEER(subgrp);
+       struct listnode *temp_node, *temp_nnode = NULL;
+       afi_t afi = SUBGRP_AFI(subgrp);
+       safi_t safi = SUBGRP_SAFI(subgrp);
+       struct bgp *bgp = SUBGRP_INST(subgrp);
+       struct bgp_filter *filter = &peer->filter[afi][safi];
+
+       if (!ADVERTISE_MAP_NAME(filter))
+               return;
+
+       for (ALL_LIST_ELEMENTS(bgp->peer, temp_node, temp_nnode, temp_peer)) {
+               if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
+                       continue;
+
+               if (peer != temp_peer)
+                       continue;
+
+               temp_peer->advmap_table_change = true;
+               break;
+       }
+}
+
+
+void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
 {
        if (family == AF_INET) {
                attr->nexthop.s_addr = INADDR_ANY;
@@ -1631,7 +1705,8 @@ static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
 
 bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
                             struct update_subgroup *subgrp,
-                            const struct prefix *p, struct attr *attr)
+                            const struct prefix *p, struct attr *attr,
+                            bool skip_rmap_check)
 {
        struct bgp_filter *filter;
        struct peer *from;
@@ -1639,7 +1714,6 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
        struct peer *onlypeer;
        struct bgp *bgp;
        struct attr *piattr;
-       char buf[PREFIX_STRLEN];
        route_map_result_t ret;
        int transparent;
        int reflect;
@@ -1675,9 +1749,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
                 * though they can have peer pointers that reference other
                 * systems
                 */
-               prefix2str(p, buf, PREFIX_STRLEN);
-               zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
-                          __func__, buf);
+               zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
+                          __func__, p);
                samepeer_safe = 1;
        }
 #endif
@@ -1710,10 +1783,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
        }
 
        /* Aggregate-address suppress check. */
-       if (pi->extra && pi->extra->suppress)
-               if (!UNSUPPRESS_MAP_NAME(filter)) {
-                       return false;
-               }
+       if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
+               return false;
 
        /*
         * If we are doing VRF 2 VRF leaking via the import
@@ -1730,11 +1801,10 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
                mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
                if (!bgp_is_valid_label(&label)) {
                        if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
-                               zlog_debug("u%" PRIu64 ":s%" PRIu64" %s/%d is filtered - no label (%p)",
+                               zlog_debug("u%" PRIu64 ":s%" PRIu64
+                                          " %pFX is filtered - no label (%p)",
                                           subgrp->update_group->id, subgrp->id,
-                                          inet_ntop(p->family, &p->u.prefix,
-                                                    buf, SU_ADDRSTRLEN),
-                                          p->prefixlen, &label);
+                                          p, &label);
                        return false;
                }
        }
@@ -1775,9 +1845,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
            && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
                if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
                        zlog_debug(
-                               "%s [Update:SEND] %s originator-id is same as remote router-id",
-                               onlypeer->host,
-                               prefix2str(p, buf, sizeof(buf)));
+                               "%s [Update:SEND] %pFX originator-id is same as remote router-id",
+                               onlypeer->host, p);
                return false;
        }
 
@@ -1792,10 +1861,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
                                if (bgp_debug_update(NULL, p,
                                                     subgrp->update_group, 0))
                                        zlog_debug(
-                                               "%s [Update:SEND] %s is filtered via ORF",
-                                               peer->host,
-                                               prefix2str(p, buf,
-                                                          sizeof(buf)));
+                                               "%s [Update:SEND] %pFX is filtered via ORF",
+                                               peer->host, p);
                                return false;
                        }
                }
@@ -1803,8 +1870,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
        /* Output filter check. */
        if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
                if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
-                       zlog_debug("%s [Update:SEND] %s is filtered",
-                                  peer->host, prefix2str(p, buf, sizeof(buf)));
+                       zlog_debug("%s [Update:SEND] %pFX is filtered",
+                                  peer->host, p);
                return false;
        }
 
@@ -1954,7 +2021,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
        bgp_peer_as_override(bgp, afi, safi, peer, attr);
 
        /* Route map & unsuppress-map apply. */
-       if (ROUTE_MAP_OUT_NAME(filter) || (pi->extra && pi->extra->suppress)) {
+       if (!skip_rmap_check
+           && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
                struct bgp_path_info rmap_path = {0};
                struct bgp_path_info_extra dummy_rmap_path_extra = {0};
                struct attr dummy_attr = {0};
@@ -1979,7 +2047,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
 
                SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
 
-               if (pi->extra && pi->extra->suppress)
+               if (bgp_path_suppressed(pi))
                        ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
                                              RMAP_BGP, &rmap_path);
                else
@@ -1990,8 +2058,9 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
 
                if (ret == RMAP_DENYMATCH) {
                        if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
-                               zlog_debug("%s [Update:SEND] %s is filtered by route-map",
-                               peer->host, prefix2str(p, buf, sizeof(buf)));
+                               zlog_debug(
+                                       "%s [Update:SEND] %pFX is filtered by route-map",
+                                       peer->host, p);
 
                        bgp_attr_flush(attr);
                        return false;
@@ -2272,10 +2341,11 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
                        if (debug) {
                                bgp_path_info_path_with_addpath_rx_str(
                                        new_select, path_buf);
-                               zlog_debug("%s: %s is the bestpath from AS %u",
-                                          pfx_buf, path_buf,
-                                          aspath_get_first_as(
-                                                  new_select->attr->aspath));
+                               zlog_debug(
+                                       "%pBD: %s is the bestpath from AS %u",
+                                       dest, path_buf,
+                                       aspath_get_first_as(
+                                               new_select->attr->aspath));
                        }
                }
        }
@@ -2349,8 +2419,8 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
                else
                        snprintf(path_buf, sizeof(path_buf), "NONE");
                zlog_debug(
-                       "%s: After path selection, newbest is %s oldbest was %s",
-                       pfx_buf, path_buf,
+                       "%pBD: After path selection, newbest is %s oldbest was %s",
+                       dest, path_buf,
                        old_select ? old_select->peer->host : "NONE");
        }
 
@@ -2365,8 +2435,8 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
                        if (pi == new_select) {
                                if (debug)
                                        zlog_debug(
-                                               "%s: %s is the bestpath, add to the multipath list",
-                                               pfx_buf, path_buf);
+                                               "%pBD: %s is the bestpath, add to the multipath list",
+                                               dest, path_buf);
                                bgp_mp_list_add(&mp_list, pi);
                                continue;
                        }
@@ -2383,8 +2453,8 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
                        if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
                                if (debug)
                                        zlog_debug(
-                                               "%s: %s has the same nexthop as the bestpath, skip it",
-                                               pfx_buf, path_buf);
+                                               "%pBD: %s has the same nexthop as the bestpath, skip it",
+                                               dest, path_buf);
                                continue;
                        }
 
@@ -2395,8 +2465,8 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
                        if (paths_eq) {
                                if (debug)
                                        zlog_debug(
-                                               "%s: %s is equivalent to the bestpath, add to the multipath list",
-                                               pfx_buf, path_buf);
+                                               "%pBD: %s is equivalent to the bestpath, add to the multipath list",
+                                               dest, path_buf);
                                bgp_mp_list_add(&mp_list, pi);
                        }
                }
@@ -2436,12 +2506,8 @@ void subgroup_process_announce_selected(struct update_subgroup *subgrp,
        onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
                                                 : NULL);
 
-       if (BGP_DEBUG(update, UPDATE_OUT)) {
-               char buf_prefix[PREFIX_STRLEN];
-               prefix2str(p, buf_prefix, sizeof(buf_prefix));
-               zlog_debug("%s: p=%s, selected=%p", __func__, buf_prefix,
-                          selected);
-       }
+       if (BGP_DEBUG(update, UPDATE_OUT))
+               zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
 
        /* First update is deferred until ORF or ROUTE-REFRESH is received */
        if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
@@ -2454,7 +2520,8 @@ void subgroup_process_announce_selected(struct update_subgroup *subgrp,
        /* Announcement to the subgroup.  If the route is filtered withdraw it.
         */
        if (selected) {
-               if (subgroup_announce_check(dest, selected, subgrp, p, &attr))
+               if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
+                                           false))
                        bgp_adj_out_set_subgroup(dest, subgrp, &attr, selected);
                else
                        bgp_adj_out_unset_subgroup(dest, subgrp, 1,
@@ -2605,7 +2672,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
                        debug = bgp_debug_bestpath(dest);
                if (debug)
                        zlog_debug(
-                               "%s: bgp delete in progress, ignoring event, p=%pRN",
+                               "%s: bgp delete in progress, ignoring event, p=%pBD",
                                __func__, dest);
                return;
        }
@@ -2629,7 +2696,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
 
        debug = bgp_debug_bestpath(dest);
        if (debug)
-               zlog_debug("%s: p=%pRN afi=%s, safi=%s start", __func__, dest,
+               zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__, dest,
                           afi2str(afi), safi2str(safi));
 
        /* The best path calculation for the route is deferred if
@@ -2637,7 +2704,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
         */
        if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
                if (BGP_DEBUG(update, UPDATE_OUT))
-                       zlog_debug("SELECT_DEFER falg set for route %p", dest);
+                       zlog_debug("SELECT_DEFER flag set for route %p", dest);
                return;
        }
 
@@ -2690,7 +2757,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
 
        if (debug)
                zlog_debug(
-                       "%s: p=%pRN afi=%s, safi=%s, old_select=%p, new_select=%p",
+                       "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
                        __func__, dest, afi2str(afi), safi2str(safi),
                        old_select, new_select);
 
@@ -2945,18 +3012,21 @@ static void bgp_processq_del(struct work_queue *wq, void *data)
        XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
 }
 
-void bgp_process_queue_init(void)
+void bgp_process_queue_init(struct bgp *bgp)
 {
-       if (!bm->process_main_queue)
-               bm->process_main_queue =
-                       work_queue_new(bm->master, "process_main_queue");
+       if (!bgp->process_queue) {
+               char name[BUFSIZ];
+
+               snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
+               bgp->process_queue = work_queue_new(bm->master, name);
+       }
 
-       bm->process_main_queue->spec.workfunc = &bgp_process_wq;
-       bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
-       bm->process_main_queue->spec.max_retries = 0;
-       bm->process_main_queue->spec.hold = 50;
+       bgp->process_queue->spec.workfunc = &bgp_process_wq;
+       bgp->process_queue->spec.del_item_data = &bgp_processq_del;
+       bgp->process_queue->spec.max_retries = 0;
+       bgp->process_queue->spec.hold = 50;
        /* Use a higher yield value of 50ms for main queue processing */
-       bm->process_main_queue->spec.yield = 50 * 1000L;
+       bgp->process_queue->spec.yield = 50 * 1000L;
 }
 
 static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
@@ -2976,7 +3046,7 @@ static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
 void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
 {
 #define ARBITRARY_PROCESS_QLEN         10000
-       struct work_queue *wq = bm->process_main_queue;
+       struct work_queue *wq = bgp->process_queue;
        struct bgp_process_queue *pqnode;
        int pqnode_reuse = 0;
 
@@ -3033,13 +3103,13 @@ void bgp_add_eoiu_mark(struct bgp *bgp)
 {
        struct bgp_process_queue *pqnode;
 
-       if (bm->process_main_queue == NULL)
+       if (bgp->process_queue == NULL)
                return;
 
        pqnode = bgp_processq_alloc(bgp);
 
        SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
-       work_queue_add(bm->process_main_queue, pqnode);
+       work_queue_add(bgp->process_queue, pqnode);
 }
 
 static int bgp_maximum_prefix_restart_timer(struct thread *thread)
@@ -3171,7 +3241,8 @@ bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
                UNSET_FLAG(peer->af_sflags[afi][safi],
                           PEER_STATUS_PREFIX_LIMIT);
 
-       if (pcount > (pcount * peer->pmax_threshold[afi][safi] / 100)) {
+       if (pcount
+           > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
                if (CHECK_FLAG(peer->af_sflags[afi][safi],
                               PEER_STATUS_PREFIX_THRESHOLD)
                    && !always)
@@ -3434,6 +3505,14 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
        uint8_t pi_type = 0;
        uint8_t pi_sub_type = 0;
 
+       if (frrtrace_enabled(frr_bgp, process_update)) {
+               char pfxprint[PREFIX2STR_BUFFER];
+
+               prefix2str(p, pfxprint, sizeof(pfxprint));
+               frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
+                        afi, safi, attr);
+       }
+
 #ifdef ENABLE_BGP_VNC
        int vnc_implicit_withdraw = 0;
 #endif
@@ -4291,7 +4370,7 @@ void bgp_stop_announce_route_timer(struct peer_af *paf)
        if (!paf->t_announce_route)
                return;
 
-       THREAD_TIMER_OFF(paf->t_announce_route);
+       thread_cancel(&paf->t_announce_route);
 }
 
 /*
@@ -4315,6 +4394,10 @@ static int bgp_announce_route_timer_expired(struct thread *t)
                return 0;
 
        peer_af_announce_route(paf, 1);
+
+       /* Notify BGP conditional advertisement scanner percess */
+       peer->advmap_config_change[paf->afi][paf->safi] = true;
+
        return 0;
 }
 
@@ -4550,7 +4633,7 @@ static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
                                  struct bgp_table *table)
 {
        struct bgp_dest *dest;
-       int force = bm->process_main_queue ? 0 : 1;
+       int force = peer->bgp->process_queue ? 0 : 1;
 
        if (!table)
                table = peer->bgp->rib[afi][safi];
@@ -4987,8 +5070,8 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
                                 */
                                flog_err(
                                        EC_BGP_UPDATE_RCV,
-                                       "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
-                                       peer->host, inet_ntoa(p.u.prefix4));
+                                       "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
+                                       peer->host, &p.u.prefix4);
                                continue;
                        }
                }
@@ -5542,28 +5625,16 @@ static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
 
 /* Configure static BGP network.  When user don't run zebra, static
    route should be installed as valid.  */
-static int bgp_static_set(struct vty *vty, const char *negate,
-                         const char *ip_str, afi_t afi, safi_t safi,
-                         const char *rmap, int backdoor, uint32_t label_index)
+int bgp_static_set(struct bgp *bgp, const char *negate, struct prefix *pfx,
+                  afi_t afi, safi_t safi, const char *rmap, int backdoor,
+                  uint32_t label_index, char *errmsg, size_t errmsg_len)
 {
-       VTY_DECLVAR_CONTEXT(bgp, bgp);
-       int ret;
        struct prefix p;
        struct bgp_static *bgp_static;
        struct bgp_dest *dest;
        uint8_t need_update = 0;
 
-       /* Convert IP prefix string to struct prefix. */
-       ret = str2prefix(ip_str, &p);
-       if (!ret) {
-               vty_out(vty, "%% Malformed prefix\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-       if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
-               vty_out(vty, "%% Malformed prefix (link-local address)\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
+       prefix_copy(&p, pfx);
        apply_mask(&p);
 
        if (negate) {
@@ -5572,24 +5643,25 @@ static int bgp_static_set(struct vty *vty, const char *negate,
                dest = bgp_node_lookup(bgp->route[afi][safi], &p);
 
                if (!dest) {
-                       vty_out(vty, "%% Can't find static route specified\n");
-                       return CMD_WARNING_CONFIG_FAILED;
+                       snprintf(errmsg, errmsg_len,
+                                "Can't find static route specified\n");
+                       return -1;
                }
 
                bgp_static = bgp_dest_get_bgp_static_info(dest);
 
                if ((label_index != BGP_INVALID_LABEL_INDEX)
                    && (label_index != bgp_static->label_index)) {
-                       vty_out(vty,
-                               "%% label-index doesn't match static route\n");
-                       return CMD_WARNING_CONFIG_FAILED;
+                       snprintf(errmsg, errmsg_len,
+                                "label-index doesn't match static route\n");
+                       return -1;
                }
 
                if ((rmap && bgp_static->rmap.name)
                    && strcmp(rmap, bgp_static->rmap.name)) {
-                       vty_out(vty,
-                               "%% route-map name doesn't match static route\n");
-                       return CMD_WARNING_CONFIG_FAILED;
+                       snprintf(errmsg, errmsg_len,
+                                "route-map name doesn't match static route\n");
+                       return -1;
                }
 
                /* Update BGP RIB. */
@@ -5610,8 +5682,9 @@ static int bgp_static_set(struct vty *vty, const char *negate,
                        /* Configuration change. */
                        /* Label index cannot be changed. */
                        if (bgp_static->label_index != label_index) {
-                               vty_out(vty, "%% cannot change label-index\n");
-                               return CMD_WARNING_CONFIG_FAILED;
+                               snprintf(errmsg, errmsg_len,
+                                        "cannot change label-index\n");
+                               return -1;
                        }
 
                        /* Check previous routes are installed into BGP.  */
@@ -5673,7 +5746,7 @@ static int bgp_static_set(struct vty *vty, const char *negate,
                        bgp_static_update(bgp, &p, bgp_static, afi, safi);
        }
 
-       return CMD_SUCCESS;
+       return 0;
 }
 
 void bgp_static_add(struct bgp *bgp)
@@ -5749,9 +5822,9 @@ void bgp_static_delete(struct bgp *bgp)
                                                        bgp_dest_get_prefix(
                                                                dest));
                                        bgp_static_free(bgp_static);
-                                       bgp_dest_set_bgp_static_info(dest,
+                                       bgp_dest_set_bgp_static_info(rm,
                                                                     NULL);
-                                       bgp_dest_unlock_node(dest);
+                                       bgp_dest_unlock_node(rm);
                                }
                        } else {
                                bgp_static = bgp_dest_get_bgp_static_info(dest);
@@ -6123,25 +6196,27 @@ DEFUN (no_bgp_table_map,
                                   argv[idx_word]->arg);
 }
 
-DEFPY(bgp_network,
-       bgp_network_cmd,
-       "[no] network \
-       <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
-       [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
-       backdoor$backdoor}]",
-       NO_STR
-       "Specify a network to announce via BGP\n"
-       "IPv4 prefix\n"
-       "Network number\n"
-       "Network mask\n"
-       "Network mask\n"
-       "Route-map to modify the attributes\n"
-       "Name of the route map\n"
-       "Label index to associate with the prefix\n"
-       "Label index value\n"
-       "Specify a BGP backdoor route\n")
-{
-       char addr_prefix_str[BUFSIZ];
+DEFPY_YANG (bgp_network, bgp_network_cmd,
+           "[no] network \
+           <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
+           [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
+           backdoor$backdoor}]",
+           NO_STR
+           "Specify a network to announce via BGP\n"
+           "IPv4 prefix\n"
+           "Network number\n"
+           "Network mask\n"
+           "Network mask\n"
+           "Route-map to modify the attributes\n"
+           "Name of the route map\n"
+           "Label index to associate with the prefix\n"
+           "Label index value\n"
+           "Specify a BGP backdoor route\n")
+{
+       char addr_prefix_str[PREFIX_STRLEN];
+       char base_xpath[XPATH_MAXLEN];
+       afi_t afi;
+       safi_t safi;
 
        if (address_str) {
                int ret;
@@ -6154,27 +6229,102 @@ DEFPY(bgp_network,
                }
        }
 
-       return bgp_static_set(
-               vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
-               bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
-               label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
+       afi = bgp_node_afi(vty);
+       safi = bgp_node_safi(vty);
+
+       if (no) {
+               nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
+       } else {
+               nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
+
+               if (map_name)
+                       nb_cli_enqueue_change(vty, "./rmap-policy-export",
+                                             NB_OP_CREATE, map_name);
+               else
+                       nb_cli_enqueue_change(vty, "./rmap-policy-export",
+                                             NB_OP_DESTROY, NULL);
+
+               if (label_index_str)
+                       nb_cli_enqueue_change(vty, "./label-index",
+                                             NB_OP_MODIFY, label_index_str);
+
+               nb_cli_enqueue_change(vty, "./backdoor", NB_OP_MODIFY,
+                                     backdoor ? "true" : "false");
+       }
+
+       snprintf(
+               base_xpath, sizeof(base_xpath),
+               "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
+               yang_afi_safi_value2identity(afi, safi),
+               bgp_afi_safi_get_container_str(afi, safi),
+               address_str ? addr_prefix_str : prefix_str);
+
+       return nb_cli_apply_changes(vty, base_xpath);
 }
 
-DEFPY(ipv6_bgp_network,
-       ipv6_bgp_network_cmd,
-       "[no] network X:X::X:X/M$prefix \
-       [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
-       NO_STR
-       "Specify a network to announce via BGP\n"
-       "IPv6 prefix\n"
-       "Route-map to modify the attributes\n"
-       "Name of the route map\n"
-       "Label index to associate with the prefix\n"
-       "Label index value\n")
+DEFPY_YANG (ipv6_bgp_network,
+           ipv6_bgp_network_cmd,
+           "[no] network X:X::X:X/M$prefix \
+           [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
+           NO_STR
+           "Specify a network to announce via BGP\n"
+           "IPv6 prefix\n"
+           "Route-map to modify the attributes\n"
+           "Name of the route map\n"
+           "Label index to associate with the prefix\n"
+           "Label index value\n")
 {
-       return bgp_static_set(
-               vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
-               label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
+       char base_xpath[XPATH_MAXLEN];
+       afi_t afi;
+       safi_t safi;
+
+       afi = bgp_node_afi(vty);
+       safi = bgp_node_safi(vty);
+
+       if (no) {
+               nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
+       } else {
+               nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
+
+               if (map_name)
+                       nb_cli_enqueue_change(vty, "./rmap-policy-export",
+                                             NB_OP_MODIFY, map_name);
+               else
+                       nb_cli_enqueue_change(vty, "./rmap-policy-export",
+                                             NB_OP_DESTROY, NULL);
+
+               if (label_index_str)
+                       nb_cli_enqueue_change(vty, "./label-index",
+                                             NB_OP_MODIFY, label_index_str);
+       }
+
+       snprintf(
+               base_xpath, sizeof(base_xpath),
+               "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
+               yang_afi_safi_value2identity(afi, safi),
+               bgp_afi_safi_get_container_str(afi, safi), prefix_str);
+
+       return nb_cli_apply_changes(vty, base_xpath);
+}
+
+void cli_show_bgp_global_afi_safi_network_config(struct vty *vty,
+                                                struct lyd_node *dnode,
+                                                bool show_defaults)
+{
+       vty_out(vty, "  network %s", yang_dnode_get_string(dnode, "./prefix"));
+
+       if (yang_dnode_exists(dnode, "./label-index"))
+               vty_out(vty, " label-index %s",
+                       yang_dnode_get_string(dnode, "./label-index"));
+
+       if (yang_dnode_exists(dnode, "./rmap-policy-export"))
+               vty_out(vty, " route-map %s",
+                       yang_dnode_get_string(dnode, "./rmap-policy-export"));
+
+       if (yang_dnode_get_bool(dnode, "./backdoor"))
+               vty_out(vty, " backdoor");
+
+       vty_out(vty, "\n");
 }
 
 static struct bgp_aggregate *bgp_aggregate_new(void)
@@ -6184,11 +6334,119 @@ static struct bgp_aggregate *bgp_aggregate_new(void)
 
 static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
 {
+       XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
+       route_map_counter_decrement(aggregate->suppress_map);
        XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
        route_map_counter_decrement(aggregate->rmap.map);
        XFREE(MTYPE_BGP_AGGREGATE, aggregate);
 }
 
+/**
+ * Helper function to avoid repeated code: prepare variables for a
+ * `route_map_apply` call.
+ *
+ * \returns `true` on route map match, otherwise `false`.
+ */
+static bool aggr_suppress_map_test(struct bgp *bgp,
+                                  struct bgp_aggregate *aggregate,
+                                  struct bgp_path_info *pi)
+{
+       const struct prefix *p = bgp_dest_get_prefix(pi->net);
+       route_map_result_t rmr = RMAP_DENYMATCH;
+       struct bgp_path_info rmap_path = {};
+       struct attr attr = {};
+
+       /* No route map entries created, just don't match. */
+       if (aggregate->suppress_map == NULL)
+               return false;
+
+       /* Call route map matching and return result. */
+       attr.aspath = aspath_empty();
+       rmap_path.peer = bgp->peer_self;
+       rmap_path.attr = &attr;
+
+       SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
+       rmr = route_map_apply(aggregate->suppress_map, p, RMAP_BGP, &rmap_path);
+       bgp->peer_self->rmap_type = 0;
+
+       bgp_attr_flush(&attr);
+
+       return rmr == RMAP_PERMITMATCH;
+}
+
+/** Test whether the aggregation has suppressed this path or not. */
+static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
+                                struct bgp_path_info *pi)
+{
+       if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
+               return false;
+
+       return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
+}
+
+/**
+ * Suppress this path and keep the reference.
+ *
+ * \returns `true` if needs processing otherwise `false`.
+ */
+static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
+                              struct bgp_path_info *pi)
+{
+       struct bgp_path_info_extra *pie;
+
+       /* Path is already suppressed by this aggregation. */
+       if (aggr_suppress_exists(aggregate, pi))
+               return false;
+
+       pie = bgp_path_info_extra_get(pi);
+
+       /* This is the first suppression, allocate memory and list it. */
+       if (pie->aggr_suppressors == NULL)
+               pie->aggr_suppressors = list_new();
+
+       listnode_add(pie->aggr_suppressors, aggregate);
+
+       /* Only mark for processing if suppressed. */
+       if (listcount(pie->aggr_suppressors) == 1) {
+               if (BGP_DEBUG(update, UPDATE_OUT))
+                       zlog_debug("aggregate-address suppressing: %pFX",
+                                  bgp_dest_get_prefix(pi->net));
+
+               bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
+               return true;
+       }
+
+       return false;
+}
+
+/**
+ * Unsuppress this path and remove the reference.
+ *
+ * \returns `true` if needs processing otherwise `false`.
+ */
+static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
+                                struct bgp_path_info *pi)
+{
+       /* Path wasn't suppressed. */
+       if (!aggr_suppress_exists(aggregate, pi))
+               return false;
+
+       listnode_delete(pi->extra->aggr_suppressors, aggregate);
+
+       /* Unsuppress and free extra memory if last item. */
+       if (listcount(pi->extra->aggr_suppressors) == 0) {
+               if (BGP_DEBUG(update, UPDATE_OUT))
+                       zlog_debug("aggregate-address unsuppressing: %pFX",
+                                  bgp_dest_get_prefix(pi->net));
+
+               list_delete(&pi->extra->aggr_suppressors);
+               bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
+               return true;
+       }
+
+       return false;
+}
+
 static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
                                    struct aspath *aspath,
                                    struct community *comm,
@@ -6383,13 +6641,11 @@ static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
  * Toggles the route suppression status for this aggregate address
  * configuration.
  */
-static void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
-                                           struct bgp *bgp,
-                                           const struct prefix *p, afi_t afi,
-                                           safi_t safi, bool suppress)
+void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
+                                    struct bgp *bgp, const struct prefix *p,
+                                    afi_t afi, safi_t safi, bool suppress)
 {
        struct bgp_table *table = bgp->rib[afi][safi];
-       struct bgp_path_info_extra *pie;
        const struct prefix *dest_p;
        struct bgp_dest *dest, *top;
        struct bgp_path_info *pi;
@@ -6410,32 +6666,17 @@ static void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
                        if (pi->sub_type == BGP_ROUTE_AGGREGATE)
                                continue;
 
-                       /*
-                        * On installation it is possible that pi->extra is
-                        * set to NULL, otherwise it must exists.
-                        */
-                       assert(!suppress && pi->extra != NULL);
-
                        /* We are toggling suppression back. */
                        if (suppress) {
-                               pie = bgp_path_info_extra_get(pi);
                                /* Suppress route if not suppressed already. */
-                               pie->suppress++;
-                               bgp_path_info_set_flag(dest, pi,
-                                                      BGP_PATH_ATTR_CHANGED);
-                               toggle_suppression = true;
+                               if (aggr_suppress_path(aggregate, pi))
+                                       toggle_suppression = true;
                                continue;
                        }
 
-                       pie = pi->extra;
-                       assert(pie->suppress > 0);
-                       pie->suppress--;
                        /* Install route if there is no more suppression. */
-                       if (pie->suppress == 0) {
-                               bgp_path_info_set_flag(dest, pi,
-                                                      BGP_PATH_ATTR_CHANGED);
+                       if (aggr_unsuppress_path(aggregate, pi))
                                toggle_suppression = true;
-                       }
                }
 
                if (toggle_suppression)
@@ -6522,6 +6763,17 @@ void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
        if (aggregate->match_med)
                bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
 
+       /*
+        * Reset aggregate count: we might've been called from route map
+        * update so in that case we must retest all more specific routes.
+        *
+        * \see `bgp_route_map_process_update`.
+        */
+       aggregate->count = 0;
+       aggregate->incomplete_origin_count = 0;
+       aggregate->incomplete_origin_count = 0;
+       aggregate->egp_origin_count = 0;
+
        /* ORIGIN attribute: If at least one route among routes that are
           aggregated has ORIGIN with the value INCOMPLETE, then the
           aggregated route must have the ORIGIN attribute with the value
@@ -6566,10 +6818,24 @@ void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
                         */
                        if (aggregate->summary_only
                            && AGGREGATE_MED_VALID(aggregate)) {
-                               (bgp_path_info_extra_get(pi))->suppress++;
-                               bgp_path_info_set_flag(dest, pi,
-                                                      BGP_PATH_ATTR_CHANGED);
-                               match++;
+                               if (aggr_suppress_path(aggregate, pi))
+                                       match++;
+                       }
+
+                       /*
+                        * Suppress more specific routes that match the route
+                        * map results.
+                        *
+                        * MED matching:
+                        * Don't suppress routes if MED matching is enabled and
+                        * it mismatched otherwise we might end up with no
+                        * routes for this path.
+                        */
+                       if (aggregate->suppress_map_name
+                           && AGGREGATE_MED_VALID(aggregate)
+                           && aggr_suppress_map_test(bgp, aggregate, pi)) {
+                               if (aggr_suppress_path(aggregate, pi))
+                                       match++;
                        }
 
                        aggregate->count++;
@@ -6709,15 +6975,17 @@ void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
 
                        if (aggregate->summary_only && pi->extra
                            && AGGREGATE_MED_VALID(aggregate)) {
-                               pi->extra->suppress--;
+                               if (aggr_unsuppress_path(aggregate, pi))
+                                       match++;
+                       }
 
-                               if (pi->extra->suppress == 0) {
-                                       bgp_path_info_set_flag(
-                                               dest, pi,
-                                               BGP_PATH_ATTR_CHANGED);
+                       if (aggregate->suppress_map_name
+                           && AGGREGATE_MED_VALID(aggregate)
+                           && aggr_suppress_map_test(bgp, aggregate, pi)) {
+                               if (aggr_unsuppress_path(aggregate, pi))
                                        match++;
-                               }
                        }
+
                        aggregate->count--;
 
                        if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
@@ -6808,7 +7076,11 @@ static void bgp_add_route_to_aggregate(struct bgp *bgp,
                                         pinew, true);
 
        if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
-               (bgp_path_info_extra_get(pinew))->suppress++;
+               aggr_suppress_path(aggregate, pinew);
+
+       if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
+           && aggr_suppress_map_test(bgp, aggregate, pinew))
+               aggr_suppress_path(aggregate, pinew);
 
        switch (pinew->attr->origin) {
        case BGP_ORIGIN_INCOMPLETE:
@@ -6904,19 +7176,17 @@ static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
        if (pi->sub_type == BGP_ROUTE_AGGREGATE)
                return;
 
-       if (aggregate->summary_only && pi->extra && pi->extra->suppress > 0
-           && AGGREGATE_MED_VALID(aggregate)) {
-               pi->extra->suppress--;
+       if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
+               if (aggr_unsuppress_path(aggregate, pi))
+                       match++;
 
-               if (pi->extra->suppress == 0) {
-                       bgp_path_info_set_flag(pi->net, pi,
-                                              BGP_PATH_ATTR_CHANGED);
+       if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
+           && aggr_suppress_map_test(bgp, aggregate, pi))
+               if (aggr_unsuppress_path(aggregate, pi))
                        match++;
-               }
-       }
 
        /*
-        * This must be called after `summary` check to avoid
+        * This must be called after `summary`, `suppress-map` check to avoid
         * "unsuppressing" twice.
         */
        if (aggregate->match_med)
@@ -7084,35 +7354,25 @@ static const char *bgp_origin2str(uint8_t origin)
        return "n/a";
 }
 
-static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
-                              afi_t afi, safi_t safi)
+int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi,
+                       safi_t safi, char *errmsg, size_t errmsg_len)
 {
-       VTY_DECLVAR_CONTEXT(bgp, bgp);
-       int ret;
-       struct prefix p;
        struct bgp_dest *dest;
        struct bgp_aggregate *aggregate;
 
-       /* Convert string to prefix structure. */
-       ret = str2prefix(prefix_str, &p);
-       if (!ret) {
-               vty_out(vty, "Malformed prefix\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-       apply_mask(&p);
-
+       apply_mask(prefix);
        /* Old configuration check. */
-       dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
+       dest = bgp_node_lookup(bgp->aggregate[afi][safi], prefix);
        if (!dest) {
-               vty_out(vty,
-                       "%% There is no aggregate-address configuration.\n");
-               return CMD_WARNING_CONFIG_FAILED;
+               snprintf(errmsg, errmsg_len,
+                        "There is no aggregate-address configuration.\n");
+               return -1;
        }
 
        aggregate = bgp_dest_get_bgp_aggregate_info(dest);
-       bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
-       bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
-                             NULL, NULL,  0, aggregate);
+       bgp_aggregate_delete(bgp, prefix, afi, safi, aggregate);
+       bgp_aggregate_install(bgp, afi, safi, prefix, 0, NULL, NULL, NULL, NULL,
+                             0, aggregate);
 
        /* Unlock aggregate address configuration. */
        bgp_dest_set_bgp_aggregate_info(dest, NULL);
@@ -7173,48 +7433,53 @@ static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
        bgp_dest_unlock_node(dest);
        bgp_dest_unlock_node(dest);
 
-       return CMD_SUCCESS;
+       return 0;
 }
 
-static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
-                            safi_t safi, const char *rmap,
-                            uint8_t summary_only, uint8_t as_set,
-                            uint8_t origin, bool match_med)
+int bgp_aggregate_set(struct bgp *bgp, struct prefix *prefix, afi_t afi,
+                     safi_t safi, const char *rmap, uint8_t summary_only,
+                     uint8_t as_set, uint8_t origin, bool match_med,
+                     const char *suppress_map,
+                     char *errmsg, size_t errmsg_len)
 {
-       VTY_DECLVAR_CONTEXT(bgp, bgp);
        int ret;
-       struct prefix p;
        struct bgp_dest *dest;
        struct bgp_aggregate *aggregate;
        uint8_t as_set_new = as_set;
+       char buf[PREFIX2STR_BUFFER];
 
-       /* Convert string to prefix structure. */
-       ret = str2prefix(prefix_str, &p);
-       if (!ret) {
-               vty_out(vty, "Malformed prefix\n");
-               return CMD_WARNING_CONFIG_FAILED;
+       if (suppress_map && summary_only) {
+               snprintf(errmsg, errmsg_len,
+                       "'summary-only' and 'suppress-map' can't be used at the same time\n");
+               return -1;
        }
-       apply_mask(&p);
 
-       if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
-           (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
-               vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
-                       prefix_str);
-               return CMD_WARNING_CONFIG_FAILED;
+       apply_mask(prefix);
+
+       if ((afi == AFI_IP && prefix->prefixlen == IPV4_MAX_BITLEN)
+           || (afi == AFI_IP6 && prefix->prefixlen == IPV6_MAX_BITLEN)) {
+               snprintf(
+                       errmsg, errmsg_len,
+                       "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
+                       prefix2str(prefix, buf, PREFIX_STRLEN));
+               return -1;
        }
 
        /* Old configuration check. */
-       dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
+       dest = bgp_node_get(bgp->aggregate[afi][safi], prefix);
        aggregate = bgp_dest_get_bgp_aggregate_info(dest);
 
        if (aggregate) {
-               vty_out(vty, "There is already same aggregate network.\n");
+               snprintf(errmsg, errmsg_len,
+                        "There is already same aggregate network.\n");
                /* try to remove the old entry */
-               ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
+               ret = bgp_aggregate_unset(bgp, prefix, afi, safi, errmsg,
+                                         errmsg_len);
                if (ret) {
-                       vty_out(vty, "Error deleting aggregate.\n");
+                       snprintf(errmsg, errmsg_len,
+                                "Error deleting aggregate.\n");
                        bgp_dest_unlock_node(dest);
-                       return CMD_WARNING_CONFIG_FAILED;
+                       return -1;
                }
        }
 
@@ -7237,7 +7502,8 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
                        zlog_warn(
                                "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
                                __func__);
-                       vty_out(vty,
+                       snprintf(
+                               errmsg, errmsg_len,
                                "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
                }
        }
@@ -7259,39 +7525,55 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
                aggregate->rmap.map = route_map_lookup_by_name(rmap);
                route_map_counter_increment(aggregate->rmap.map);
        }
+
+       if (suppress_map) {
+               XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
+               route_map_counter_decrement(aggregate->suppress_map);
+
+               aggregate->suppress_map_name =
+                       XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
+               aggregate->suppress_map =
+                       route_map_lookup_by_name(aggregate->suppress_map_name);
+               route_map_counter_increment(aggregate->suppress_map);
+       }
+
        bgp_dest_set_bgp_aggregate_info(dest, aggregate);
 
        /* Aggregate address insert into BGP routing table. */
-       bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
+       bgp_aggregate_route(bgp, prefix, afi, safi, aggregate);
 
-       return CMD_SUCCESS;
+       return 0;
 }
 
-DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
-      "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
-      "as-set$as_set_s"
-      "|summary-only$summary_only"
-      "|route-map WORD$rmap_name"
-      "|origin <egp|igp|incomplete>$origin_s"
-      "|matching-MED-only$match_med"
-      "}",
-      NO_STR
-      "Configure BGP aggregate entries\n"
-      "Aggregate prefix\n" "Aggregate address\n" "Aggregate mask\n"
-      "Generate AS set path information\n"
-      "Filter more specific routes from updates\n"
-      "Apply route map to aggregate network\n"
-      "Route map name\n"
-      "BGP origin code\n"
-      "Remote EGP\n"
-      "Local IGP\n"
-      "Unknown heritage\n"
-      "Only aggregate routes with matching MED\n")
-{
-       const char *prefix_s = NULL;
+DEFPY_YANG(
+       aggregate_addressv4, aggregate_addressv4_cmd,
+       "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
+       "as-set$as_set_s"
+       "|summary-only$summary_only"
+       "|route-map WORD$rmap_name"
+       "|origin <egp|igp|incomplete>$origin_s"
+       "|matching-MED-only$match_med"
+       "|suppress-map WORD$suppress_map"
+       "}",
+       NO_STR
+       "Configure BGP aggregate entries\n"
+       "Aggregate prefix\n"
+       "Aggregate address\n"
+       "Aggregate mask\n"
+       "Generate AS set path information\n"
+       "Filter more specific routes from updates\n"
+       "Apply route map to aggregate network\n"
+       "Route map name\n"
+       "BGP origin code\n"
+       "Remote EGP\n"
+       "Local IGP\n"
+       "Unknown heritage\n"
+       "Only aggregate routes with matching MED\n"
+       "Suppress the selected more specific routes\n"
+       "Route map with the route selectors\n")
+{
+       char base_xpath[XPATH_MAXLEN];
        safi_t safi = bgp_node_safi(vty);
-       uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
-       int as_set = AGGREGATE_AS_UNSET;
        char prefix_buf[PREFIX2STR_BUFFER];
 
        if (addr_str) {
@@ -7300,75 +7582,158 @@ DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
                        vty_out(vty, "%% Inconsistent address and mask\n");
                        return CMD_WARNING_CONFIG_FAILED;
                }
-               prefix_s = prefix_buf;
-       } else
-               prefix_s = prefix_str;
-
-       if (origin_s) {
-               if (strcmp(origin_s, "egp") == 0)
-                       origin = BGP_ORIGIN_EGP;
-               else if (strcmp(origin_s, "igp") == 0)
-                       origin = BGP_ORIGIN_IGP;
-               else if (strcmp(origin_s, "incomplete") == 0)
-                       origin = BGP_ORIGIN_INCOMPLETE;
+       } else {
+               strlcpy(prefix_buf, prefix_str, sizeof(prefix_buf));
        }
 
-       if (as_set_s)
-               as_set = AGGREGATE_AS_SET;
+       if (!no && origin_s)
+               nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
+
+       if (!no && as_set_s)
+               nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
+       else
+               nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
+
+       if (!no && summary_only)
+               nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
+                                     "true");
+       else
+               nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
+                                     "false");
+
+       if (!no && match_med)
+               nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
+       else
+               nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
+                                     "false");
+
+       if (rmap_name)
+               nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
+                                     rmap_name);
+       else
+               nb_cli_enqueue_change(vty, "./rmap-policy-export",
+                                     NB_OP_DESTROY, NULL);
+
+       if (suppress_map)
+               nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
+                                     suppress_map);
+       else
+               nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
+                                     NULL);
+
+       snprintf(
+               base_xpath, sizeof(base_xpath),
+               "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
+               yang_afi_safi_value2identity(AFI_IP, safi),
+               bgp_afi_safi_get_container_str(AFI_IP, safi), prefix_buf);
 
-       /* Handle configuration removal, otherwise installation. */
        if (no)
-               return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
-
-       return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
-                                summary_only != NULL, as_set, origin,
-                                match_med != NULL);
-}
-
-DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
-      "[no] aggregate-address X:X::X:X/M$prefix {"
-      "as-set$as_set_s"
-      "|summary-only$summary_only"
-      "|route-map WORD$rmap_name"
-      "|origin <egp|igp|incomplete>$origin_s"
-      "|matching-MED-only$match_med"
-      "}",
-      NO_STR
-      "Configure BGP aggregate entries\n"
-      "Aggregate prefix\n"
-      "Generate AS set path information\n"
-      "Filter more specific routes from updates\n"
-      "Apply route map to aggregate network\n"
-      "Route map name\n"
-      "BGP origin code\n"
-      "Remote EGP\n"
-      "Local IGP\n"
-      "Unknown heritage\n"
-      "Only aggregate routes with matching MED\n")
-{
-       uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
-       int as_set = AGGREGATE_AS_UNSET;
-
-       if (origin_s) {
-               if (strcmp(origin_s, "egp") == 0)
-                       origin = BGP_ORIGIN_EGP;
-               else if (strcmp(origin_s, "igp") == 0)
-                       origin = BGP_ORIGIN_IGP;
-               else if (strcmp(origin_s, "incomplete") == 0)
-                       origin = BGP_ORIGIN_INCOMPLETE;
-       }
-
-       if (as_set_s)
-               as_set = AGGREGATE_AS_SET;
-
-       /* Handle configuration removal, otherwise installation. */
+               nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
+       else
+               nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
+
+       return nb_cli_apply_changes(vty, base_xpath);
+}
+
+DEFPY_YANG(aggregate_addressv6, aggregate_addressv6_cmd,
+          "[no] aggregate-address X:X::X:X/M$prefix {"
+          "as-set$as_set_s"
+          "|summary-only$summary_only"
+          "|route-map WORD$rmap_name"
+          "|origin <egp|igp|incomplete>$origin_s"
+          "|matching-MED-only$match_med"
+          "|suppress-map WORD$suppress_map"
+          "}",
+          NO_STR
+          "Configure BGP aggregate entries\n"
+          "Aggregate prefix\n"
+          "Generate AS set path information\n"
+          "Filter more specific routes from updates\n"
+          "Apply route map to aggregate network\n"
+          "Route map name\n"
+          "BGP origin code\n"
+          "Remote EGP\n"
+          "Local IGP\n"
+          "Unknown heritage\n"
+          "Only aggregate routes with matching MED\n"
+          "Suppress the selected more specific routes\n"
+          "Route map with the route selectors\n")
+{
+       char base_xpath[XPATH_MAXLEN];
+       safi_t safi = bgp_node_safi(vty);
+
+       if (!no && origin_s)
+               nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
+
+       if (!no && as_set_s)
+               nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
+       else
+               nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
+
+       if (!no && summary_only)
+               nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
+                                     "true");
+       else
+               nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
+                                     "false");
+
+       if (!no && match_med)
+               nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
+       else
+               nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
+                                     "false");
+
+       if (rmap_name)
+               nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
+                                     rmap_name);
+
+       if (suppress_map)
+               nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
+                                     suppress_map);
+       else
+               nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
+                                     NULL);
+
+       snprintf(
+               base_xpath, sizeof(base_xpath),
+               "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
+               yang_afi_safi_value2identity(AFI_IP6, safi),
+               bgp_afi_safi_get_container_str(AFI_IP6, safi), prefix_str);
+
        if (no)
-               return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
-                                          SAFI_UNICAST);
+               nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
+       else
+               nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
+
+       return nb_cli_apply_changes(vty, base_xpath);
+}
+
+void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
+       struct vty *vty, struct lyd_node *dnode, bool show_defaults)
+{
+       uint8_t origin;
+
+       vty_out(vty, "  aggregate-address %s",
+               yang_dnode_get_string(dnode, "./prefix"));
 
-       return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
-                                rmap_name, summary_only != NULL, as_set,
-                                origin, match_med != NULL);
+       if (yang_dnode_get_bool(dnode, "./as-set"))
+               vty_out(vty, " as-set");
+
+       if (yang_dnode_get_bool(dnode, "./summary-only"))
+               vty_out(vty, " summary-only");
+
+       if (yang_dnode_exists(dnode, "./rmap-policy-export"))
+               vty_out(vty, " route-map %s",
+                       yang_dnode_get_string(dnode, "./rmap-policy-export"));
+
+       origin = yang_dnode_get_enum(dnode, "./origin");
+       if (origin != BGP_ORIGIN_UNSPECIFIED)
+               vty_out(vty, " origin %s", bgp_origin2str(origin));
+
+       if (yang_dnode_get_bool(dnode, "./match-med"))
+               vty_out(vty, " matching-MED-only");
+
+       vty_out(vty, "\n");
 }
 
 /* Redistribute route treatment. */
@@ -7613,10 +7978,7 @@ static void route_vty_out_route(const struct prefix *p, struct vty *vty,
 
        if (p->family == AF_INET) {
                if (!json) {
-                       len = vty_out(
-                               vty, "%s/%d",
-                               inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
-                               p->prefixlen);
+                       len = vty_out(vty, "%pFX", p);
                } else {
                        json_object_string_add(json, "prefix",
                                               inet_ntop(p->family,
@@ -7627,14 +7989,10 @@ static void route_vty_out_route(const struct prefix *p, struct vty *vty,
                        json_object_string_add(json, "network", buf2);
                }
        } else if (p->family == AF_ETHERNET) {
-               prefix2str(p, buf, PREFIX_STRLEN);
-               len = vty_out(vty, "%s", buf);
+               len = vty_out(vty, "%pFX", p);
        } else if (p->family == AF_EVPN) {
                if (!json)
-                       len = vty_out(
-                               vty, "%s",
-                               bgp_evpn_route2str((struct prefix_evpn *)p, buf,
-                                                  BUFSIZ));
+                       len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
                else
                        bgp_evpn_route2json((struct prefix_evpn *)p, json);
        } else if (p->family == AF_FLOWSPEC) {
@@ -7644,10 +8002,7 @@ static void route_vty_out_route(const struct prefix *p, struct vty *vty,
                               NLRI_STRING_FORMAT_MIN, json);
        } else {
                if (!json)
-                       len = vty_out(
-                               vty, "%s/%d",
-                               inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
-                               p->prefixlen);
+                       len = vty_out(vty, "%pFX", p);
                else {
                        json_object_string_add(json, "prefix",
                                                inet_ntop(p->family,
@@ -7686,7 +8041,7 @@ static void route_vty_short_status_out(struct vty *vty,
                if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
                        json_object_boolean_true_add(json_path, "stale");
 
-               if (path->extra && path->extra->suppress)
+               if (path->extra && bgp_path_suppressed(path))
                        json_object_boolean_true_add(json_path, "suppressed");
 
                if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
@@ -7723,7 +8078,7 @@ static void route_vty_short_status_out(struct vty *vty,
                vty_out(vty, "R");
        else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
                vty_out(vty, "S");
-       else if (path->extra && path->extra->suppress)
+       else if (bgp_path_suppressed(path))
                vty_out(vty, "s");
        else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
                 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
@@ -7893,10 +8248,14 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
                }
        } else if (safi == SAFI_EVPN) {
                if (json_paths) {
+                       char buf[BUFSIZ] = {0};
+
                        json_nexthop_global = json_object_new_object();
 
                        json_object_string_add(json_nexthop_global, "ip",
-                                              inet_ntoa(attr->nexthop));
+                                              inet_ntop(AF_INET,
+                                                        &attr->nexthop, buf,
+                                                        sizeof(buf)));
 
                        if (path->peer->hostname)
                                json_object_string_add(json_nexthop_global,
@@ -7924,13 +8283,16 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
        } else if (safi == SAFI_FLOWSPEC) {
                if (attr->nexthop.s_addr != INADDR_ANY) {
                        if (json_paths) {
+                               char buf[BUFSIZ] = {0};
+
                                json_nexthop_global = json_object_new_object();
 
                                json_object_string_add(json_nexthop_global,
                                                       "afi", "ipv4");
                                json_object_string_add(
                                        json_nexthop_global, "ip",
-                                       inet_ntoa(attr->nexthop));
+                                       inet_ntop(AF_INET, &attr->nexthop, buf,
+                                                 sizeof(buf)));
 
                                if (path->peer->hostname)
                                        json_object_string_add(
@@ -7960,10 +8322,14 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
                }
        } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
                if (json_paths) {
+                       char buf[BUFSIZ] = {0};
+
                        json_nexthop_global = json_object_new_object();
 
                        json_object_string_add(json_nexthop_global, "ip",
-                                              inet_ntoa(attr->nexthop));
+                                              inet_ntop(AF_INET,
+                                                        &attr->nexthop, buf,
+                                                        sizeof(buf)));
 
                        if (path->peer->hostname)
                                json_object_string_add(json_nexthop_global,
@@ -8271,18 +8637,24 @@ void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
        /* Print attribute */
        if (attr) {
                if (use_json) {
+                       char buf[BUFSIZ] = {0};
+
                        if (p->family == AF_INET
                            && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
                                || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
                                if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
                                        json_object_string_add(
                                                json_net, "nextHop",
-                                               inet_ntoa(
-                                                       attr->mp_nexthop_global_in));
+                                               inet_ntop(
+                                                       AF_INET,
+                                                       &attr->mp_nexthop_global_in,
+                                                       buf, sizeof(buf)));
                                else
                                        json_object_string_add(
                                                json_net, "nextHop",
-                                               inet_ntoa(attr->nexthop));
+                                               inet_ntop(AF_INET,
+                                                         &attr->nexthop, buf,
+                                                         sizeof(buf)));
                        } else if (p->family == AF_INET6
                                   || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
                                char buf[BUFSIZ];
@@ -8292,11 +8664,16 @@ void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
                                        inet_ntop(AF_INET6,
                                                  &attr->mp_nexthop_global, buf,
                                                  BUFSIZ));
-                       } else if (p->family == AF_EVPN &&
-                                  !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
-                               json_object_string_add(json_net,
-                                       "nextHop", inet_ntoa(
-                                       attr->mp_nexthop_global_in));
+                       } else if (p->family == AF_EVPN
+                                  && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
+                               char buf[BUFSIZ] = {0};
+
+                               json_object_string_add(
+                                       json_net, "nextHop",
+                                       inet_ntop(AF_INET,
+                                                 &attr->mp_nexthop_global_in,
+                                                 buf, sizeof(buf)));
+                       }
 
                        if (attr->flag
                            & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
@@ -8324,15 +8701,12 @@ void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
                                || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
                                if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
                                    || safi == SAFI_EVPN)
-                                       vty_out(vty, "%-16s",
-                                               inet_ntoa(
-                                                       attr->mp_nexthop_global_in));
+                                       vty_out(vty, "%-16pI4",
+                                               &attr->mp_nexthop_global_in);
                                else if (wide)
-                                       vty_out(vty, "%-41s",
-                                               inet_ntoa(attr->nexthop));
+                                       vty_out(vty, "%-41pI4", &attr->nexthop);
                                else
-                                       vty_out(vty, "%-16s",
-                                               inet_ntoa(attr->nexthop));
+                                       vty_out(vty, "%-16pI4", &attr->nexthop);
                        } else if (p->family == AF_INET6
                                   || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
                                char buf[BUFSIZ];
@@ -8417,22 +8791,27 @@ void route_vty_out_tag(struct vty *vty, const struct prefix *p,
             && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
            || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
            || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
+               char buf[BUFSIZ] = {0};
+
                if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
                    || safi == SAFI_EVPN) {
                        if (json)
                                json_object_string_add(
                                        json_out, "mpNexthopGlobalIn",
-                                       inet_ntoa(attr->mp_nexthop_global_in));
+                                       inet_ntop(AF_INET,
+                                                 &attr->mp_nexthop_global_in,
+                                                 buf, sizeof(buf)));
                        else
-                               vty_out(vty, "%-16s",
-                                       inet_ntoa(attr->mp_nexthop_global_in));
+                               vty_out(vty, "%-16pI4",
+                                       &attr->mp_nexthop_global_in);
                } else {
                        if (json)
                                json_object_string_add(
                                        json_out, "nexthop",
-                                       inet_ntoa(attr->nexthop));
+                                       inet_ntop(AF_INET, &attr->nexthop, buf,
+                                                 sizeof(buf)));
                        else
-                               vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
+                               vty_out(vty, "%-16pI4", &attr->nexthop);
                }
        } else if (((p->family == AF_INET6)
                    && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
@@ -8941,7 +9320,6 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
 {
        char buf[INET6_ADDRSTRLEN];
        char buf1[BUFSIZ];
-       char buf2[EVPN_ROUTE_STRLEN];
        struct attr *attr = path->attr;
        int sockunion_vty_out(struct vty *, union sockunion *);
        time_t tbuf;
@@ -8979,7 +9357,6 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
        if (path->extra) {
                char tag_buf[30];
 
-               buf2[0] = '\0';
                tag_buf[0] = '\0';
                if (path->extra && path->extra->num_labels) {
                        bgp_evpn_label2str(path->extra->label,
@@ -8988,11 +9365,9 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
                }
                if (safi == SAFI_EVPN) {
                        if (!json_paths) {
-                               bgp_evpn_route2str(
+                               vty_out(vty, "  Route %pFX",
                                        (struct prefix_evpn *)
-                                               bgp_dest_get_prefix(bn),
-                                       buf2, sizeof(buf2));
-                               vty_out(vty, "  Route %s", buf2);
+                                               bgp_dest_get_prefix(bn));
                                if (tag_buf[0] != '\0')
                                        vty_out(vty, " VNI %s", tag_buf);
                                vty_out(vty, "\n");
@@ -9016,14 +9391,20 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
                                                pdest),
                                        buf1, sizeof(buf1));
                                if (is_pi_family_evpn(parent_ri)) {
-                                       bgp_evpn_route2str(
+                                       vty_out(vty,
+                                               "  Imported from %s:%pFX, VNI %s\n",
+                                               buf1,
                                                (struct prefix_evpn *)
                                                        bgp_dest_get_prefix(
                                                                dest),
-                                               buf2, sizeof(buf2));
-                                       vty_out(vty, "  Imported from %s:%s, VNI %s\n", buf1, buf2, tag_buf);
+                                               tag_buf);
                                } else
-                                       vty_out(vty, "  Imported from %s:%s\n", buf1, buf2);
+                                       vty_out(vty,
+                                               "  Imported from %s:%pFX\n",
+                                               buf1,
+                                               (struct prefix_evpn *)
+                                                       bgp_dest_get_prefix(
+                                                               dest));
                        }
                }
        }
@@ -9060,11 +9441,14 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
 
        if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
                if (json_paths) {
+                       char buf[BUFSIZ] = {0};
+
                        json_object_int_add(json_path, "aggregatorAs",
                                            attr->aggregator_as);
-                       json_object_string_add(
-                               json_path, "aggregatorId",
-                               inet_ntoa(attr->aggregator_addr));
+                       json_object_string_add(json_path, "aggregatorId",
+                                              inet_ntop(AF_INET,
+                                                        &attr->aggregator_addr,
+                                                        buf, sizeof(buf)));
                        if (attr->aggregator_as == BGP_AS_ZERO)
                                json_object_boolean_true_add(
                                        json_path, "aggregatorAsMalformed");
@@ -9074,13 +9458,13 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
                } else {
                        if (attr->aggregator_as == BGP_AS_ZERO)
                                vty_out(vty,
-                                       ", (aggregated by %u(malformed) %s)",
+                                       ", (aggregated by %u(malformed) %pI4)",
                                        attr->aggregator_as,
-                                       inet_ntoa(attr->aggregator_addr));
+                                       &attr->aggregator_addr);
                        else
-                               vty_out(vty, ", (aggregated by %u %s)",
+                               vty_out(vty, ", (aggregated by %u %pI4)",
                                        attr->aggregator_as,
-                                       inet_ntoa(attr->aggregator_addr));
+                                       &attr->aggregator_addr);
                }
        }
 
@@ -9127,12 +9511,16 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
             || bn_p->family == AF_EVPN)
            && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
                || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
+               char buf[BUFSIZ] = {0};
+
                if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
                    || safi == SAFI_EVPN) {
                        if (json_paths) {
                                json_object_string_add(
                                        json_nexthop_global, "ip",
-                                       inet_ntoa(attr->mp_nexthop_global_in));
+                                       inet_ntop(AF_INET,
+                                                 &attr->mp_nexthop_global_in,
+                                                 buf, sizeof(buf)));
 
                                if (path->peer->hostname)
                                        json_object_string_add(
@@ -9151,7 +9539,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
                        if (json_paths) {
                                json_object_string_add(
                                        json_nexthop_global, "ip",
-                                       inet_ntoa(attr->nexthop));
+                                       inet_ntop(AF_INET, &attr->nexthop, buf,
+                                                 sizeof(buf)));
 
                                if (path->peer->hostname)
                                        json_object_string_add(
@@ -9248,11 +9637,16 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
                                vty_out(vty, " from :: ");
                }
 
-               if (json_paths)
+               if (json_paths) {
+                       char buf[BUFSIZ] = {0};
+
                        json_object_string_add(json_peer, "routerId",
-                                              inet_ntoa(bgp->router_id));
-               else
-                       vty_out(vty, "(%s)", inet_ntoa(bgp->router_id));
+                                              inet_ntop(AF_INET,
+                                                        &bgp->router_id, buf,
+                                                        sizeof(buf)));
+               } else {
+                       vty_out(vty, "(%pI4)", &bgp->router_id);
+               }
        }
 
        /* We RXed this path from one of our peers */
@@ -9305,8 +9699,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
                        }
 
                        if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
-                               vty_out(vty, " (%s)",
-                                       inet_ntoa(attr->originator_id));
+                               vty_out(vty, " (%pI4)", &attr->originator_id);
                        else
                                vty_out(vty, " (%s)",
                                        inet_ntop(AF_INET,
@@ -9616,14 +10009,17 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
        /* Line 7 display Originator, Cluster-id */
        if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
            || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
+               char buf[BUFSIZ] = {0};
+
                if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
                        if (json_paths)
                                json_object_string_add(
                                        json_path, "originatorId",
-                                       inet_ntoa(attr->originator_id));
+                                       inet_ntop(AF_INET, &attr->originator_id,
+                                                 buf, sizeof(buf)));
                        else
-                               vty_out(vty, "      Originator: %s",
-                                       inet_ntoa(attr->originator_id));
+                               vty_out(vty, "      Originator: %pI4",
+                                       &attr->originator_id);
                }
 
                if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
@@ -9637,8 +10033,10 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
                                for (i = 0; i < attr->cluster->length / 4;
                                     i++) {
                                        json_string = json_object_new_string(
-                                               inet_ntoa(attr->cluster
-                                                                 ->list[i]));
+                                               inet_ntop(
+                                                       AF_INET,
+                                                       &attr->cluster->list[i],
+                                                       buf, sizeof(buf)));
                                        json_object_array_add(
                                                json_cluster_list_list,
                                                json_string);
@@ -9662,9 +10060,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
 
                                for (i = 0; i < attr->cluster->length / 4;
                                     i++) {
-                                       vty_out(vty, "%s ",
-                                               inet_ntoa(attr->cluster
-                                                                 ->list[i]));
+                                       vty_out(vty, "%pI4 ",
+                                               &attr->cluster->list[i]);
                                }
                        }
                }
@@ -9888,13 +10285,14 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
                }
 
                vty_out(vty,
-                       " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
+                       " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
+                       ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
                        " \"localAS\": %u,\n \"routes\": { ",
                        bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
                        bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
-                                               ? VRF_DEFAULT_NAME
-                                               : bgp->name,
-                       table->version, inet_ntoa(bgp->router_id),
+                               ? VRF_DEFAULT_NAME
+                               : bgp->name,
+                       table->version, &bgp->router_id,
                        bgp->default_local_pref, bgp->as);
                if (rd) {
                        vty_out(vty, " \"routeDistinguishers\" : {");
@@ -10072,9 +10470,10 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
                        }
 
                        if (!use_json && header) {
-                               vty_out(vty, "BGP table version is %" PRIu64", local router ID is %s, vrf id ",
-                                       table->version,
-                                       inet_ntoa(bgp->router_id));
+                               vty_out(vty,
+                                       "BGP table version is %" PRIu64
+                                       ", local router ID is %pI4, vrf id ",
+                                       table->version, &bgp->router_id);
                                if (bgp->vrf_id == VRF_UNKNOWN)
                                        vty_out(vty, "%s", VRFID_NONE_STR);
                                else
@@ -10337,8 +10736,6 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
        struct peer *peer;
        struct listnode *node, *nnode;
        char buf1[RD_ADDRSTRLEN];
-       char buf2[INET6_ADDRSTRLEN];
-       char buf3[EVPN_ROUTE_STRLEN];
        char prefix_str[BUFSIZ];
        int count = 0;
        int best = 0;
@@ -10370,11 +10767,10 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
        if (safi == SAFI_EVPN) {
 
                if (!json) {
-                       vty_out(vty, "BGP routing table entry for %s%s%s\n",
+                       vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
                                prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
-                               : "", prd ? ":" : "",
-                               bgp_evpn_route2str((struct prefix_evpn *)p,
-                               buf3, sizeof(buf3)));
+                                   : "",
+                               prd ? ":" : "", (struct prefix_evpn *)p);
                } else {
                        json_object_string_add(json, "rd",
                                prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
@@ -10383,15 +10779,12 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
                }
        } else {
                if (!json) {
-                       vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
+                       vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
                                ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
-                                ? prefix_rd2str(prd, buf1,
-                                        sizeof(buf1))
-                                : ""),
-                               safi == SAFI_MPLS_VPN ? ":" : "",
-                               inet_ntop(p->family, &p->u.prefix, buf2,
-                                       INET6_ADDRSTRLEN),
-                               p->prefixlen);
+                                        ? prefix_rd2str(prd, buf1,
+                                                        sizeof(buf1))
+                                        : ""),
+                               safi == SAFI_MPLS_VPN ? ":" : "", p);
 
                } else
                        json_object_string_add(json, "prefix",
@@ -10413,7 +10806,7 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
                count++;
                if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
                        best = count;
-                       if (pi->extra && pi->extra->suppress)
+                       if (bgp_path_suppressed(pi))
                                suppress = 1;
 
                        if (pi->attr->community == NULL)
@@ -12409,12 +12802,15 @@ static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
                                  json_object *json_ocode, bool wide)
 {
        uint64_t version = table ? table->version : 0;
+       char buf[BUFSIZ] = {0};
 
        if (*header1) {
                if (json) {
                        json_object_int_add(json, "bgpTableVersion", version);
                        json_object_string_add(json, "bgpLocalRouterId",
-                                              inet_ntoa(bgp->router_id));
+                                              inet_ntop(AF_INET,
+                                                        &bgp->router_id, buf,
+                                                        sizeof(buf)));
                        json_object_int_add(json, "defaultLocPrf",
                                            bgp->default_local_pref);
                        json_object_int_add(json, "localAS", bgp->as);
@@ -12424,8 +12820,9 @@ static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
                                               json_ocode);
                } else {
                        vty_out(vty,
-                               "BGP table version is %" PRIu64 ", local router ID is %s, vrf id ",
-                               version, inet_ntoa(bgp->router_id));
+                               "BGP table version is %" PRIu64
+                               ", local router ID is %pI4, vrf id ",
+                               version, &bgp->router_id);
                        if (bgp->vrf_id == VRF_UNKNOWN)
                                vty_out(vty, "%s", VRFID_NONE_STR);
                        else
@@ -12517,11 +12914,15 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
 
        if (type == bgp_show_adj_route_advertised && subgrp
            && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
+               char buf[BUFSIZ] = {0};
+
                if (use_json) {
                        json_object_int_add(json, "bgpTableVersion",
                                            table->version);
                        json_object_string_add(json, "bgpLocalRouterId",
-                                              inet_ntoa(bgp->router_id));
+                                              inet_ntop(AF_INET,
+                                                        &bgp->router_id, buf,
+                                                        sizeof(buf)));
                        json_object_int_add(json, "defaultLocPrf",
                                                bgp->default_local_pref);
                        json_object_int_add(json, "localAS", bgp->as);
@@ -12533,8 +12934,10 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
                                json, "bgpOriginatingDefaultNetwork",
                                (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
                } else {
-                       vty_out(vty, "BGP table version is %" PRIu64", local router ID is %s, vrf id ",
-                               table->version, inet_ntoa(bgp->router_id));
+                       vty_out(vty,
+                               "BGP table version is %" PRIu64
+                               ", local router ID is %pI4, vrf id ",
+                               table->version, &bgp->router_id);
                        if (bgp->vrf_id == VRF_UNKNOWN)
                                vty_out(vty, "%s", VRFID_NONE_STR);
                        else
@@ -12999,10 +13402,6 @@ static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
        if (use_json)
                SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
 
-       /* labeled-unicast routes live in the unicast table */
-       if (safi == SAFI_LABELED_UNICAST)
-               safi = SAFI_UNICAST;
-
        if (!peer || !peer->afc[afi][safi]) {
                if (use_json) {
                        json_object *json_no = NULL;
@@ -13018,6 +13417,10 @@ static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
                return CMD_WARNING;
        }
 
+       /* labeled-unicast routes live in the unicast table */
+       if (safi == SAFI_LABELED_UNICAST)
+               safi = SAFI_UNICAST;
+
        return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags);
 }
 
@@ -13160,28 +13563,21 @@ static void bgp_distance_free(struct bgp_distance *bdistance)
        XFREE(MTYPE_BGP_DISTANCE, bdistance);
 }
 
-static int bgp_distance_set(struct vty *vty, const char *distance_str,
-                           const char *ip_str, const char *access_list_str)
+int bgp_distance_set(uint8_t distance, const char *ip_str,
+                    const char *access_list_str, afi_t afi, safi_t safi,
+                    char *errmsg, size_t errmsg_len)
 {
        int ret;
-       afi_t afi;
-       safi_t safi;
        struct prefix p;
-       uint8_t distance;
        struct bgp_dest *dest;
        struct bgp_distance *bdistance;
 
-       afi = bgp_node_afi(vty);
-       safi = bgp_node_safi(vty);
-
        ret = str2prefix(ip_str, &p);
        if (ret == 0) {
-               vty_out(vty, "Malformed prefix\n");
+               snprintf(errmsg, errmsg_len, "Malformed prefix\n");
                return CMD_WARNING_CONFIG_FAILED;
        }
 
-       distance = atoi(distance_str);
-
        /* Get BGP distance node. */
        dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
        bdistance = bgp_dest_get_bgp_distance_info(dest);
@@ -13204,37 +13600,32 @@ static int bgp_distance_set(struct vty *vty, const char *distance_str,
        return CMD_SUCCESS;
 }
 
-static int bgp_distance_unset(struct vty *vty, const char *distance_str,
-                             const char *ip_str, const char *access_list_str)
+int bgp_distance_unset(uint8_t distance, const char *ip_str,
+                      const char *access_list_str, afi_t afi, safi_t safi,
+                      char *errmsg, size_t errmsg_len)
 {
        int ret;
-       afi_t afi;
-       safi_t safi;
        struct prefix p;
-       int distance;
        struct bgp_dest *dest;
        struct bgp_distance *bdistance;
 
-       afi = bgp_node_afi(vty);
-       safi = bgp_node_safi(vty);
-
        ret = str2prefix(ip_str, &p);
        if (ret == 0) {
-               vty_out(vty, "Malformed prefix\n");
+               snprintf(errmsg, errmsg_len, "Malformed prefix\n");
                return CMD_WARNING_CONFIG_FAILED;
        }
 
        dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
        if (!dest) {
-               vty_out(vty, "Can't find specified prefix\n");
+               snprintf(errmsg, errmsg_len, "Can't find specified prefix\n");
                return CMD_WARNING_CONFIG_FAILED;
        }
 
        bdistance = bgp_dest_get_bgp_distance_info(dest);
-       distance = atoi(distance_str);
 
        if (bdistance->distance != distance) {
-               vty_out(vty, "Distance does not match configured\n");
+               snprintf(errmsg, errmsg_len,
+                        "Distance does not match configured\n");
                return CMD_WARNING_CONFIG_FAILED;
        }
 
@@ -13312,9 +13703,8 @@ uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
  * we should tell ZEBRA update the routes for a specific
  * AFI/SAFI to reflect changes in RIB.
  */
-static void bgp_announce_routes_distance_update(struct bgp *bgp,
-                                               afi_t update_afi,
-                                               safi_t update_safi)
+void bgp_announce_routes_distance_update(struct bgp *bgp, afi_t update_afi,
+                                        safi_t update_safi)
 {
        afi_t afi;
        safi_t safi;
@@ -13334,237 +13724,228 @@ static void bgp_announce_routes_distance_update(struct bgp *bgp,
        }
 }
 
-DEFUN (bgp_distance,
-       bgp_distance_cmd,
-       "distance bgp (1-255) (1-255) (1-255)",
-       "Define an administrative distance\n"
-       "BGP distance\n"
-       "Distance for routes external to the AS\n"
-       "Distance for routes internal to the AS\n"
-       "Distance for local routes\n")
+DEFUN_YANG(bgp_distance, bgp_distance_cmd,
+          "distance bgp (1-255) (1-255) (1-255)",
+          "Define an administrative distance\n"
+          "BGP distance\n"
+          "Distance for routes external to the AS\n"
+          "Distance for routes internal to the AS\n"
+          "Distance for local routes\n")
 {
-       VTY_DECLVAR_CONTEXT(bgp, bgp);
        int idx_number = 2;
        int idx_number_2 = 3;
        int idx_number_3 = 4;
-       int distance_ebgp = atoi(argv[idx_number]->arg);
-       int distance_ibgp = atoi(argv[idx_number_2]->arg);
-       int distance_local = atoi(argv[idx_number_3]->arg);
        afi_t afi;
        safi_t safi;
+       char xpath[XPATH_MAXLEN];
 
        afi = bgp_node_afi(vty);
        safi = bgp_node_safi(vty);
 
-       if (bgp->distance_ebgp[afi][safi] != distance_ebgp
-           || bgp->distance_ibgp[afi][safi] != distance_ibgp
-           || bgp->distance_local[afi][safi] != distance_local) {
-               bgp->distance_ebgp[afi][safi] = distance_ebgp;
-               bgp->distance_ibgp[afi][safi] = distance_ibgp;
-               bgp->distance_local[afi][safi] = distance_local;
-               bgp_announce_routes_distance_update(bgp, afi, safi);
-       }
-       return CMD_SUCCESS;
-}
+       snprintf(
+               xpath, sizeof(xpath),
+               "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
+               yang_afi_safi_value2identity(afi, safi),
+               bgp_afi_safi_get_container_str(afi, safi));
+       nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[idx_number]->arg);
+       snprintf(
+               xpath, sizeof(xpath),
+               "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
+               yang_afi_safi_value2identity(afi, safi),
+               bgp_afi_safi_get_container_str(afi, safi));
+       nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
+                             argv[idx_number_2]->arg);
+       snprintf(
+               xpath, sizeof(xpath),
+               "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
+               yang_afi_safi_value2identity(afi, safi),
+               bgp_afi_safi_get_container_str(afi, safi));
+
+       nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
+                             argv[idx_number_3]->arg);
+
+       return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFUN_YANG(no_bgp_distance, no_bgp_distance_cmd,
+          "no distance bgp [(1-255) (1-255) (1-255)]",
+          NO_STR
+          "Define an administrative distance\n"
+          "BGP distance\n"
+          "Distance for routes external to the AS\n"
+          "Distance for routes internal to the AS\n"
+          "Distance for local routes\n")
+{
+       afi_t afi;
+       safi_t safi;
+       char xpath[XPATH_MAXLEN];
 
-DEFUN (no_bgp_distance,
-       no_bgp_distance_cmd,
-       "no distance bgp [(1-255) (1-255) (1-255)]",
-       NO_STR
-       "Define an administrative distance\n"
-       "BGP distance\n"
-       "Distance for routes external to the AS\n"
-       "Distance for routes internal to the AS\n"
-       "Distance for local routes\n")
+       afi = bgp_node_afi(vty);
+       safi = bgp_node_safi(vty);
+
+       snprintf(
+               xpath, sizeof(xpath),
+               "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
+               yang_afi_safi_value2identity(afi, safi),
+               bgp_afi_safi_get_container_str(afi, safi));
+       nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
+       snprintf(
+               xpath, sizeof(xpath),
+               "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
+               yang_afi_safi_value2identity(afi, safi),
+               bgp_afi_safi_get_container_str(afi, safi));
+       nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
+       snprintf(
+               xpath, sizeof(xpath),
+               "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
+               yang_afi_safi_value2identity(afi, safi),
+               bgp_afi_safi_get_container_str(afi, safi));
+
+       nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
+
+       return nb_cli_apply_changes(vty, NULL);
+}
+
+void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty *vty,
+                                                       struct lyd_node *dnode,
+                                                       bool show_defaults)
+{
+       uint8_t distance_ebgp, distance_ibgp, distance_local;
+
+       distance_ebgp = yang_dnode_get_uint8(dnode, "./external");
+       distance_ibgp = yang_dnode_get_uint8(dnode, "./internal");
+       distance_local = yang_dnode_get_uint8(dnode, "./local");
+
+       vty_out(vty, "  distance bgp %d %d %d\n", distance_ebgp, distance_ibgp,
+               distance_local);
+}
+
+DEFPY_YANG(bgp_distance_source,
+          bgp_distance_source_cmd,
+          "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
+          NO_STR
+          "Define an administrative distance\n"
+          "Distance value\n"
+          "IPv4 source prefix\n"
+          "IPv6 source prefix\n"
+          "Access list name\n")
 {
-       VTY_DECLVAR_CONTEXT(bgp, bgp);
        afi_t afi;
        safi_t safi;
+       char xpath[XPATH_MAXLEN];
 
        afi = bgp_node_afi(vty);
        safi = bgp_node_safi(vty);
 
-       if (bgp->distance_ebgp[afi][safi] != 0
-           || bgp->distance_ibgp[afi][safi] != 0
-           || bgp->distance_local[afi][safi] != 0) {
-               bgp->distance_ebgp[afi][safi] = 0;
-               bgp->distance_ibgp[afi][safi] = 0;
-               bgp->distance_local[afi][safi] = 0;
-               bgp_announce_routes_distance_update(bgp, afi, safi);
+       if (!no) {
+               nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
+               nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY,
+                                     distance_str);
+               if (acl)
+                       nb_cli_enqueue_change(vty,
+                                             "./access-list-policy-export",
+                                             NB_OP_CREATE, acl);
+               else
+                       nb_cli_enqueue_change(vty,
+                                             "./access-list-policy-export",
+                                             NB_OP_DESTROY, NULL);
+       } else {
+               nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
        }
-       return CMD_SUCCESS;
-}
 
+       snprintf(
+               xpath, sizeof(xpath),
+               "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
+               yang_afi_safi_value2identity(afi, safi),
+               bgp_afi_safi_get_container_str(afi, safi), prefix_str);
 
-DEFUN (bgp_distance_source,
-       bgp_distance_source_cmd,
-       "distance (1-255) A.B.C.D/M",
-       "Define an administrative distance\n"
-       "Administrative distance\n"
-       "IP source prefix\n")
-{
-       int idx_number = 1;
-       int idx_ipv4_prefixlen = 2;
-       bgp_distance_set(vty, argv[idx_number]->arg,
-                        argv[idx_ipv4_prefixlen]->arg, NULL);
-       return CMD_SUCCESS;
+       return nb_cli_apply_changes(vty, xpath);
 }
 
-DEFUN (no_bgp_distance_source,
-       no_bgp_distance_source_cmd,
-       "no distance (1-255) A.B.C.D/M",
-       NO_STR
-       "Define an administrative distance\n"
-       "Administrative distance\n"
-       "IP source prefix\n")
+void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
+       struct vty *vty, struct lyd_node *dnode, bool show_defaults)
 {
-       int idx_number = 2;
-       int idx_ipv4_prefixlen = 3;
-       bgp_distance_unset(vty, argv[idx_number]->arg,
-                          argv[idx_ipv4_prefixlen]->arg, NULL);
-       return CMD_SUCCESS;
+       vty_out(vty, "  distance %d %s %s\n",
+               yang_dnode_get_uint8(dnode, "./distance"),
+               yang_dnode_get_string(dnode, "./prefix"),
+               (yang_dnode_exists(dnode, "./access-list-policy-export"))
+                       ? yang_dnode_get_string(dnode,
+                                               "./access-list-policy-export")
+                       : "");
 }
 
-DEFUN (bgp_distance_source_access_list,
-       bgp_distance_source_access_list_cmd,
-       "distance (1-255) A.B.C.D/M WORD",
-       "Define an administrative distance\n"
-       "Administrative distance\n"
-       "IP source prefix\n"
-       "Access list name\n")
+DEFPY_YANG(bgp_dampening,
+          bgp_dampening_cmd,
+          "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_supress]]",
+          NO_STR
+          "BGP Specific commands\n"
+          "Enable route-flap dampening\n"
+          "Half-life time for the penalty\n"
+          "Value to start reusing a route\n"
+          "Value to start suppressing a route\n"
+          "Maximum duration to suppress a stable route\n")
 {
-       int idx_number = 1;
-       int idx_ipv4_prefixlen = 2;
-       int idx_word = 3;
-       bgp_distance_set(vty, argv[idx_number]->arg,
-                        argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
-       return CMD_SUCCESS;
-}
+       afi_t afi;
+       safi_t safi;
+       char xpath[XPATH_MAXLEN];
 
-DEFUN (no_bgp_distance_source_access_list,
-       no_bgp_distance_source_access_list_cmd,
-       "no distance (1-255) A.B.C.D/M WORD",
-       NO_STR
-       "Define an administrative distance\n"
-       "Administrative distance\n"
-       "IP source prefix\n"
-       "Access list name\n")
-{
-       int idx_number = 2;
-       int idx_ipv4_prefixlen = 3;
-       int idx_word = 4;
-       bgp_distance_unset(vty, argv[idx_number]->arg,
-                          argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
-       return CMD_SUCCESS;
-}
+       afi = bgp_node_afi(vty);
+       safi = bgp_node_safi(vty);
 
-DEFUN (ipv6_bgp_distance_source,
-       ipv6_bgp_distance_source_cmd,
-       "distance (1-255) X:X::X:X/M",
-       "Define an administrative distance\n"
-       "Administrative distance\n"
-       "IP source prefix\n")
-{
-       bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
-       return CMD_SUCCESS;
-}
+       if (!no) {
+               nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
+               if (argc == 6) {
+                       nb_cli_enqueue_change(vty, "./reach-decay",
+                                             NB_OP_MODIFY, halflife_str);
+                       nb_cli_enqueue_change(vty, "./reuse-above",
+                                             NB_OP_MODIFY, reuse_str);
+                       nb_cli_enqueue_change(vty, "./suppress-above",
+                                             NB_OP_MODIFY, suppress_str);
+                       nb_cli_enqueue_change(vty, "./unreach-decay",
+                                             NB_OP_MODIFY, max_supress_str);
+               } if (argc == 3) {
+                       nb_cli_enqueue_change(vty, "./reach-decay",
+                                             NB_OP_MODIFY, halflife_str);
+               }
+       } else {
+               nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "false");
+       }
 
-DEFUN (no_ipv6_bgp_distance_source,
-       no_ipv6_bgp_distance_source_cmd,
-       "no distance (1-255) X:X::X:X/M",
-       NO_STR
-       "Define an administrative distance\n"
-       "Administrative distance\n"
-       "IP source prefix\n")
-{
-       bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
-       return CMD_SUCCESS;
-}
+       snprintf(
+               xpath, sizeof(xpath),
+               "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
+               yang_afi_safi_value2identity(afi, safi),
+               bgp_afi_safi_get_container_str(afi, safi));
 
-DEFUN (ipv6_bgp_distance_source_access_list,
-       ipv6_bgp_distance_source_access_list_cmd,
-       "distance (1-255) X:X::X:X/M WORD",
-       "Define an administrative distance\n"
-       "Administrative distance\n"
-       "IP source prefix\n"
-       "Access list name\n")
-{
-       bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
-       return CMD_SUCCESS;
+       return nb_cli_apply_changes(vty, xpath);
 }
 
-DEFUN (no_ipv6_bgp_distance_source_access_list,
-       no_ipv6_bgp_distance_source_access_list_cmd,
-       "no distance (1-255) X:X::X:X/M WORD",
-       NO_STR
-       "Define an administrative distance\n"
-       "Administrative distance\n"
-       "IP source prefix\n"
-       "Access list name\n")
+void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty *vty,
+                                                      struct lyd_node *dnode,
+                                                      bool show_defaults)
 {
-       bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
-       return CMD_SUCCESS;
-}
+       if (!yang_dnode_get_bool(dnode, "./enable"))
+               return;
 
-DEFUN (bgp_damp_set,
-       bgp_damp_set_cmd,
-       "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
-       "BGP Specific commands\n"
-       "Enable route-flap dampening\n"
-       "Half-life time for the penalty\n"
-       "Value to start reusing a route\n"
-       "Value to start suppressing a route\n"
-       "Maximum duration to suppress a stable route\n")
-{
-       VTY_DECLVAR_CONTEXT(bgp, bgp);
-       int idx_half_life = 2;
-       int idx_reuse = 3;
-       int idx_suppress = 4;
-       int idx_max_suppress = 5;
        int half = DEFAULT_HALF_LIFE * 60;
        int reuse = DEFAULT_REUSE;
        int suppress = DEFAULT_SUPPRESS;
-       int max = 4 * half;
-
-       if (argc == 6) {
-               half = atoi(argv[idx_half_life]->arg) * 60;
-               reuse = atoi(argv[idx_reuse]->arg);
-               suppress = atoi(argv[idx_suppress]->arg);
-               max = atoi(argv[idx_max_suppress]->arg) * 60;
-       } else if (argc == 3) {
-               half = atoi(argv[idx_half_life]->arg) * 60;
-               max = 4 * half;
-       }
-
-       /*
-        * These can't be 0 but our SA doesn't understand the
-        * way our cli is constructed
-        */
-       assert(reuse);
-       assert(half);
-       if (suppress < reuse) {
-               vty_out(vty,
-                       "Suppress value cannot be less than reuse value \n");
-               return 0;
-       }
-
-       return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
-                              reuse, suppress, max);
-}
-
-DEFUN (bgp_damp_unset,
-       bgp_damp_unset_cmd,
-       "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
-       NO_STR
-       "BGP Specific commands\n"
-       "Enable route-flap dampening\n"
-       "Half-life time for the penalty\n"
-       "Value to start reusing a route\n"
-       "Value to start suppressing a route\n"
-       "Maximum duration to suppress a stable route\n")
-{
-       VTY_DECLVAR_CONTEXT(bgp, bgp);
-       return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
+       int max;
+
+       half = yang_dnode_get_uint8(dnode, "../reach-decay");
+       reuse = yang_dnode_get_uint16(dnode, "../reuse-above");
+       suppress = yang_dnode_get_uint16(dnode, "../suppress-above");
+       max = yang_dnode_get_uint8(dnode, "../unreach-decay");
+
+       if (half == DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
+           && suppress == DEFAULT_SUPPRESS && max == half * 4)
+               vty_out(vty, "  bgp dampening\n");
+       else if (half != DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
+                && suppress == DEFAULT_SUPPRESS && max == half * 4)
+               vty_out(vty, "  bgp dampening %u\n", half);
+       else
+               vty_out(vty, "  bgp dampening %u %d %d %d\n", half, reuse,
+                       suppress, max);
 }
 
 /* Display specified route of BGP table. */
@@ -13785,7 +14166,6 @@ static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
        const struct prefix_rd *prd;
        struct bgp_static *bgp_static;
        mpls_label_t label;
-       char buf[SU_ADDRSTRLEN];
        char rdbuf[RD_ADDRSTRLEN];
 
        /* Network configuration. */
@@ -13809,10 +14189,7 @@ static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
                        prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
                        label = decode_label(&bgp_static->label);
 
-                       vty_out(vty, "  network %s/%d rd %s",
-                               inet_ntop(p->family, &p->u.prefix, buf,
-                                         SU_ADDRSTRLEN),
-                               p->prefixlen, rdbuf);
+                       vty_out(vty, "  network %pFX rd %s", p, rdbuf);
                        if (safi == SAFI_MPLS_VPN)
                                vty_out(vty, " label %u", label);
 
@@ -13910,7 +14287,6 @@ void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
        const struct prefix *p;
        struct bgp_static *bgp_static;
        struct bgp_aggregate *bgp_aggregate;
-       char buf[SU_ADDRSTRLEN];
 
        if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
                bgp_config_write_network_vpn(vty, bgp, afi, safi);
@@ -13931,9 +14307,7 @@ void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
 
                p = bgp_dest_get_prefix(dest);
 
-               vty_out(vty, "  network %s/%d",
-                       inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
-                       p->prefixlen);
+               vty_out(vty, "  network %pFX", p);
 
                if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
                        vty_out(vty, " label-index %u",
@@ -13957,9 +14331,7 @@ void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
 
                p = bgp_dest_get_prefix(dest);
 
-               vty_out(vty, "  aggregate-address %s/%d",
-                       inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
-                       p->prefixlen);
+               vty_out(vty, "  aggregate-address %pFX", p);
 
                if (bgp_aggregate->as_set)
                        vty_out(vty, " as-set");
@@ -13977,6 +14349,10 @@ void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
                if (bgp_aggregate->match_med)
                        vty_out(vty, " matching-MED-only");
 
+               if (bgp_aggregate->suppress_map_name)
+                       vty_out(vty, " suppress-map %s",
+                               bgp_aggregate->suppress_map_name);
+
                vty_out(vty, "\n");
        }
 }
@@ -14004,7 +14380,7 @@ void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
             dest = bgp_route_next(dest)) {
                bdistance = bgp_dest_get_bgp_distance_info(dest);
                if (bdistance != NULL)
-                       vty_out(vty, "  distance %d %pRN %s\n",
+                       vty_out(vty, "  distance %d %pBD %s\n",
                                bdistance->distance, dest,
                                bdistance->access_list ? bdistance->access_list
                                                       : "");
@@ -14099,54 +14475,27 @@ void bgp_route_init(void)
        install_element(BGP_NODE, &bgp_distance_cmd);
        install_element(BGP_NODE, &no_bgp_distance_cmd);
        install_element(BGP_NODE, &bgp_distance_source_cmd);
-       install_element(BGP_NODE, &no_bgp_distance_source_cmd);
-       install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
-       install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
        install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
        install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
        install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
-       install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
-       install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
-       install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
        install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
        install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
        install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
-       install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
-       install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
-       install_element(BGP_IPV4M_NODE,
-                       &no_bgp_distance_source_access_list_cmd);
        install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
        install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
-       install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
-       install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
-       install_element(BGP_IPV6_NODE,
-                       &ipv6_bgp_distance_source_access_list_cmd);
-       install_element(BGP_IPV6_NODE,
-                       &no_ipv6_bgp_distance_source_access_list_cmd);
+       install_element(BGP_IPV6_NODE, &bgp_distance_source_cmd);
        install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
        install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
-       install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
-       install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
-       install_element(BGP_IPV6M_NODE,
-                       &ipv6_bgp_distance_source_access_list_cmd);
-       install_element(BGP_IPV6M_NODE,
-                       &no_ipv6_bgp_distance_source_access_list_cmd);
+       install_element(BGP_IPV6M_NODE, &bgp_distance_source_cmd);
 
        /* BGP dampening */
-       install_element(BGP_NODE, &bgp_damp_set_cmd);
-       install_element(BGP_NODE, &bgp_damp_unset_cmd);
-       install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
-       install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
-       install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
-       install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
-       install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
-       install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
-       install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
-       install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
-       install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
-       install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
-       install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
-       install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
+       install_element(BGP_NODE, &bgp_dampening_cmd);
+       install_element(BGP_IPV4_NODE, &bgp_dampening_cmd);
+       install_element(BGP_IPV4M_NODE, &bgp_dampening_cmd);
+       install_element(BGP_IPV4L_NODE, &bgp_dampening_cmd);
+       install_element(BGP_IPV6_NODE, &bgp_dampening_cmd);
+       install_element(BGP_IPV6M_NODE, &bgp_dampening_cmd);
+       install_element(BGP_IPV6L_NODE, &bgp_dampening_cmd);
 
        /* Large Communities */
        install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);