]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_route.c
Merge pull request #3069 from donaldsharp/bgp_nexthop_address
[mirror_frr.git] / bgpd / bgp_route.c
index 1ded492a20a3594bfd4a3ea93583be27b45edbf4..a04ed8eef53489a19eb10cfadf00e830241950c2 100644 (file)
 #include "queue.h"
 #include "memory.h"
 #include "lib/json.h"
+#include "lib_errors.h"
 
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_table.h"
 #include "bgpd/bgp_route.h"
 #include "bgpd/bgp_attr.h"
 #include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_errors.h"
 #include "bgpd/bgp_aspath.h"
 #include "bgpd/bgp_regex.h"
 #include "bgpd/bgp_community.h"
@@ -187,8 +189,24 @@ static void bgp_info_extra_free(struct bgp_info_extra **extra)
        if (e->parent) {
                struct bgp_info *bi = (struct bgp_info *)e->parent;
 
-               if (bi->net)
-                       bi->net = bgp_unlock_node((struct bgp_node *)bi->net);
+               if (bi->net) {
+                       /* FIXME: since multiple e may have the same e->parent
+                        * and e->parent->net is holding a refcount for each
+                        * of them, we need to do some fudging here.
+                        *
+                        * WARNING: if bi->net->lock drops to 0, bi may be
+                        * freed as well (because bi->net was holding the
+                        * last reference to bi) => write after free!
+                        */
+                       unsigned refcount;
+
+                       bi = bgp_info_lock(bi);
+                       refcount = bi->net->lock - 1;
+                       bgp_unlock_node((struct bgp_node *)bi->net);
+                       if (!refcount)
+                               bi->net = NULL;
+                       bgp_info_unlock(bi);
+               }
                bgp_info_unlock(e->parent);
                e->parent = NULL;
        }
@@ -197,8 +215,7 @@ static void bgp_info_extra_free(struct bgp_info_extra **extra)
                bgp_unlock(e->bgp_orig);
 
        if ((*extra)->bgp_fs_pbr)
-               list_delete_all_node((*extra)->bgp_fs_pbr);
-       (*extra)->bgp_fs_pbr = NULL;
+               list_delete_and_null(&((*extra)->bgp_fs_pbr));
        XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
 
        *extra = NULL;
@@ -337,14 +354,9 @@ static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_info *ri)
                /* slight hack, but more robust against errors. */
                if (ri->peer->pcount[table->afi][table->safi])
                        ri->peer->pcount[table->afi][table->safi]--;
-               else {
-                       zlog_warn(
-                               "%s: Asked to decrement 0 prefix count for peer %s",
-                               __func__, ri->peer->host);
-                       zlog_backtrace(LOG_WARNING);
-                       zlog_warn("%s: Please report to Quagga bugzilla",
-                                 __func__);
-               }
+               else
+                       flog_err(EC_LIB_DEVELOPMENT,
+                                "Asked to decrement 0 prefix count for peer");
        } else if (BGP_INFO_COUNTABLE(ri)
                   && !CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) {
                SET_FLAG(ri->flags, BGP_INFO_COUNTED);
@@ -493,16 +505,18 @@ static int bgp_info_cmp(struct bgp *bgp, struct bgp_info *new,
                        }
 
                        if (newattr->sticky && !existattr->sticky) {
-                               zlog_warn(
-                                       "%s: %s wins over %s due to sticky MAC flag",
-                                       pfx_buf, new_buf, exist_buf);
+                               if (debug)
+                                       zlog_debug(
+                                               "%s: %s wins over %s due to sticky MAC flag",
+                                               pfx_buf, new_buf, exist_buf);
                                return 1;
                        }
 
                        if (!newattr->sticky && existattr->sticky) {
-                               zlog_warn(
-                                       "%s: %s loses to %s due to sticky MAC flag",
-                                       pfx_buf, new_buf, exist_buf);
+                               if (debug)
+                                       zlog_debug(
+                                               "%s: %s loses to %s due to sticky MAC flag",
+                                               pfx_buf, new_buf, exist_buf);
                                return 0;
                        }
                }
@@ -1036,8 +1050,8 @@ static enum filter_type bgp_input_filter(struct peer *peer, struct prefix *p,
 
 #define FILTER_EXIST_WARN(F, f, filter)                                        \
        if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter)))                 \
-               zlog_warn("%s: Could not find configured input %s-list %s!",   \
-                         peer->host, #f, F##_IN_NAME(filter));
+               zlog_debug("%s: Could not find configured input %s-list %s!",  \
+                          peer->host, #f, F##_IN_NAME(filter));
 
        if (DISTRIBUTE_IN_NAME(filter)) {
                FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
@@ -1075,8 +1089,8 @@ static enum filter_type bgp_output_filter(struct peer *peer, struct prefix *p,
 
 #define FILTER_EXIST_WARN(F, f, filter)                                        \
        if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter)))               \
-               zlog_warn("%s: Could not find configured output %s-list %s!",  \
-                         peer->host, #f, F##_OUT_NAME(filter));
+               zlog_debug("%s: Could not find configured output %s-list %s!", \
+                          peer->host, #f, F##_OUT_NAME(filter));
 
        if (DISTRIBUTE_OUT_NAME(filter)) {
                FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
@@ -4026,7 +4040,6 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
                for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
                     rn = bgp_route_next(rn)) {
                        struct bgp_node *rm;
-                       struct bgp_info *ri;
 
                        /* look for neighbor in tables */
                        if ((table = rn->info) == NULL)
@@ -4202,8 +4215,9 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
 
                /* Prefix length check. */
                if (p.prefixlen > prefix_blen(&p) * 8) {
-                       zlog_err(
-                               "%s [Error] Update packet error (wrong perfix length %d for afi %u)",
+                       flog_err(
+                               EC_BGP_UPDATE_RCV,
+                               "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
                                peer->host, p.prefixlen, packet->afi);
                        return -1;
                }
@@ -4213,7 +4227,8 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
 
                /* When packet overflow occur return immediately. */
                if (pnt + psize > lim) {
-                       zlog_err(
+                       flog_err(
+                               EC_BGP_UPDATE_RCV,
                                "%s [Error] Update packet error (prefix length %d overflows packet)",
                                peer->host, p.prefixlen);
                        return -1;
@@ -4222,7 +4237,8 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
                /* Defensive coding, double-check the psize fits in a struct
                 * prefix */
                if (psize > (ssize_t)sizeof(p.u)) {
-                       zlog_err(
+                       flog_err(
+                               EC_BGP_UPDATE_RCV,
                                "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
                                peer->host, p.prefixlen, sizeof(p.u));
                        return -1;
@@ -4243,7 +4259,8 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
                                 * be logged locally, and the prefix SHOULD be
                                 * ignored.
                                 */
-                               zlog_err(
+                               flog_err(
+                                       EC_BGP_UPDATE_RCV,
                                        "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
                                        peer->host, inet_ntoa(p.u.prefix4));
                                continue;
@@ -4255,7 +4272,8 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
                        if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
                                char buf[BUFSIZ];
 
-                               zlog_err(
+                               flog_err(
+                                       EC_BGP_UPDATE_RCV,
                                        "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
                                        peer->host,
                                        inet_ntop(AF_INET6, &p.u.prefix6, buf,
@@ -4266,7 +4284,8 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
                        if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
                                char buf[BUFSIZ];
 
-                               zlog_err(
+                               flog_err(
+                                       EC_BGP_UPDATE_RCV,
                                        "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
                                        peer->host,
                                        inet_ntop(AF_INET6, &p.u.prefix6, buf,
@@ -4295,7 +4314,8 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
 
        /* Packet length consistency check. */
        if (pnt != lim) {
-               zlog_err(
+               flog_err(
+                       EC_BGP_UPDATE_RCV,
                        "%s [Error] Update packet error (prefix length mismatch with total length)",
                        peer->host);
                return -1;
@@ -4707,7 +4727,6 @@ static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p,
                        break;
 
        if (ri) {
-               union gw_addr add;
                memset(&add, 0, sizeof(union gw_addr));
                if (attrhash_cmp(ri->attr, attr_new)
                    && overlay_index_equal(afi, ri, bgp_static->eth_s_id, &add)
@@ -4826,7 +4845,7 @@ static int bgp_static_set(struct vty *vty, const char *negate,
                        return CMD_WARNING_CONFIG_FAILED;
                }
 
-               bgp_static = rn->info;
+               bgp_static = bgp_static_get_node_info(rn);
 
                if ((label_index != BGP_INVALID_LABEL_INDEX)
                    && (label_index != bgp_static->label_index)) {
@@ -4848,7 +4867,7 @@ static int bgp_static_set(struct vty *vty, const char *negate,
 
                /* Clear configuration. */
                bgp_static_free(bgp_static);
-               rn->info = NULL;
+               bgp_static_set_node_info(rn, NULL);
                bgp_unlock_node(rn);
                bgp_unlock_node(rn);
        } else {
@@ -4856,10 +4875,9 @@ static int bgp_static_set(struct vty *vty, const char *negate,
                /* Set BGP static route configuration. */
                rn = bgp_node_get(bgp->route[afi][safi], &p);
 
-               if (rn->info) {
+               bgp_static = bgp_static_get_node_info(rn);
+               if (bgp_static) {
                        /* Configuration change. */
-                       bgp_static = rn->info;
-
                        /* Label index cannot be changed. */
                        if (bgp_static->label_index != label_index) {
                                vty_out(vty, "%% cannot change label-index\n");
@@ -4908,7 +4926,7 @@ static int bgp_static_set(struct vty *vty, const char *negate,
                                bgp_static->rmap.map =
                                        route_map_lookup_by_name(rmap);
                        }
-                       rn->info = bgp_static;
+                       bgp_static_set_node_info(rn, bgp_static);
                }
 
                bgp_static->valid = 1;
@@ -4943,14 +4961,16 @@ void bgp_static_add(struct bgp *bgp)
 
                                for (rm = bgp_table_top(table); rm;
                                     rm = bgp_route_next(rm)) {
-                                       bgp_static = rm->info;
+                                       bgp_static =
+                                               bgp_static_get_node_info(rm);
                                        bgp_static_update_safi(bgp, &rm->p,
                                                               bgp_static, afi,
                                                               safi);
                                }
                        } else {
-                               bgp_static_update(bgp, &rn->p, rn->info, afi,
-                                                 safi);
+                               bgp_static_update(bgp, &rn->p,
+                                                 bgp_static_get_node_info(rn),
+                                                 afi, safi);
                        }
                }
 }
@@ -4978,19 +4998,20 @@ void bgp_static_delete(struct bgp *bgp)
 
                                for (rm = bgp_table_top(table); rm;
                                     rm = bgp_route_next(rm)) {
-                                       bgp_static = rm->info;
+                                       bgp_static =
+                                               bgp_static_get_node_info(rm);
                                        bgp_static_withdraw_safi(
                                                bgp, &rm->p, AFI_IP, safi,
                                                (struct prefix_rd *)&rn->p);
                                        bgp_static_free(bgp_static);
-                                       rn->info = NULL;
+                                       bgp_static_set_node_info(rn, NULL);
                                        bgp_unlock_node(rn);
                                }
                        } else {
-                               bgp_static = rn->info;
+                               bgp_static = bgp_static_get_node_info(rn);
                                bgp_static_withdraw(bgp, &rn->p, afi, safi);
                                bgp_static_free(bgp_static);
-                               rn->info = NULL;
+                               bgp_static_set_node_info(rn, NULL);
                                bgp_unlock_node(rn);
                        }
                }
@@ -5019,13 +5040,14 @@ void bgp_static_redo_import_check(struct bgp *bgp)
 
                                for (rm = bgp_table_top(table); rm;
                                     rm = bgp_route_next(rm)) {
-                                       bgp_static = rm->info;
+                                       bgp_static =
+                                               bgp_static_get_node_info(rm);
                                        bgp_static_update_safi(bgp, &rm->p,
                                                               bgp_static, afi,
                                                               safi);
                                }
                        } else {
-                               bgp_static = rn->info;
+                               bgp_static = bgp_static_get_node_info(rn);
                                bgp_static_update(bgp, &rn->p, bgp_static, afi,
                                                  safi);
                        }
@@ -5197,7 +5219,7 @@ int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
                        if (gwip)
                                prefix_copy(&bgp_static->gatewayIp, &gw_ip);
                }
-               rn->info = bgp_static;
+               bgp_static_set_node_info(rn, bgp_static);
 
                bgp_static->valid = 1;
                bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
@@ -5259,9 +5281,9 @@ int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
        if (rn) {
                bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
 
-               bgp_static = rn->info;
+               bgp_static = bgp_static_get_node_info(rn);
                bgp_static_free(bgp_static);
-               rn->info = NULL;
+               bgp_static_set_node_info(rn, NULL);
                bgp_unlock_node(rn);
                bgp_unlock_node(rn);
        } else
@@ -5435,7 +5457,8 @@ static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
        XFREE(MTYPE_BGP_AGGREGATE, aggregate);
 }
 
-static int bgp_aggregate_info_same(struct bgp_info *ri, struct aspath *aspath,
+static int bgp_aggregate_info_same(struct bgp_info *ri, uint8_t origin,
+                                  struct aspath *aspath,
                                   struct community *comm)
 {
        static struct aspath *ae = NULL;
@@ -5446,6 +5469,9 @@ static int bgp_aggregate_info_same(struct bgp_info *ri, struct aspath *aspath,
        if (!ri)
                return 0;
 
+       if (origin != ri->attr->origin)
+               return 0;
+
        if (!aspath_cmp(ri->attr->aspath, (aspath) ? aspath : ae))
                return 0;
 
@@ -5480,7 +5506,8 @@ static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi,
                 * If the aggregate information has not changed
                 * no need to re-install it again.
                 */
-               if (bgp_aggregate_info_same(rn->info, aspath, community)) {
+               if (bgp_aggregate_info_same(rn->info, origin, aspath,
+                                           community)) {
                        bgp_unlock_node(rn);
 
                        if (aspath)
@@ -5745,13 +5772,14 @@ void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p,
        child = bgp_node_get(table, p);
 
        /* Aggregate address configuration check. */
-       for (rn = child; rn; rn = bgp_node_parent_nolock(rn))
-               if ((aggregate = rn->info) != NULL
-                   && rn->p.prefixlen < p->prefixlen) {
+       for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
+               aggregate = bgp_aggregate_get_node_info(rn);
+               if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
                        bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate);
                        bgp_aggregate_route(bgp, &rn->p, ri, afi, safi, NULL,
                                            aggregate);
                }
+       }
        bgp_unlock_node(child);
 }
 
@@ -5775,13 +5803,14 @@ void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p,
        child = bgp_node_get(table, p);
 
        /* Aggregate address configuration check. */
-       for (rn = child; rn; rn = bgp_node_parent_nolock(rn))
-               if ((aggregate = rn->info) != NULL
-                   && rn->p.prefixlen < p->prefixlen) {
+       for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
+               aggregate = bgp_aggregate_get_node_info(rn);
+               if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
                        bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate);
                        bgp_aggregate_route(bgp, &rn->p, NULL, afi, safi, del,
                                            aggregate);
                }
+       }
        bgp_unlock_node(child);
 }
 
@@ -5814,12 +5843,12 @@ static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
                return CMD_WARNING_CONFIG_FAILED;
        }
 
-       aggregate = rn->info;
+       aggregate = bgp_aggregate_get_node_info(rn);
        bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
        bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL, 0, aggregate);
 
        /* Unlock aggregate address configuration. */
-       rn->info = NULL;
+       bgp_aggregate_set_node_info(rn, NULL);
        bgp_aggregate_free(aggregate);
        bgp_unlock_node(rn);
        bgp_unlock_node(rn);
@@ -5870,7 +5899,7 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
        aggregate->summary_only = summary_only;
        aggregate->as_set = as_set;
        aggregate->safi = safi;
-       rn->info = aggregate;
+       bgp_aggregate_set_node_info(rn, aggregate);
 
        /* Aggregate address insert into BGP routing table. */
        bgp_aggregate_route(bgp, &p, NULL, afi, safi, NULL, aggregate);
@@ -6734,7 +6763,7 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
 
 /* called from terminal list command */
 void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr,
-                      safi_t safi, uint8_t use_json, json_object *json_ar)
+                      safi_t safi, bool use_json, json_object *json_ar)
 {
        json_object *json_status = NULL;
        json_object *json_net = NULL;
@@ -7063,7 +7092,7 @@ void route_vty_out_overlay(struct vty *vty, struct prefix *p,
 /* dampening route */
 static void damp_route_vty_out(struct vty *vty, struct prefix *p,
                               struct bgp_info *binfo, int display, safi_t safi,
-                              uint8_t use_json, json_object *json)
+                              bool use_json, json_object *json)
 {
        struct attr *attr;
        int len;
@@ -7126,7 +7155,7 @@ static void damp_route_vty_out(struct vty *vty, struct prefix *p,
 /* flap route */
 static void flap_route_vty_out(struct vty *vty, struct prefix *p,
                               struct bgp_info *binfo, int display, safi_t safi,
-                              uint8_t use_json, json_object *json)
+                              bool use_json, json_object *json)
 {
        struct attr *attr;
        struct bgp_damp_info *bdi;
@@ -8139,12 +8168,12 @@ static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
                           afi_t afi, safi_t safi, enum bgp_show_type type);
 static int bgp_show_community(struct vty *vty, struct bgp *bgp,
                              const char *comstr, int exact, afi_t afi,
-                             safi_t safi, uint8_t use_json);
+                             safi_t safi, bool use_json);
 
 
 static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
                          struct bgp_table *table, enum bgp_show_type type,
-                         void *output_arg, uint8_t use_json, char *rd,
+                         void *output_arg, bool use_json, char *rd,
                          int is_last, unsigned long *output_cum,
                          unsigned long *total_cum,
                          unsigned long *json_header_depth)
@@ -8177,7 +8206,6 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
                        vty_out(vty, " \"routeDistinguishers\" : {");
                        ++*json_header_depth;
                }
-               json_paths = json_object_new_object();
        }
 
        if (use_json && rd) {
@@ -8266,8 +8294,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
                                        continue;
                        }
                        if (type == bgp_show_type_prefix_longer) {
-                               struct prefix *p = output_arg;
-
+                               p = output_arg;
                                if (!prefix_match(p, &rn->p))
                                        continue;
                        }
@@ -8404,8 +8431,6 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
                *total_cum = total_count;
        }
        if (use_json) {
-               if (json_paths)
-                       json_object_free(json_paths);
                if (rd) {
                        vty_out(vty, " }%s ", (is_last ? "" : ","));
                }
@@ -8434,8 +8459,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
 
 int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
                      struct bgp_table *table, struct prefix_rd *prd_match,
-                     enum bgp_show_type type, void *output_arg,
-                     uint8_t use_json)
+                     enum bgp_show_type type, void *output_arg, bool use_json)
 {
        struct bgp_node *rn, *next;
        unsigned long output_cum = 0;
@@ -8475,7 +8499,7 @@ int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
        return CMD_SUCCESS;
 }
 static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
-                   enum bgp_show_type type, void *output_arg, uint8_t use_json)
+                   enum bgp_show_type type, void *output_arg, bool use_json)
 {
        struct bgp_table *table;
        unsigned long json_header_depth = 0;
@@ -8513,16 +8537,18 @@ static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
 }
 
 static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
-                                             safi_t safi, uint8_t use_json)
+                                             safi_t safi, bool use_json)
 {
        struct listnode *node, *nnode;
        struct bgp *bgp;
        int is_first = 1;
+       bool route_output = false;
 
        if (use_json)
                vty_out(vty, "{\n");
 
        for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+               route_output = true;
                if (use_json) {
                        if (!is_first)
                                vty_out(vty, ",\n");
@@ -8545,6 +8571,8 @@ static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
 
        if (use_json)
                vty_out(vty, "}\n");
+       else if (!route_output)
+               vty_out(vty, "%% BGP instance not found\n");
 }
 
 /* Header of detailed BGP route information */
@@ -8563,9 +8591,19 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
        int count = 0;
        int best = 0;
        int suppress = 0;
+       int accept_own = 0;
+       int route_filter_translated_v4 = 0;
+       int route_filter_v4 = 0;
+       int route_filter_translated_v6 = 0;
+       int route_filter_v6 = 0;
+       int llgr_stale = 0;
+       int no_llgr = 0;
+       int accept_own_nexthop = 0;
+       int blackhole = 0;
        int no_export = 0;
        int no_advertise = 0;
        int local_as = 0;
+       int no_peer = 0;
        int first = 1;
        int has_valid_label = 0;
        mpls_label_t label = 0;
@@ -8642,12 +8680,41 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
                } else
                        vty_out(vty, ", no best path");
 
-               if (no_advertise)
-                       vty_out(vty, ", not advertised to any peer");
+               if (accept_own)
+                       vty_out(vty,
+                       ", accept own local route exported and imported in different VRF");
+               else if (route_filter_translated_v4)
+                       vty_out(vty,
+                       ", mark translated RTs for VPNv4 route filtering");
+               else if (route_filter_v4)
+                       vty_out(vty,
+                       ", attach RT as-is for VPNv4 route filtering");
+               else if (route_filter_translated_v6)
+                       vty_out(vty,
+                       ", mark translated RTs for VPNv6 route filtering");
+               else if (route_filter_v6)
+                       vty_out(vty,
+                       ", attach RT as-is for VPNv6 route filtering");
+               else if (llgr_stale)
+                       vty_out(vty,
+                       ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
+               else if (no_llgr)
+                       vty_out(vty,
+                       ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
+               else if (accept_own_nexthop)
+                       vty_out(vty,
+                       ", accept local nexthop");
+               else if (blackhole)
+                       vty_out(vty, ", inform peer to blackhole prefix");
                else if (no_export)
                        vty_out(vty, ", not advertised to EBGP peer");
+               else if (no_advertise)
+                       vty_out(vty, ", not advertised to any peer");
                else if (local_as)
                        vty_out(vty, ", not advertised outside local AS");
+               else if (no_peer)
+                       vty_out(vty,
+                       ", inform EBGP peer not to advertise to their EBGP peers");
 
                if (suppress)
                        vty_out(vty,
@@ -8691,8 +8758,7 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
                                   struct bgp_table *rib, const char *ip_str,
                                   afi_t afi, safi_t safi,
                                   struct prefix_rd *prd, int prefix_check,
-                                  enum bgp_path_type pathtype,
-                                  uint8_t use_json)
+                                  enum bgp_path_type pathtype, bool use_json)
 {
        int ret;
        int header;
@@ -8828,7 +8894,7 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
 static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
                          afi_t afi, safi_t safi, struct prefix_rd *prd,
                          int prefix_check, enum bgp_path_type pathtype,
-                         uint8_t use_json)
+                         bool use_json)
 {
        if (!bgp) {
                bgp = bgp_get_default();
@@ -8852,7 +8918,7 @@ static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
 
 static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
                               struct cmd_token **argv, afi_t afi, safi_t safi,
-                              uint8_t uj)
+                              bool uj)
 {
        struct lcommunity *lcom;
        struct buffer *b;
@@ -8889,7 +8955,7 @@ static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
 
 static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
                                    const char *lcom, afi_t afi, safi_t safi,
-                                   uint8_t uj)
+                                   bool uj)
 {
        struct community_list *list;
 
@@ -8937,7 +9003,7 @@ DEFUN (show_ip_bgp_large_community_list,
                        safi = bgp_vty_safi_from_str(argv[idx]->text);
        }
 
-       int uj = use_json(argc, argv);
+       bool uj = use_json(argc, argv);
 
        struct bgp *bgp = bgp_lookup_by_name(vrf);
        if (bgp == NULL) {
@@ -8980,7 +9046,7 @@ DEFUN (show_ip_bgp_large_community,
                        safi = bgp_vty_safi_from_str(argv[idx]->text);
        }
 
-       int uj = use_json(argc, argv);
+       bool uj = use_json(argc, argv);
 
        struct bgp *bgp = bgp_lookup_by_name(vrf);
        if (bgp == NULL) {
@@ -9008,6 +9074,10 @@ DEFUN (show_ip_bgp,
            |prefix-list WORD\
            |filter-list WORD\
            |statistics\
+           |community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown\
+           no-peer|blackhole|llgr-stale|no-llgr|accept-own|accept-own-nexthop\
+           route-filter-v6|route-filter-v4|route-filter-translated-v6|\
+           route-filter-translated-v4> [exact-match]\
            |community-list <(1-500)|WORD> [exact-match]\
            |A.B.C.D/M longer-prefixes\
            |X:X::X:X/M longer-prefixes\
@@ -9027,6 +9097,23 @@ DEFUN (show_ip_bgp,
        "Display routes conforming to the filter-list\n"
        "Regular expression access list name\n"
        "BGP RIB advertisement statistics\n"
+       "Display routes matching the communities\n"
+       COMMUNITY_AANN_STR
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Graceful shutdown (well-known community)\n"
+       "Do not export to any peer (well-known community)\n"
+       "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
+       "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
+       "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
+       "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
+       "Should accept VPN route with local nexthop (well-known community)\n"
+       "RT VPNv6 route filtering (well-known community)\n"
+       "RT VPNv4 route filtering (well-known community)\n"
+       "RT translated VPNv6 route filtering (well-known community)\n"
+       "RT translated VPNv4 route filtering (well-known community)\n"
+       "Exact match of the communities\n"
        "Display routes matching the community-list\n"
        "community-list number\n"
        "community-list name\n"
@@ -9043,7 +9130,7 @@ DEFUN (show_ip_bgp,
        int idx = 0;
 
        bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
-                                           &bgp);
+                                           &bgp, false);
        if (!idx)
                return CMD_WARNING;
 
@@ -9119,16 +9206,16 @@ DEFUN (show_ip_bgp_json,
        int idx = 0;
        int idx_community_type = 0;
        int exact_match = 0;
+       bool uj = use_json(argc, argv);
+
+       if (uj)
+               argc--;
 
        bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
-                                           &bgp);
+                                           &bgp, uj);
        if (!idx)
                return CMD_WARNING;
 
-       int uj = use_json(argc, argv);
-       if (uj)
-               argc--;
-
        if (argv_find(argv, argc, "cidr-only", &idx))
                return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
                                NULL, uj);
@@ -9197,12 +9284,12 @@ DEFUN (show_ip_bgp_route,
        char *prefix = NULL;
        struct bgp *bgp = NULL;
        enum bgp_path_type path_type;
-       uint8_t uj = use_json(argc, argv);
+       bool uj = use_json(argc, argv);
 
        int idx = 0;
 
        bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
-                                           &bgp);
+                                           &bgp, uj);
        if (!idx)
                return CMD_WARNING;
 
@@ -9265,7 +9352,7 @@ DEFUN (show_ip_bgp_regexp,
 
        int idx = 0;
        bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
-                                           &bgp);
+                                           &bgp, false);
        if (!idx)
                return CMD_WARNING;
 
@@ -9294,17 +9381,17 @@ DEFUN (show_ip_bgp_instance_all,
        afi_t afi = AFI_IP;
        safi_t safi = SAFI_UNICAST;
        struct bgp *bgp = NULL;
-
        int idx = 0;
-       bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
-                                           &bgp);
-       if (!idx)
-               return CMD_WARNING;
+       bool uj = use_json(argc, argv);
 
-       int uj = use_json(argc, argv);
        if (uj)
                argc--;
 
+       bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
+                                           &bgp, uj);
+       if (!idx)
+               return CMD_WARNING;
+
        bgp_show_all_instances_routes_vty(vty, afi, safi, uj);
        return CMD_SUCCESS;
 }
@@ -9375,7 +9462,7 @@ static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
 
 static int bgp_show_community(struct vty *vty, struct bgp *bgp,
                              const char *comstr, int exact, afi_t afi,
-                             safi_t safi, uint8_t use_json)
+                             safi_t safi, bool use_json)
 {
        struct community *com;
        int ret = 0;
@@ -9434,7 +9521,7 @@ static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
 }
 
 static struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp,
-                                       const char *ip_str, uint8_t use_json)
+                                       const char *ip_str, bool use_json)
 {
        int ret;
        struct peer *peer;
@@ -9787,8 +9874,6 @@ static int bgp_peer_count_walker(struct thread *t)
                                pc->count[PCOUNT_ADJ_IN]++;
 
                for (ri = rn->info; ri; ri = ri->next) {
-                       char buf[SU_ADDRSTRLEN];
-
                        if (ri->peer != peer)
                                continue;
 
@@ -9810,22 +9895,14 @@ static int bgp_peer_count_walker(struct thread *t)
                        if (CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) {
                                pc->count[PCOUNT_COUNTED]++;
                                if (CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
-                                       zlog_warn(
-                                               "%s [pcount] %s/%d is counted but flags 0x%x",
-                                               peer->host,
-                                               inet_ntop(rn->p.family,
-                                                         &rn->p.u.prefix, buf,
-                                                         SU_ADDRSTRLEN),
-                                               rn->p.prefixlen, ri->flags);
+                                       flog_err(
+                                               EC_LIB_DEVELOPMENT,
+                                               "Attempting to count but flags say it is unusable");
                        } else {
                                if (!CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
-                                       zlog_warn(
-                                               "%s [pcount] %s/%d not counted but flags 0x%x",
-                                               peer->host,
-                                               inet_ntop(rn->p.family,
-                                                         &rn->p.u.prefix, buf,
-                                                         SU_ADDRSTRLEN),
-                                               rn->p.prefixlen, ri->flags);
+                                       flog_err(
+                                               EC_LIB_DEVELOPMENT,
+                                               "Not counted but flags say we should");
                        }
                }
        }
@@ -9833,7 +9910,7 @@ static int bgp_peer_count_walker(struct thread *t)
 }
 
 static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
-                          safi_t safi, uint8_t use_json)
+                          safi_t safi, bool use_json)
 {
        struct peer_pcounts pcounts = {.peer = peer};
        unsigned int i;
@@ -9943,16 +10020,16 @@ DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
        struct peer *peer;
        int idx = 0;
        struct bgp *bgp = NULL;
+       bool uj = use_json(argc, argv);
+
+       if (uj)
+               argc--;
 
        bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
-                                           &bgp);
+                                           &bgp, uj);
        if (!idx)
                return CMD_WARNING;
 
-       int uj = use_json(argc, argv);
-       if (uj)
-               argc--;
-
        argv_find(argv, argc, "neighbors", &idx);
        peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
        if (!peer)
@@ -9979,7 +10056,7 @@ DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
 {
        int idx_peer = 6;
        struct peer *peer;
-       uint8_t uj = use_json(argc, argv);
+       bool uj = use_json(argc, argv);
 
        peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
        if (!peer)
@@ -10052,7 +10129,7 @@ DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix,
 
 static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
                           safi_t safi, enum bgp_show_adj_route_type type,
-                          const char *rmap_name, uint8_t use_json,
+                          const char *rmap_name, bool use_json,
                           json_object *json)
 {
        struct bgp_table *table;
@@ -10323,7 +10400,7 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
 
 static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
                           safi_t safi, enum bgp_show_adj_route_type type,
-                          const char *rmap_name, uint8_t use_json)
+                          const char *rmap_name, bool use_json)
 {
        json_object *json = NULL;
 
@@ -10397,18 +10474,17 @@ DEFUN (show_ip_bgp_instance_neighbor_advertised_route,
        struct bgp *bgp = NULL;
        struct peer *peer;
        enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
-
        int idx = 0;
-       bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
-                                           &bgp);
-       if (!idx)
-               return CMD_WARNING;
-
-       int uj = use_json(argc, argv);
+       bool uj = use_json(argc, argv);
 
        if (uj)
                argc--;
 
+       bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
+                                           &bgp, uj);
+       if (!idx)
+               return CMD_WARNING;
+
        /* neighbors <A.B.C.D|X:X::X:X|WORD> */
        argv_find(argv, argc, "neighbors", &idx);
        peerstr = argv[++idx]->arg;
@@ -10470,7 +10546,7 @@ DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
        argv_find(argv, argc, "neighbors", &idx);
        peerstr = argv[++idx]->arg;
 
-       uint8_t uj = use_json(argc, argv);
+       bool uj = use_json(argc, argv);
 
        ret = str2sockunion(peerstr, &su);
        if (ret < 0) {
@@ -10514,7 +10590,7 @@ DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
 
 static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
                                   afi_t afi, safi_t safi,
-                                  enum bgp_show_type type, uint8_t use_json)
+                                  enum bgp_show_type type, bool use_json)
 {
        /* labeled-unicast routes live in the unicast table */
        if (safi == SAFI_LABELED_UNICAST)
@@ -10554,14 +10630,17 @@ DEFUN (show_ip_bgp_flowspec_routes_detailed,
        safi_t safi = SAFI_UNICAST;
        struct bgp *bgp = NULL;
        int idx = 0;
+       bool uj = use_json(argc, argv);
+
+       if (uj)
+               argc--;
 
        bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
-                                           &bgp);
+                                           &bgp, uj);
        if (!idx)
                return CMD_WARNING;
 
-       return bgp_show(vty, bgp, afi, safi,
-                       bgp_show_type_detail, NULL, use_json(argc, argv));
+       return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj);
 }
 
 DEFUN (show_ip_bgp_neighbor_routes,
@@ -10589,18 +10668,17 @@ DEFUN (show_ip_bgp_neighbor_routes,
        safi_t safi = SAFI_UNICAST;
        struct peer *peer;
        enum bgp_show_type sh_type = bgp_show_type_neighbor;
-
        int idx = 0;
+       bool uj = use_json(argc, argv);
+
+       if (uj)
+               argc--;
 
        bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
-                                           &bgp);
+                                           &bgp, uj);
        if (!idx)
                return CMD_WARNING;
 
-       int uj = use_json(argc, argv);
-       if (uj)
-               argc--;
-
        /* neighbors <A.B.C.D|X:X::X:X|WORD> */
        argv_find(argv, argc, "neighbors", &idx);
        peerstr = argv[++idx]->arg;
@@ -10696,12 +10774,12 @@ static int bgp_distance_set(struct vty *vty, const char *distance_str,
 
        /* Get BGP distance node. */
        rn = bgp_node_get(bgp_distance_table[afi][safi], (struct prefix *)&p);
-       if (rn->info) {
-               bdistance = rn->info;
+       bdistance = bgp_distance_get_node(rn);
+       if (bdistance)
                bgp_unlock_node(rn);
-       else {
+       else {
                bdistance = bgp_distance_new();
-               rn->info = bdistance;
+               bgp_distance_set_node_info(rn, bdistance);
        }
 
        /* Set distance value. */
@@ -10746,7 +10824,7 @@ static int bgp_distance_unset(struct vty *vty, const char *distance_str,
                return CMD_WARNING_CONFIG_FAILED;
        }
 
-       bdistance = rn->info;
+       bdistance = bgp_distance_get_node(rn);
        distance = atoi(distance_str);
 
        if (bdistance->distance != distance) {
@@ -10785,7 +10863,7 @@ uint8_t bgp_distance_apply(struct prefix *p, struct bgp_info *rinfo, afi_t afi,
        sockunion2hostprefix(&peer->su, &q);
        rn = bgp_node_match(bgp_distance_table[afi][safi], &q);
        if (rn) {
-               bdistance = rn->info;
+               bdistance = bgp_distance_get_node(rn);
                bgp_unlock_node(rn);
 
                if (bdistance->access_list) {
@@ -10800,7 +10878,7 @@ uint8_t bgp_distance_apply(struct prefix *p, struct bgp_info *rinfo, afi_t afi,
        /* Backdoor check. */
        rn = bgp_node_lookup(bgp->route[afi][safi], p);
        if (rn) {
-               bgp_static = rn->info;
+               bgp_static = bgp_static_get_node_info(rn);
                bgp_unlock_node(rn);
 
                if (bgp_static->backdoor) {
@@ -11215,7 +11293,8 @@ static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
                        continue;
 
                for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
-                       if ((bgp_static = rn->info) == NULL)
+                       bgp_static = bgp_static_get_node_info(rn);
+                       if (bgp_static == NULL)
                                continue;
 
                        p = &rn->p;
@@ -11264,7 +11343,8 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
                        continue;
 
                for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
-                       if ((bgp_static = rn->info) == NULL)
+                       bgp_static = bgp_static_get_node_info(rn);
+                       if (bgp_static == NULL)
                                continue;
 
                        char *macrouter = NULL;
@@ -11339,7 +11419,8 @@ void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
        /* Network configuration. */
        for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
             rn = bgp_route_next(rn)) {
-               if ((bgp_static = rn->info) == NULL)
+               bgp_static = bgp_static_get_node_info(rn);
+               if (bgp_static == NULL)
                        continue;
 
                p = &rn->p;
@@ -11385,7 +11466,8 @@ void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
        /* Aggregate-address configuration. */
        for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn;
             rn = bgp_route_next(rn)) {
-               if ((bgp_aggregate = rn->info) == NULL)
+               bgp_aggregate = bgp_aggregate_get_node_info(rn);
+               if (bgp_aggregate == NULL)
                        continue;
 
                p = &rn->p;
@@ -11435,8 +11517,9 @@ void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
        }
 
        for (rn = bgp_table_top(bgp_distance_table[afi][safi]); rn;
-            rn = bgp_route_next(rn))
-               if ((bdistance = rn->info) != NULL) {
+            rn = bgp_route_next(rn)) {
+               bdistance = bgp_distance_get_node(rn);
+               if (bdistance != NULL) {
                        char buf[PREFIX_STRLEN];
 
                        vty_out(vty, "  distance %d %s %s\n",
@@ -11445,6 +11528,7 @@ void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
                                bdistance->access_list ? bdistance->access_list
                                                       : "");
                }
+       }
 }
 
 /* Allocate routing table structure and install commands. */