]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_route.c
bgpd: Add peer action for PEER_FLAG_IFPEER_V6ONLY flag
[mirror_frr.git] / bgpd / bgp_route.c
index 4bbc535cdc96de1ac2b05228cbf7650aa288db10..9fa0aaa4fd7cbfd5ad4600fe56934411006baee4 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(LIB_ERR_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);
@@ -2459,16 +2473,10 @@ static void bgp_processq_del(struct work_queue *wq, void *data)
 
 void bgp_process_queue_init(void)
 {
-       if (!bm->process_main_queue) {
+       if (!bm->process_main_queue)
                bm->process_main_queue =
                        work_queue_new(bm->master, "process_main_queue");
 
-               if (!bm->process_main_queue) {
-                       zlog_err("%s: Failed to allocate work queue", __func__);
-                       exit(1);
-               }
-       }
-
        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;
@@ -3838,11 +3846,7 @@ static void bgp_clear_node_queue_init(struct peer *peer)
        snprintf(wname, sizeof(wname), "clear %s", peer->host);
 #undef CLEAR_QUEUE_NAME_LEN
 
-       if ((peer->clear_node_queue = work_queue_new(bm->master, wname))
-           == NULL) {
-               zlog_err("%s: Failed to allocate work queue", __func__);
-               exit(1);
-       }
+       peer->clear_node_queue = work_queue_new(bm->master, wname);
        peer->clear_node_queue->spec.hold = 10;
        peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
        peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
@@ -4212,8 +4216,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(
+                               BGP_ERR_UPDATE_RCV,
+                               "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
                                peer->host, p.prefixlen, packet->afi);
                        return -1;
                }
@@ -4223,7 +4228,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(
+                               BGP_ERR_UPDATE_RCV,
                                "%s [Error] Update packet error (prefix length %d overflows packet)",
                                peer->host, p.prefixlen);
                        return -1;
@@ -4232,7 +4238,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(
+                               BGP_ERR_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;
@@ -4253,7 +4260,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(
+                                       BGP_ERR_UPDATE_RCV,
                                        "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
                                        peer->host, inet_ntoa(p.u.prefix4));
                                continue;
@@ -4265,7 +4273,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(
+                                       BGP_ERR_UPDATE_RCV,
                                        "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
                                        peer->host,
                                        inet_ntop(AF_INET6, &p.u.prefix6, buf,
@@ -4276,7 +4285,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(
+                                       BGP_ERR_UPDATE_RCV,
                                        "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
                                        peer->host,
                                        inet_ntop(AF_INET6, &p.u.prefix6, buf,
@@ -4305,7 +4315,8 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
 
        /* Packet length consistency check. */
        if (pnt != lim) {
-               zlog_err(
+               flog_err(
+                       BGP_ERR_UPDATE_RCV,
                        "%s [Error] Update packet error (prefix length mismatch with total length)",
                        peer->host);
                return -1;
@@ -5201,8 +5212,8 @@ int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
                        if (routermac) {
                                bgp_static->router_mac =
                                        XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
-                               prefix_str2mac(routermac,
-                                              bgp_static->router_mac);
+                               (void)prefix_str2mac(routermac,
+                                                    bgp_static->router_mac);
                        }
                        if (gwip)
                                prefix_copy(&bgp_static->gatewayIp, &gw_ip);
@@ -5445,7 +5456,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;
@@ -5456,6 +5468,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;
 
@@ -5490,7 +5505,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)
@@ -6255,24 +6271,14 @@ static void route_vty_out_route(struct prefix *p, struct vty *vty,
                                json_object *json)
 {
        int len = 0;
-       uint32_t destination;
        char buf[BUFSIZ];
 
        if (p->family == AF_INET) {
                if (!json) {
-                       len = vty_out(vty, "%s",
-                                     inet_ntop(p->family, &p->u.prefix, buf,
-                                               BUFSIZ));
-                       destination = ntohl(p->u.prefix4.s_addr);
-
-                       if ((IN_CLASSC(destination) && p->prefixlen == 24)
-                           || (IN_CLASSB(destination) && p->prefixlen == 16)
-                           || (IN_CLASSA(destination) && p->prefixlen == 8)
-                           || p->u.prefix4.s_addr == 0) {
-                               /* When mask is natural,
-                                  mask is not displayed. */
-                       } else
-                               len += vty_out(vty, "/%d", p->prefixlen);
+                       len = vty_out(
+                               vty, "%s/%d",
+                               inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
+                               p->prefixlen);
                } else {
                        json_object_string_add(json, "prefix",
                                               inet_ntop(p->family,
@@ -7737,13 +7743,6 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
                        else
                                vty_out(vty, ", localpref %u",
                                        attr->local_pref);
-               } else {
-                       if (json_paths)
-                               json_object_int_add(json_path, "localpref",
-                                                   bgp->default_local_pref);
-                       else
-                               vty_out(vty, ", localpref %u",
-                                       bgp->default_local_pref);
                }
 
                if (attr->weight != 0) {
@@ -8204,7 +8203,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) {
@@ -8431,8 +8429,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 ? "" : ","));
                }
@@ -8590,9 +8586,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;
@@ -8669,12 +8675,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,
@@ -9035,6 +9070,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\
@@ -9054,6 +9093,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"
@@ -9567,7 +9623,7 @@ ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
   unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
   unsigned long res = (newtot * TALLY_SIGFIG) / count;
   unsigned long ret = newtot / count;
-  
+
   if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
     return ret + 1;
   else
@@ -9661,7 +9717,7 @@ static int bgp_table_stats_walker(struct thread *t)
                                ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
                                ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
 #if 0
-              ts->counts[BGP_STATS_ASPATH_AVGHOPS] 
+              ts->counts[BGP_STATS_ASPATH_AVGHOPS]
                 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
                               ts->counts[BGP_STATS_ASPATH_AVGHOPS],
                               hops);
@@ -9814,8 +9870,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;
 
@@ -9837,22 +9891,12 @@ 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(LIB_ERR_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(LIB_ERR_DEVELOPMENT,
+                                                "Not counted but flags say we should");
                        }
                }
        }
@@ -10149,9 +10193,9 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
                                               json_scode);
                        json_object_object_add(json, "bgpOriginCodes",
                                               json_ocode);
-                       json_object_string_add(json,
-                                              "bgpOriginatingDefaultNetwork",
-                                              "0.0.0.0");
+                       json_object_string_add(
+                               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 ",
@@ -10165,7 +10209,8 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
                        vty_out(vty, BGP_SHOW_NCODE_HEADER);
                        vty_out(vty, BGP_SHOW_OCODE_HEADER);
 
-                       vty_out(vty, "Originating default network 0.0.0.0\n\n");
+                       vty_out(vty, "Originating default network %s\n\n",
+                               (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
                }
                header1 = 0;
        }