]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgpd.c
Merge pull request #3367 from karamalla0406/frr3333
[mirror_frr.git] / bgpd / bgpd.c
index 552244b2f651e440efc8417736a68bd83749aeb9..48a3b1bb0902a9bfe27cd62bb3ffaf1e3d416cde 100644 (file)
@@ -85,6 +85,7 @@
 #include "bgpd/bgp_flowspec.h"
 #include "bgpd/bgp_labelpool.h"
 #include "bgpd/bgp_pbr.h"
+#include "bgpd/bgp_addpath.h"
 
 DEFINE_MTYPE_STATIC(BGPD, PEER_TX_SHUTDOWN_MSG, "Peer shutdown message (TX)");
 DEFINE_QOBJ_TYPE(bgp_master)
@@ -170,6 +171,7 @@ int bgp_option_set(int flag)
        case BGP_OPT_MULTIPLE_INSTANCE:
        case BGP_OPT_CONFIG_CISCO:
        case BGP_OPT_NO_LISTEN:
+       case BGP_OPT_NO_ZEBRA:
                SET_FLAG(bm->options, flag);
                break;
        default:
@@ -185,6 +187,7 @@ int bgp_option_unset(int flag)
                if (listcount(bm->bgp) > 1)
                        return BGP_ERR_MULTIPLE_INSTANCE_USED;
        /* Fall through.  */
+       case BGP_OPT_NO_ZEBRA:
        case BGP_OPT_NO_FIB:
        case BGP_OPT_CONFIG_CISCO:
                UNSET_FLAG(bm->options, flag);
@@ -271,6 +274,10 @@ void bgp_router_id_zebra_bump(vrf_id_t vrf_id, const struct prefix *router_id)
 {
        struct listnode *node, *nnode;
        struct bgp *bgp;
+       struct in_addr *addr = NULL;
+
+       if (router_id != NULL)
+               addr = (struct in_addr *)&(router_id->u.prefix4);
 
        if (vrf_id == VRF_DEFAULT) {
                /* Router-id change for default VRF has to also update all
@@ -279,17 +286,43 @@ void bgp_router_id_zebra_bump(vrf_id_t vrf_id, const struct prefix *router_id)
                        if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
                                continue;
 
-                       bgp->router_id_zebra = router_id->u.prefix4;
-                       if (!bgp->router_id_static.s_addr)
-                               bgp_router_id_set(bgp, &router_id->u.prefix4);
+                       if (addr)
+                               bgp->router_id_zebra = *addr;
+                       else
+                               addr = &bgp->router_id_zebra;
+
+                       if (!bgp->router_id_static.s_addr) {
+                               /* Router ID is updated if there are no active
+                                * peer sessions
+                                */
+                               if (bgp->established_peers == 0) {
+                                       if (BGP_DEBUG(zebra, ZEBRA))
+                                               zlog_debug("RID change : vrf %u, RTR ID %s",
+                                       bgp->vrf_id, inet_ntoa(*addr));
+                                       bgp_router_id_set(bgp, addr);
+                               }
+                       }
                }
        } else {
                bgp = bgp_lookup_by_vrf_id(vrf_id);
                if (bgp) {
-                       bgp->router_id_zebra = router_id->u.prefix4;
+                       if (addr)
+                               bgp->router_id_zebra = *addr;
+                       else
+                               addr = &bgp->router_id_zebra;
+
+                       if (!bgp->router_id_static.s_addr) {
+                               /* Router ID is updated if there are no active
+                                * peer sessions
+                                */
+                               if (bgp->established_peers == 0) {
+                                       if (BGP_DEBUG(zebra, ZEBRA))
+                                               zlog_debug("RID change : vrf %u, RTR ID %s",
+                                       bgp->vrf_id, inet_ntoa(*addr));
+                                       bgp_router_id_set(bgp, addr);
+                               }
+                       }
 
-                       if (!bgp->router_id_static.s_addr)
-                               bgp_router_id_set(bgp, &router_id->u.prefix4);
                }
        }
 }
@@ -769,7 +802,7 @@ static unsigned int peer_hash_key_make(void *p)
        return sockunion_hash(&peer->su);
 }
 
-static int peer_hash_same(const void *p1, const void *p2)
+static bool peer_hash_same(const void *p1, const void *p2)
 {
        const struct peer *peer1 = p1;
        const struct peer *peer2 = p2;
@@ -883,6 +916,31 @@ static bool peergroup_filter_check(struct peer *peer, afi_t afi, safi_t safi,
        }
 }
 
+/* Return true if the addpath type is set for peer and different from
+ * peer-group.
+ */
+static int peergroup_af_addpath_check(struct peer *peer, afi_t afi, safi_t safi)
+{
+       enum bgp_addpath_strat type, g_type;
+
+       type = peer->addpath_type[afi][safi];
+
+       if (type != BGP_ADDPATH_NONE) {
+               if (peer_group_active(peer)) {
+                       g_type = peer->group->conf->addpath_type[afi][safi];
+
+                       if (type != g_type)
+                               return 1;
+                       else
+                               return 0;
+               }
+
+               return 1;
+       }
+
+       return 0;
+}
+
 /* Check peer's AS number and determines if this peer is IBGP or EBGP */
 static inline bgp_peer_sort_t peer_calc_sort(struct peer *peer)
 {
@@ -960,6 +1018,9 @@ bgp_peer_sort_t peer_sort(struct peer *peer)
 
 static void peer_free(struct peer *peer)
 {
+       afi_t afi;
+       safi_t safi;
+
        assert(peer->status == Deleted);
 
        QOBJ_UNREG(peer);
@@ -1032,6 +1093,13 @@ static void peer_free(struct peer *peer)
 
        bfd_info_free(&(peer->bfd_info));
 
+       for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+               for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
+                       bgp_addpath_set_peer_type(peer, afi, safi,
+                                                BGP_ADDPATH_NONE);
+               }
+       }
+
        bgp_unlock(peer->bgp);
 
        memset(peer, 0, sizeof(struct peer));
@@ -1118,6 +1186,7 @@ struct peer *peer_new(struct bgp *bgp)
                        SET_FLAG(peer->af_flags_invert[afi][safi],
                                 PEER_FLAG_SEND_LARGE_COMMUNITY);
                }
+               peer->addpath_type[afi][safi] = BGP_ADDPATH_NONE;
        }
 
        /* set nexthop-unchanged for l2vpn evpn by default */
@@ -1210,6 +1279,8 @@ void peer_xfer_config(struct peer *peer_dst, struct peer *peer_src)
                peer_dst->allowas_in[afi][safi] =
                        peer_src->allowas_in[afi][safi];
                peer_dst->weight[afi][safi] = peer_src->weight[afi][safi];
+               peer_dst->addpath_type[afi][safi] =
+                       peer_src->addpath_type[afi][safi];
        }
 
        for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) {
@@ -1422,7 +1493,15 @@ void bgp_recalculate_all_bestpaths(struct bgp *bgp)
        }
 }
 
-/* Create new BGP peer.  */
+/*
+ * Create new BGP peer.
+ *
+ * conf_if and su are mutually exclusive if configuring from the cli.
+ * If we are handing a doppelganger, then we *must* pass in both
+ * the original peer's su and conf_if, so that we can appropriately
+ * track the bgp->peerhash( ie we don't want to remove the current
+ * one from the config ).
+ */
 struct peer *peer_create(union sockunion *su, const char *conf_if,
                         struct bgp *bgp, as_t local_as, as_t remote_as,
                         int as_type, afi_t afi, safi_t safi,
@@ -1435,7 +1514,10 @@ struct peer *peer_create(union sockunion *su, const char *conf_if,
        peer = peer_new(bgp);
        if (conf_if) {
                peer->conf_if = XSTRDUP(MTYPE_PEER_CONF_IF, conf_if);
-               bgp_peer_conf_if_to_su_update(peer);
+               if (su)
+                       peer->su = *su;
+               else
+                       bgp_peer_conf_if_to_su_update(peer);
                if (peer->host)
                        XFREE(MTYPE_BGP_PEER_HOST, peer->host);
                peer->host = XSTRDUP(MTYPE_BGP_PEER_HOST, conf_if);
@@ -1797,11 +1879,17 @@ static void peer_group2peer_config_copy_af(struct peer_group *group,
                                      MTYPE_BGP_FILTER_NAME);
                PEER_ATTR_INHERIT(peer, group, filter[afi][safi].usmap.map);
        }
+
+       if (peer->addpath_type[afi][safi] == BGP_ADDPATH_NONE) {
+               peer->addpath_type[afi][safi] = conf->addpath_type[afi][safi];
+               bgp_addpath_type_changed(conf->bgp);
+       }
 }
 
 static int peer_activate_af(struct peer *peer, afi_t afi, safi_t safi)
 {
        int active;
+       struct peer *other;
 
        if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
                flog_err(EC_BGP_PEER_GROUP, "%s was called for peer-group %s",
@@ -1852,6 +1940,23 @@ static int peer_activate_af(struct peer *peer, afi_t afi, safi_t safi)
                        bgp_notify_send(peer, BGP_NOTIFY_CEASE,
                                        BGP_NOTIFY_CEASE_CONFIG_CHANGE);
                }
+               /*
+                * If we are turning on a AFI/SAFI locally and we've
+                * started bringing a peer up, we need to tell
+                * the other peer to restart because we might loose
+                * configuration here because when the doppelganger
+                * gets to a established state due to how
+                * we resolve we could just overwrite the afi/safi
+                * activation.
+                */
+               other = peer->doppelganger;
+               if (other
+                   && (other->status == OpenSent
+                       || other->status == OpenConfirm)) {
+                       other->last_reset = PEER_DOWN_AF_ACTIVATE;
+                       bgp_notify_send(other, BGP_NOTIFY_CEASE,
+                                       BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+               }
        }
 
        return 0;
@@ -2426,14 +2531,14 @@ int peer_group_delete(struct peer_group *group)
                        peer_delete(other);
                }
        }
-       list_delete_and_null(&group->peer);
+       list_delete(&group->peer);
 
        for (afi = AFI_IP; afi < AFI_MAX; afi++) {
                for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode,
                                       prefix)) {
                        prefix_free(prefix);
                }
-               list_delete_and_null(&group->listen_range[afi]);
+               list_delete(&group->listen_range[afi]);
        }
 
        XFREE(MTYPE_PEER_GROUP_HOST, group->name);
@@ -2807,7 +2912,7 @@ static struct bgp *bgp_create(as_t *as, const char *name,
 #if DFLT_BGP_DETERMINISTIC_MED
        bgp_flag_set(bgp, BGP_FLAG_DETERMINISTIC_MED);
 #endif
-       bgp->addpath_tx_id = BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE;
+       bgp_addpath_init_bgp_data(&bgp->tx_addpath);
 
        bgp->as = *as;
 
@@ -3022,6 +3127,8 @@ int bgp_get(struct bgp **bgp_val, as_t *as, const char *name,
        }
 
        bgp = bgp_create(as, name, inst_type);
+       if (bgp_option_check(BGP_OPT_NO_ZEBRA) && name)
+               bgp->vrf_id = vrf_generate_id();
        bgp_router_id_set(bgp, &bgp->router_id_zebra);
        bgp_address_init(bgp);
        bgp_tip_hash_init(bgp);
@@ -3043,9 +3150,12 @@ int bgp_get(struct bgp **bgp_val, as_t *as, const char *name,
        bgp_handle_socket(bgp, vrf, VRF_UNKNOWN, true);
        listnode_add(bm->bgp, bgp);
 
-       if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
+       if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
+               if (BGP_DEBUG(zebra, ZEBRA))
+                       zlog_debug("%s: Registering BGP instance %s to zebra",
+                                  __PRETTY_FUNCTION__, name);
                bgp_zebra_instance_register(bgp);
-
+       }
 
        return 0;
 }
@@ -3189,8 +3299,12 @@ int bgp_delete(struct bgp *bgp)
        }
 
        /* Deregister from Zebra, if needed */
-       if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
+       if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
+               if (BGP_DEBUG(zebra, ZEBRA))
+                       zlog_debug("%s: deregistering this bgp %s instance from zebra",
+                                  __PRETTY_FUNCTION__, bgp->name);
                bgp_zebra_instance_deregister(bgp);
+       }
 
        /* Remove visibility via the master list - there may however still be
         * routes to be processed still referencing the struct bgp.
@@ -3221,8 +3335,8 @@ void bgp_free(struct bgp *bgp)
 
        QOBJ_UNREG(bgp);
 
-       list_delete_and_null(&bgp->group);
-       list_delete_and_null(&bgp->peer);
+       list_delete(&bgp->group);
+       list_delete(&bgp->peer);
 
        if (bgp->peerhash) {
                hash_free(bgp->peerhash);
@@ -3264,9 +3378,9 @@ void bgp_free(struct bgp *bgp)
                vpn_policy_direction_t dir;
 
                if (bgp->vpn_policy[afi].import_vrf)
-                       list_delete_and_null(&bgp->vpn_policy[afi].import_vrf);
+                       list_delete(&bgp->vpn_policy[afi].import_vrf);
                if (bgp->vpn_policy[afi].export_vrf)
-                       list_delete_and_null(&bgp->vpn_policy[afi].export_vrf);
+                       list_delete(&bgp->vpn_policy[afi].export_vrf);
 
                dir = BGP_VPN_POLICY_DIR_FROMVPN;
                if (bgp->vpn_policy[afi].rtlist[dir])
@@ -3591,15 +3705,7 @@ int peer_active_nego(struct peer *peer)
        return 0;
 }
 
-/* peer_flag_change_type. */
-enum peer_change_type {
-       peer_change_none,
-       peer_change_reset,
-       peer_change_reset_in,
-       peer_change_reset_out,
-};
-
-static void peer_change_action(struct peer *peer, afi_t afi, safi_t safi,
+void peer_change_action(struct peer *peer, afi_t afi, safi_t safi,
                               enum peer_change_type type)
 {
        if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
@@ -3695,8 +3801,6 @@ static const struct peer_flag_action peer_af_flag_action_list[] = {
        {PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE, 1, peer_change_reset_out},
        {PEER_FLAG_AS_OVERRIDE, 1, peer_change_reset_out},
        {PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE, 1, peer_change_reset_out},
-       {PEER_FLAG_ADDPATH_TX_ALL_PATHS, 1, peer_change_reset},
-       {PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS, 1, peer_change_reset},
        {PEER_FLAG_WEIGHT, 0, peer_change_reset_in},
        {0, 0, 0}};
 
@@ -3869,6 +3973,9 @@ static int peer_flag_modify(struct peer *peer, uint32_t flag, int set)
                return 0;
        }
 
+       if (set && flag == PEER_FLAG_CAPABILITY_ENHE)
+               bgp_nht_register_enhe_capability_interfaces(peer);
+
        /*
         * Update peer-group members, unless they are explicitely overriding
         * peer-group configuration.
@@ -3892,6 +3999,9 @@ static int peer_flag_modify(struct peer *peer, uint32_t flag, int set)
                /* Update flag on peer-group member. */
                COND_FLAG(member->flags, flag, set != member_invert);
 
+               if (set && flag == PEER_FLAG_CAPABILITY_ENHE)
+                       bgp_nht_register_enhe_capability_interfaces(member);
+
                /* Execute flag action on peer-group member. */
                if (action.type == peer_change_reset)
                        peer_flag_modify_action(member, flag);
@@ -3915,9 +4025,7 @@ static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
 {
        int found;
        int size;
-       int addpath_tx_used;
        bool invert, member_invert;
-       struct bgp *bgp;
        struct peer *member;
        struct listnode *node, *nnode;
        struct peer_flag_action action;
@@ -4080,45 +4188,6 @@ static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
                }
        }
 
-       /* Track if addpath TX is in use */
-       if (flag & (PEER_FLAG_ADDPATH_TX_ALL_PATHS
-                   | PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) {
-               bgp = peer->bgp;
-               addpath_tx_used = 0;
-
-               if (set) {
-                       addpath_tx_used = 1;
-
-                       if (flag & PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS) {
-                               if (!bgp_flag_check(
-                                           bgp, BGP_FLAG_DETERMINISTIC_MED)) {
-                                       zlog_info(
-                                               "%s: enabling bgp deterministic-med, this is required"
-                                               " for addpath-tx-bestpath-per-AS",
-                                               peer->host);
-                                       bgp_flag_set(
-                                               bgp,
-                                               BGP_FLAG_DETERMINISTIC_MED);
-                                       bgp_recalculate_all_bestpaths(bgp);
-                               }
-                       }
-               } else {
-                       for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode,
-                                              member)) {
-                               if (CHECK_FLAG(member->af_flags[afi][safi],
-                                              PEER_FLAG_ADDPATH_TX_ALL_PATHS)
-                                   || CHECK_FLAG(
-                                              member->af_flags[afi][safi],
-                                              PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) {
-                                       addpath_tx_used = 1;
-                                       break;
-                               }
-                       }
-               }
-
-               bgp->addpath_tx_used[afi][safi] = addpath_tx_used;
-       }
-
        return 0;
 }
 
@@ -4467,7 +4536,7 @@ int peer_update_source_unset(struct peer *peer)
 }
 
 int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi,
-                              const char *rmap)
+                              const char *rmap, struct route_map *route_map)
 {
        struct peer *member;
        struct listnode *node, *nnode;
@@ -4483,8 +4552,7 @@ int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi,
 
                        peer->default_rmap[afi][safi].name =
                                XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
-                       peer->default_rmap[afi][safi].map =
-                               route_map_lookup_by_name(rmap);
+                       peer->default_rmap[afi][safi].map = route_map;
                }
        } else if (!rmap) {
                if (peer->default_rmap[afi][safi].name)
@@ -4528,8 +4596,7 @@ int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi,
 
                        member->default_rmap[afi][safi].name =
                                XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
-                       member->default_rmap[afi][safi].map =
-                               route_map_lookup_by_name(rmap);
+                       member->default_rmap[afi][safi].map = route_map;
                }
 
                /* Update peer route announcements. */
@@ -5994,7 +6061,7 @@ static void peer_aslist_del(const char *aslist_name)
 
 
 int peer_route_map_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
-                      const char *name)
+                      const char *name, struct route_map *route_map)
 {
        struct peer *member;
        struct bgp_filter *filter;
@@ -6008,7 +6075,7 @@ int peer_route_map_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
        if (filter->map[direct].name)
                XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
        filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
-       filter->map[direct].map = route_map_lookup_by_name(name);
+       filter->map[direct].map = route_map;
 
        /* Check if handling a regular peer. */
        if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
@@ -6037,7 +6104,7 @@ int peer_route_map_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
                if (filter->map[direct].name)
                        XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
                filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
-               filter->map[direct].map = route_map_lookup_by_name(name);
+               filter->map[direct].map = route_map;
 
                /* Process peer route updates. */
                peer_on_policy_change(member, afi, safi,
@@ -6112,7 +6179,7 @@ int peer_route_map_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
 
 /* Set unsuppress-map to the peer. */
 int peer_unsuppress_map_set(struct peer *peer, afi_t afi, safi_t safi,
-                           const char *name)
+                           const char *name, struct route_map *route_map)
 {
        struct peer *member;
        struct bgp_filter *filter;
@@ -6123,7 +6190,7 @@ int peer_unsuppress_map_set(struct peer *peer, afi_t afi, safi_t safi,
        if (filter->usmap.name)
                XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
        filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
-       filter->usmap.map = route_map_lookup_by_name(name);
+       filter->usmap.map = route_map;
 
        /* Check if handling a regular peer. */
        if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
@@ -6151,7 +6218,7 @@ int peer_unsuppress_map_set(struct peer *peer, afi_t afi, safi_t safi,
                if (filter->usmap.name)
                        XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
                filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
-               filter->usmap.map = route_map_lookup_by_name(name);
+               filter->usmap.map = route_map;
 
                /* Process peer route updates. */
                peer_on_policy_change(member, afi, safi, 1);
@@ -6279,9 +6346,6 @@ int peer_maximum_prefix_set(struct peer *peer, afi_t afi, safi_t safi,
 
 int peer_maximum_prefix_unset(struct peer *peer, afi_t afi, safi_t safi)
 {
-       struct peer *member;
-       struct listnode *node, *nnode;
-
        /* Inherit configuration from peer-group if peer is member. */
        if (peer_group_active(peer)) {
                peer_af_flag_inherit(peer, afi, safi, PEER_FLAG_MAX_PREFIX);
@@ -6305,19 +6369,26 @@ int peer_maximum_prefix_unset(struct peer *peer, afi_t afi, safi_t safi)
         * Remove flags and configuration from all peer-group members, unless
         * they are explicitely overriding peer-group configuration.
         */
-       for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
-               /* Skip peers with overridden configuration. */
-               if (CHECK_FLAG(member->af_flags_override[afi][safi],
-                              PEER_FLAG_MAX_PREFIX))
-                       continue;
+       if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+               struct peer *member;
+               struct listnode *node;
 
-               /* Remove flag and configuration on peer-group member. */
-               UNSET_FLAG(member->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
-               UNSET_FLAG(member->af_flags[afi][safi],
-                          PEER_FLAG_MAX_PREFIX_WARNING);
-               member->pmax[afi][safi] = 0;
-               member->pmax_threshold[afi][safi] = 0;
-               member->pmax_restart[afi][safi] = 0;
+               for (ALL_LIST_ELEMENTS_RO(peer->group->peer, node, member)) {
+                       /* Skip peers with overridden configuration. */
+                       if (CHECK_FLAG(member->af_flags_override[afi][safi],
+                                      PEER_FLAG_MAX_PREFIX))
+                               continue;
+
+                       /* Remove flag and configuration on peer-group member.
+                        */
+                       UNSET_FLAG(member->af_flags[afi][safi],
+                                  PEER_FLAG_MAX_PREFIX);
+                       UNSET_FLAG(member->af_flags[afi][safi],
+                                  PEER_FLAG_MAX_PREFIX_WARNING);
+                       member->pmax[afi][safi] = 0;
+                       member->pmax_threshold[afi][safi] = 0;
+                       member->pmax_restart[afi][safi] = 0;
+               }
        }
 
        return 0;
@@ -7021,15 +7092,21 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
        }
 
        /* addpath TX knobs */
-       if (peergroup_af_flag_check(peer, afi, safi,
-                                   PEER_FLAG_ADDPATH_TX_ALL_PATHS)) {
-               vty_out(vty, "  neighbor %s addpath-tx-all-paths\n", addr);
-       }
-
-       if (peergroup_af_flag_check(peer, afi, safi,
-                                   PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) {
-               vty_out(vty, "  neighbor %s addpath-tx-bestpath-per-AS\n",
-                       addr);
+       if (peergroup_af_addpath_check(peer, afi, safi)) {
+               switch (peer->addpath_type[afi][safi]) {
+               case BGP_ADDPATH_ALL:
+                       vty_out(vty, "  neighbor %s addpath-tx-all-paths\n",
+                               addr);
+                       break;
+               case BGP_ADDPATH_BEST_PER_AS:
+                       vty_out(vty,
+                               "  neighbor %s addpath-tx-bestpath-per-AS\n",
+                               addr);
+                       break;
+               case BGP_ADDPATH_MAX:
+               case BGP_ADDPATH_NONE:
+                       break;
+               }
        }
 
        /* ORF capability.  */
@@ -7788,7 +7865,7 @@ void bgp_pthreads_finish()
        frr_pthread_finish();
 }
 
-void bgp_init(void)
+void bgp_init(unsigned short instance)
 {
 
        /* allocates some vital data structures used by peer commands in
@@ -7798,7 +7875,7 @@ void bgp_init(void)
        bgp_pthreads_init();
 
        /* Init zebra. */
-       bgp_zebra_init(bm->master);
+       bgp_zebra_init(bm->master, instance);
 
 #if ENABLE_BGP_VNC
        vnc_zebra_init(bm->master);
@@ -7864,7 +7941,7 @@ void bgp_terminate(void)
        bgp_close();
 
        if (bm->listen_sockets)
-               list_delete_and_null(&bm->listen_sockets);
+               list_delete(&bm->listen_sockets);
 
        for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp))
                for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))