back to topotato report
topotato coverage report
Current view: top level - bgpd - bgp_route.c (source / functions) Hit Total Coverage
Test: test_bgp_set_aspath_replace.py::BGPSetAspathReplace Lines: 1408 7647 18.4 %
Date: 2023-02-24 18:37:49 Functions: 73 224 32.6 %

          Line data    Source code
       1             : /* BGP routing information
       2             :  * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
       3             :  * Copyright (C) 2016 Job Snijders <job@instituut.net>
       4             :  *
       5             :  * This file is part of GNU Zebra.
       6             :  *
       7             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       8             :  * under the terms of the GNU General Public License as published by the
       9             :  * Free Software Foundation; either version 2, or (at your option) any
      10             :  * later version.
      11             :  *
      12             :  * GNU Zebra is distributed in the hope that it will be useful, but
      13             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License along
      18             :  * with this program; see the file COPYING; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : #include <zebra.h>
      23             : #include <math.h>
      24             : 
      25             : #include "printfrr.h"
      26             : #include "frrstr.h"
      27             : #include "prefix.h"
      28             : #include "linklist.h"
      29             : #include "memory.h"
      30             : #include "command.h"
      31             : #include "stream.h"
      32             : #include "filter.h"
      33             : #include "log.h"
      34             : #include "routemap.h"
      35             : #include "buffer.h"
      36             : #include "sockunion.h"
      37             : #include "plist.h"
      38             : #include "thread.h"
      39             : #include "workqueue.h"
      40             : #include "queue.h"
      41             : #include "memory.h"
      42             : #include "srv6.h"
      43             : #include "lib/json.h"
      44             : #include "lib_errors.h"
      45             : #include "zclient.h"
      46             : #include "bgpd/bgpd.h"
      47             : #include "bgpd/bgp_table.h"
      48             : #include "bgpd/bgp_route.h"
      49             : #include "bgpd/bgp_attr.h"
      50             : #include "bgpd/bgp_debug.h"
      51             : #include "bgpd/bgp_errors.h"
      52             : #include "bgpd/bgp_aspath.h"
      53             : #include "bgpd/bgp_regex.h"
      54             : #include "bgpd/bgp_community.h"
      55             : #include "bgpd/bgp_community_alias.h"
      56             : #include "bgpd/bgp_ecommunity.h"
      57             : #include "bgpd/bgp_lcommunity.h"
      58             : #include "bgpd/bgp_clist.h"
      59             : #include "bgpd/bgp_packet.h"
      60             : #include "bgpd/bgp_filter.h"
      61             : #include "bgpd/bgp_fsm.h"
      62             : #include "bgpd/bgp_mplsvpn.h"
      63             : #include "bgpd/bgp_nexthop.h"
      64             : #include "bgpd/bgp_damp.h"
      65             : #include "bgpd/bgp_advertise.h"
      66             : #include "bgpd/bgp_zebra.h"
      67             : #include "bgpd/bgp_vty.h"
      68             : #include "bgpd/bgp_mpath.h"
      69             : #include "bgpd/bgp_nht.h"
      70             : #include "bgpd/bgp_updgrp.h"
      71             : #include "bgpd/bgp_label.h"
      72             : #include "bgpd/bgp_addpath.h"
      73             : #include "bgpd/bgp_mac.h"
      74             : #include "bgpd/bgp_network.h"
      75             : #include "bgpd/bgp_trace.h"
      76             : #include "bgpd/bgp_rpki.h"
      77             : 
      78             : #ifdef ENABLE_BGP_VNC
      79             : #include "bgpd/rfapi/rfapi_backend.h"
      80             : #include "bgpd/rfapi/vnc_import_bgp.h"
      81             : #include "bgpd/rfapi/vnc_export_bgp.h"
      82             : #endif
      83             : #include "bgpd/bgp_encap_types.h"
      84             : #include "bgpd/bgp_encap_tlv.h"
      85             : #include "bgpd/bgp_evpn.h"
      86             : #include "bgpd/bgp_evpn_mh.h"
      87             : #include "bgpd/bgp_evpn_vty.h"
      88             : #include "bgpd/bgp_flowspec.h"
      89             : #include "bgpd/bgp_flowspec_util.h"
      90             : #include "bgpd/bgp_pbr.h"
      91             : 
      92             : #include "bgpd/bgp_route_clippy.c"
      93             : 
      94          34 : DEFINE_HOOK(bgp_snmp_update_stats,
      95             :             (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
      96             :             (rn, pi, added));
      97             : 
      98           0 : DEFINE_HOOK(bgp_rpki_prefix_status,
      99             :             (struct peer *peer, struct attr *attr,
     100             :              const struct prefix *prefix),
     101             :             (peer, attr, prefix));
     102             : 
     103             : /* Extern from bgp_dump.c */
     104             : extern const char *bgp_origin_str[];
     105             : extern const char *bgp_origin_long_str[];
     106             : 
     107             : /* PMSI strings. */
     108             : #define PMSI_TNLTYPE_STR_NO_INFO "No info"
     109             : #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
     110             : static const struct message bgp_pmsi_tnltype_str[] = {
     111             :         {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
     112             :         {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
     113             :         {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
     114             :         {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
     115             :         {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
     116             :         {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
     117             :         {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
     118             :         {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
     119             :         {0}
     120             : };
     121             : 
     122             : #define VRFID_NONE_STR "-"
     123             : #define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
     124             : 
     125          27 : DEFINE_HOOK(bgp_process,
     126             :             (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
     127             :              struct peer *peer, bool withdraw),
     128             :             (bgp, afi, safi, bn, peer, withdraw));
     129             : 
     130             : /** Test if path is suppressed. */
     131          32 : static bool bgp_path_suppressed(struct bgp_path_info *pi)
     132             : {
     133          16 :         if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
     134             :                 return false;
     135             : 
     136           0 :         return listcount(pi->extra->aggr_suppressors) > 0;
     137             : }
     138             : 
     139          30 : struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
     140             :                                   safi_t safi, const struct prefix *p,
     141             :                                   struct prefix_rd *prd)
     142             : {
     143          30 :         struct bgp_dest *dest;
     144          30 :         struct bgp_dest *pdest = NULL;
     145             : 
     146          30 :         assert(table);
     147             : 
     148          30 :         if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
     149          30 :             || (safi == SAFI_EVPN)) {
     150           0 :                 pdest = bgp_node_get(table, (struct prefix *)prd);
     151             : 
     152           0 :                 if (!bgp_dest_has_bgp_path_info_data(pdest))
     153           0 :                         bgp_dest_set_bgp_table_info(
     154             :                                 pdest, bgp_table_init(table->bgp, afi, safi));
     155             :                 else
     156           0 :                         bgp_dest_unlock_node(pdest);
     157           0 :                 table = bgp_dest_get_bgp_table_info(pdest);
     158             :         }
     159             : 
     160          30 :         dest = bgp_node_get(table, p);
     161             : 
     162          30 :         if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
     163             :             || (safi == SAFI_EVPN))
     164           0 :                 dest->pdest = pdest;
     165             : 
     166          30 :         return dest;
     167             : }
     168             : 
     169           0 : struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
     170             :                                      safi_t safi, const struct prefix *p,
     171             :                                      struct prefix_rd *prd)
     172             : {
     173           0 :         struct bgp_dest *dest;
     174           0 :         struct bgp_dest *pdest = NULL;
     175             : 
     176           0 :         if (!table)
     177             :                 return NULL;
     178             : 
     179           0 :         if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
     180           0 :             || (safi == SAFI_EVPN)) {
     181           0 :                 pdest = bgp_node_lookup(table, (struct prefix *)prd);
     182           0 :                 if (!pdest)
     183             :                         return NULL;
     184             : 
     185           0 :                 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
     186           0 :                         bgp_dest_unlock_node(pdest);
     187           0 :                         return NULL;
     188             :                 }
     189             : 
     190             :                 table = bgp_dest_get_bgp_table_info(pdest);
     191             :         }
     192             : 
     193           0 :         dest = bgp_node_lookup(table, p);
     194             : 
     195           0 :         return dest;
     196             : }
     197             : 
     198             : /* Allocate bgp_path_info_extra */
     199           0 : static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
     200             : {
     201           0 :         struct bgp_path_info_extra *new;
     202           0 :         new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
     203             :                       sizeof(struct bgp_path_info_extra));
     204           0 :         new->label[0] = MPLS_INVALID_LABEL;
     205           0 :         new->num_labels = 0;
     206           0 :         new->bgp_fs_pbr = NULL;
     207           0 :         new->bgp_fs_iprule = NULL;
     208           0 :         return new;
     209             : }
     210             : 
     211          17 : void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
     212             : {
     213          17 :         struct bgp_path_info_extra *e;
     214             : 
     215          17 :         if (!extra || !*extra)
     216             :                 return;
     217             : 
     218           0 :         e = *extra;
     219           0 :         if (e->damp_info)
     220           0 :                 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
     221             :                                    e->damp_info->safi);
     222             : 
     223           0 :         e->damp_info = NULL;
     224           0 :         if (e->parent) {
     225           0 :                 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
     226             : 
     227           0 :                 if (bpi->net) {
     228             :                         /* FIXME: since multiple e may have the same e->parent
     229             :                          * and e->parent->net is holding a refcount for each
     230             :                          * of them, we need to do some fudging here.
     231             :                          *
     232             :                          * WARNING: if bpi->net->lock drops to 0, bpi may be
     233             :                          * freed as well (because bpi->net was holding the
     234             :                          * last reference to bpi) => write after free!
     235             :                          */
     236           0 :                         unsigned refcount;
     237             : 
     238           0 :                         bpi = bgp_path_info_lock(bpi);
     239           0 :                         refcount = bgp_dest_get_lock_count(bpi->net) - 1;
     240           0 :                         bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
     241           0 :                         if (!refcount)
     242           0 :                                 bpi->net = NULL;
     243           0 :                         bgp_path_info_unlock(bpi);
     244             :                 }
     245           0 :                 bgp_path_info_unlock(e->parent);
     246           0 :                 e->parent = NULL;
     247             :         }
     248             : 
     249           0 :         if (e->bgp_orig)
     250           0 :                 bgp_unlock(e->bgp_orig);
     251             : 
     252           0 :         if (e->peer_orig)
     253           0 :                 peer_unlock(e->peer_orig);
     254             : 
     255           0 :         if (e->aggr_suppressors)
     256           0 :                 list_delete(&e->aggr_suppressors);
     257             : 
     258           0 :         if (e->mh_info)
     259           0 :                 bgp_evpn_path_mh_info_free(e->mh_info);
     260             : 
     261           0 :         if ((*extra)->bgp_fs_iprule)
     262           0 :                 list_delete(&((*extra)->bgp_fs_iprule));
     263           0 :         if ((*extra)->bgp_fs_pbr)
     264           0 :                 list_delete(&((*extra)->bgp_fs_pbr));
     265           0 :         XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
     266             : }
     267             : 
     268             : /* Get bgp_path_info extra information for the given bgp_path_info, lazy
     269             :  * allocated if required.
     270             :  */
     271           0 : struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
     272             : {
     273           0 :         if (!pi->extra)
     274           0 :                 pi->extra = bgp_path_info_extra_new();
     275           0 :         return pi->extra;
     276             : }
     277             : 
     278             : /* Free bgp route information. */
     279          17 : void bgp_path_info_free_with_caller(const char *name,
     280             :                                     struct bgp_path_info *path)
     281             : {
     282          17 :         frrtrace(2, frr_bgp, bgp_path_info_free, path, name);
     283          17 :         bgp_attr_unintern(&path->attr);
     284             : 
     285          17 :         bgp_unlink_nexthop(path);
     286          17 :         bgp_path_info_extra_free(&path->extra);
     287          17 :         bgp_path_info_mpath_free(&path->mpath);
     288          17 :         if (path->net)
     289          17 :                 bgp_addpath_free_info_data(&path->tx_addpath,
     290             :                                            &path->net->tx_addpath);
     291             : 
     292          17 :         peer_unlock(path->peer); /* bgp_path_info peer reference */
     293             : 
     294          17 :         XFREE(MTYPE_BGP_ROUTE, path);
     295          17 : }
     296             : 
     297          33 : struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
     298             : {
     299          33 :         path->lock++;
     300           0 :         return path;
     301             : }
     302             : 
     303          33 : struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
     304             : {
     305          33 :         assert(path && path->lock > 0);
     306          33 :         path->lock--;
     307             : 
     308          33 :         if (path->lock == 0) {
     309          17 :                 bgp_path_info_free(path);
     310          17 :                 return NULL;
     311             :         }
     312             : 
     313             :         return path;
     314             : }
     315             : 
     316             : /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
     317          20 : static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
     318             : {
     319          20 :         struct peer *peer;
     320          20 :         struct bgp_path_info *old_pi, *nextpi;
     321          20 :         bool set_flag = false;
     322          20 :         struct bgp *bgp = NULL;
     323          20 :         struct bgp_table *table = NULL;
     324          20 :         afi_t afi = 0;
     325          20 :         safi_t safi = 0;
     326             : 
     327             :         /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
     328             :          * then the route selection is deferred
     329             :          */
     330          20 :         if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
     331             :                 return 0;
     332             : 
     333          20 :         if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
     334           3 :                 if (BGP_DEBUG(update, UPDATE_OUT))
     335           0 :                         zlog_debug(
     336             :                                 "Route %pBD is in workqueue and being processed, not deferred.",
     337             :                                 dest);
     338             : 
     339           3 :                 return 0;
     340             :         }
     341             : 
     342          17 :         table = bgp_dest_table(dest);
     343          17 :         if (table) {
     344          17 :                 bgp = table->bgp;
     345          17 :                 afi = table->afi;
     346          17 :                 safi = table->safi;
     347             :         }
     348             : 
     349          17 :         for (old_pi = bgp_dest_get_bgp_path_info(dest);
     350          37 :              (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
     351          20 :                 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
     352           3 :                         continue;
     353             : 
     354             :                 /* Route selection is deferred if there is a stale path which
     355             :                  * which indicates peer is in restart mode
     356             :                  */
     357          17 :                 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
     358           0 :                     && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
     359             :                         set_flag = true;
     360             :                 } else {
     361             :                         /* If the peer is graceful restart capable and peer is
     362             :                          * restarting mode, set the flag BGP_NODE_SELECT_DEFER
     363             :                          */
     364          17 :                         peer = old_pi->peer;
     365          17 :                         if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
     366          11 :                             && BGP_PEER_RESTARTING_MODE(peer)
     367             :                             && (old_pi
     368           0 :                                 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
     369             :                                 set_flag = true;
     370             :                         }
     371             :                 }
     372             :                 if (set_flag)
     373             :                         break;
     374             :         }
     375             : 
     376             :         /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
     377             :          * is active
     378             :          */
     379          17 :         if (set_flag && table) {
     380           0 :                 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
     381           0 :                         if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
     382           0 :                                 bgp->gr_info[afi][safi].gr_deferred++;
     383           0 :                         SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
     384           0 :                         if (BGP_DEBUG(update, UPDATE_OUT))
     385           0 :                                 zlog_debug("DEFER route %pBD, dest %p", dest,
     386             :                                            dest);
     387           0 :                         return 0;
     388             :                 }
     389             :         }
     390             :         return -1;
     391             : }
     392             : 
     393          17 : void bgp_path_info_add_with_caller(const char *name, struct bgp_dest *dest,
     394             :                                    struct bgp_path_info *pi)
     395             : {
     396          17 :         frrtrace(3, frr_bgp, bgp_path_info_add, dest, pi, name);
     397          17 :         struct bgp_path_info *top;
     398             : 
     399          17 :         top = bgp_dest_get_bgp_path_info(dest);
     400             : 
     401          17 :         pi->next = top;
     402          17 :         pi->prev = NULL;
     403          17 :         if (top)
     404           3 :                 top->prev = pi;
     405          17 :         bgp_dest_set_bgp_path_info(dest, pi);
     406             : 
     407          17 :         bgp_path_info_lock(pi);
     408          17 :         bgp_dest_lock_node(dest);
     409          17 :         peer_lock(pi->peer); /* bgp_path_info peer reference */
     410          17 :         bgp_dest_set_defer_flag(dest, false);
     411          17 :         hook_call(bgp_snmp_update_stats, dest, pi, true);
     412          17 : }
     413             : 
     414             : /* Do the actual removal of info from RIB, for use by bgp_process
     415             :    completion callback *only* */
     416          17 : void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
     417             : {
     418          17 :         if (pi->next)
     419           3 :                 pi->next->prev = pi->prev;
     420          17 :         if (pi->prev)
     421           0 :                 pi->prev->next = pi->next;
     422             :         else
     423          17 :                 bgp_dest_set_bgp_path_info(dest, pi->next);
     424             : 
     425          17 :         bgp_path_info_mpath_dequeue(pi);
     426          17 :         bgp_path_info_unlock(pi);
     427          17 :         hook_call(bgp_snmp_update_stats, dest, pi, false);
     428          17 :         bgp_dest_unlock_node(dest);
     429          17 : }
     430             : 
     431          15 : void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
     432             : {
     433          30 :         bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
     434             :         /* set of previous already took care of pcount */
     435          15 :         UNSET_FLAG(pi->flags, BGP_PATH_VALID);
     436          15 : }
     437             : 
     438             : /* undo the effects of a previous call to bgp_path_info_delete; typically
     439             :    called when a route is deleted and then quickly re-added before the
     440             :    deletion has been processed */
     441           0 : void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
     442             : {
     443           0 :         bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
     444             :         /* unset of previous already took care of pcount */
     445           0 :         SET_FLAG(pi->flags, BGP_PATH_VALID);
     446           0 : }
     447             : 
     448             : /* Adjust pcount as required */
     449          26 : static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
     450             : {
     451          26 :         struct bgp_table *table;
     452             : 
     453          26 :         assert(dest && bgp_dest_table(dest));
     454          26 :         assert(pi && pi->peer && pi->peer->bgp);
     455             : 
     456          26 :         table = bgp_dest_table(dest);
     457             : 
     458          26 :         if (pi->peer == pi->peer->bgp->peer_self)
     459             :                 return;
     460             : 
     461          18 :         if (!BGP_PATH_COUNTABLE(pi)
     462           7 :             && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
     463             : 
     464           7 :                 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
     465             : 
     466             :                 /* slight hack, but more robust against errors. */
     467           7 :                 if (pi->peer->pcount[table->afi][table->safi])
     468           7 :                         pi->peer->pcount[table->afi][table->safi]--;
     469             :                 else
     470           0 :                         flog_err(EC_LIB_DEVELOPMENT,
     471             :                                  "Asked to decrement 0 prefix count for peer");
     472          11 :         } else if (BGP_PATH_COUNTABLE(pi)
     473          11 :                    && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
     474          11 :                 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
     475          11 :                 pi->peer->pcount[table->afi][table->safi]++;
     476             :         }
     477             : }
     478             : 
     479           0 : static int bgp_label_index_differs(struct bgp_path_info *pi1,
     480             :                                    struct bgp_path_info *pi2)
     481             : {
     482           0 :         return (!(pi1->attr->label_index == pi2->attr->label_index));
     483             : }
     484             : 
     485             : /* Set/unset bgp_path_info flags, adjusting any other state as needed.
     486             :  * This is here primarily to keep prefix-count in check.
     487             :  */
     488          40 : void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
     489             :                             uint32_t flag)
     490             : {
     491          40 :         SET_FLAG(pi->flags, flag);
     492             : 
     493             :         /* early bath if we know it's not a flag that changes countability state
     494             :          */
     495           0 :         if (!CHECK_FLAG(flag,
     496             :                         BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
     497             :                 return;
     498             : 
     499          15 :         bgp_pcount_adjust(dest, pi);
     500             : }
     501             : 
     502          20 : void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
     503             :                               uint32_t flag)
     504             : {
     505          20 :         UNSET_FLAG(pi->flags, flag);
     506             : 
     507             :         /* early bath if we know it's not a flag that changes countability state
     508             :          */
     509           0 :         if (!CHECK_FLAG(flag,
     510             :                         BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
     511             :                 return;
     512             : 
     513           0 :         bgp_pcount_adjust(dest, pi);
     514             : }
     515             : 
     516             : /* Get MED value.  If MED value is missing and "bgp bestpath
     517             :    missing-as-worst" is specified, treat it as the worst value. */
     518           0 : static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
     519             : {
     520           0 :         if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
     521           0 :                 return attr->med;
     522             :         else {
     523           0 :                 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
     524             :                         return BGP_MED_MAX;
     525             :                 else
     526           0 :                         return 0;
     527             :         }
     528             : }
     529             : 
     530           0 : void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
     531             :                                             size_t buf_len)
     532             : {
     533           0 :         if (pi->addpath_rx_id)
     534           0 :                 snprintf(buf, buf_len, "path %s (addpath rxid %d)",
     535           0 :                          pi->peer->host, pi->addpath_rx_id);
     536             :         else
     537           0 :                 snprintf(buf, buf_len, "path %s", pi->peer->host);
     538           0 : }
     539             : 
     540             : 
     541             : /*
     542             :  * Get the ultimate path info.
     543             :  */
     544          11 : struct bgp_path_info *bgp_get_imported_bpi_ultimate(struct bgp_path_info *info)
     545             : {
     546          11 :         struct bgp_path_info *bpi_ultimate;
     547             : 
     548          11 :         if (info->sub_type != BGP_ROUTE_IMPORTED)
     549             :                 return info;
     550             : 
     551             :         for (bpi_ultimate = info;
     552           0 :              bpi_ultimate->extra && bpi_ultimate->extra->parent;
     553             :              bpi_ultimate = bpi_ultimate->extra->parent)
     554             :                 ;
     555             : 
     556             :         return bpi_ultimate;
     557             : }
     558             : 
     559             : /* Compare two bgp route entity.  If 'new' is preferable over 'exist' return 1.
     560             :  */
     561          14 : static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
     562             :                              struct bgp_path_info *exist, int *paths_eq,
     563             :                              struct bgp_maxpaths_cfg *mpath_cfg, int debug,
     564             :                              char *pfx_buf, afi_t afi, safi_t safi,
     565             :                              enum bgp_path_selection_reason *reason)
     566             : {
     567          14 :         const struct prefix *new_p;
     568          14 :         struct attr *newattr, *existattr;
     569          14 :         enum bgp_peer_sort new_sort;
     570          14 :         enum bgp_peer_sort exist_sort;
     571          14 :         uint32_t new_pref;
     572          14 :         uint32_t exist_pref;
     573          14 :         uint32_t new_med;
     574          14 :         uint32_t exist_med;
     575          14 :         uint32_t new_weight;
     576          14 :         uint32_t exist_weight;
     577          14 :         uint32_t newm, existm;
     578          14 :         struct in_addr new_id;
     579          14 :         struct in_addr exist_id;
     580          14 :         int new_cluster;
     581          14 :         int exist_cluster;
     582          14 :         int internal_as_route;
     583          14 :         int confed_as_route;
     584          14 :         int ret = 0;
     585          14 :         int igp_metric_ret = 0;
     586          14 :         int peer_sort_ret = -1;
     587          14 :         char new_buf[PATH_ADDPATH_STR_BUFFER];
     588          14 :         char exist_buf[PATH_ADDPATH_STR_BUFFER];
     589          14 :         uint32_t new_mm_seq;
     590          14 :         uint32_t exist_mm_seq;
     591          14 :         int nh_cmp;
     592          14 :         esi_t *exist_esi;
     593          14 :         esi_t *new_esi;
     594          14 :         bool same_esi;
     595          14 :         bool old_proxy;
     596          14 :         bool new_proxy;
     597          14 :         bool new_origin, exist_origin;
     598          14 :         struct bgp_path_info *bpi_ultimate;
     599             : 
     600          14 :         *paths_eq = 0;
     601             : 
     602             :         /* 0. Null check. */
     603          14 :         if (new == NULL) {
     604           0 :                 *reason = bgp_path_selection_none;
     605           0 :                 if (debug)
     606           0 :                         zlog_debug("%s: new is NULL", pfx_buf);
     607           0 :                 return 0;
     608             :         }
     609             : 
     610          14 :         if (debug) {
     611           0 :                 bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
     612           0 :                 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, new_buf,
     613             :                                                        sizeof(new_buf));
     614             :         }
     615             : 
     616          14 :         if (exist == NULL) {
     617          14 :                 *reason = bgp_path_selection_first;
     618          14 :                 if (debug)
     619           0 :                         zlog_debug("%s(%s): %s is the initial bestpath",
     620             :                                    pfx_buf, bgp->name_pretty, new_buf);
     621          14 :                 return 1;
     622             :         }
     623             : 
     624           0 :         if (debug) {
     625           0 :                 bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
     626           0 :                 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, exist_buf,
     627             :                                                        sizeof(exist_buf));
     628           0 :                 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
     629             :                            pfx_buf, bgp->name_pretty, new_buf, new->flags,
     630             :                            exist_buf, exist->flags);
     631             :         }
     632             : 
     633           0 :         newattr = new->attr;
     634           0 :         existattr = exist->attr;
     635             : 
     636             :         /* A BGP speaker that has advertised the "Long-lived Graceful Restart
     637             :          * Capability" to a neighbor MUST perform the following upon receiving
     638             :          * a route from that neighbor with the "LLGR_STALE" community, or upon
     639             :          * attaching the "LLGR_STALE" community itself per Section 4.2:
     640             :          *
     641             :          * Treat the route as the least-preferred in route selection (see
     642             :          * below). See the Risks of Depreferencing Routes section (Section 5.2)
     643             :          * for a discussion of potential risks inherent in doing this.
     644             :          */
     645           0 :         if (bgp_attr_get_community(newattr) &&
     646           0 :             community_include(bgp_attr_get_community(newattr),
     647             :                               COMMUNITY_LLGR_STALE)) {
     648           0 :                 if (debug)
     649           0 :                         zlog_debug(
     650             :                                 "%s: %s wins over %s due to LLGR_STALE community",
     651             :                                 pfx_buf, new_buf, exist_buf);
     652           0 :                 return 0;
     653             :         }
     654             : 
     655           0 :         if (bgp_attr_get_community(existattr) &&
     656           0 :             community_include(bgp_attr_get_community(existattr),
     657             :                               COMMUNITY_LLGR_STALE)) {
     658           0 :                 if (debug)
     659           0 :                         zlog_debug(
     660             :                                 "%s: %s loses to %s due to LLGR_STALE community",
     661             :                                 pfx_buf, new_buf, exist_buf);
     662           0 :                 return 1;
     663             :         }
     664             : 
     665           0 :         new_p = bgp_dest_get_prefix(new->net);
     666             : 
     667             :         /* For EVPN routes, we cannot just go by local vs remote, we have to
     668             :          * look at the MAC mobility sequence number, if present.
     669             :          */
     670           0 :         if ((safi == SAFI_EVPN)
     671           0 :             && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
     672             :                 /* This is an error condition described in RFC 7432 Section
     673             :                  * 15.2. The RFC
     674             :                  * states that in this scenario "the PE MUST alert the operator"
     675             :                  * but it
     676             :                  * does not state what other action to take. In order to provide
     677             :                  * some
     678             :                  * consistency in this scenario we are going to prefer the path
     679             :                  * with the
     680             :                  * sticky flag.
     681             :                  */
     682           0 :                 if (newattr->sticky != existattr->sticky) {
     683           0 :                         if (!debug) {
     684           0 :                                 prefix2str(new_p, pfx_buf,
     685             :                                            sizeof(*pfx_buf)
     686             :                                                    * PREFIX2STR_BUFFER);
     687           0 :                                 bgp_path_info_path_with_addpath_rx_str(
     688             :                                         new, new_buf, sizeof(new_buf));
     689           0 :                                 bgp_path_info_path_with_addpath_rx_str(
     690             :                                         exist, exist_buf, sizeof(exist_buf));
     691             :                         }
     692             : 
     693           0 :                         if (newattr->sticky && !existattr->sticky) {
     694           0 :                                 *reason = bgp_path_selection_evpn_sticky_mac;
     695           0 :                                 if (debug)
     696           0 :                                         zlog_debug(
     697             :                                                 "%s: %s wins over %s due to sticky MAC flag",
     698             :                                                 pfx_buf, new_buf, exist_buf);
     699           0 :                                 return 1;
     700             :                         }
     701             : 
     702           0 :                         if (!newattr->sticky && existattr->sticky) {
     703           0 :                                 *reason = bgp_path_selection_evpn_sticky_mac;
     704           0 :                                 if (debug)
     705           0 :                                         zlog_debug(
     706             :                                                 "%s: %s loses to %s due to sticky MAC flag",
     707             :                                                 pfx_buf, new_buf, exist_buf);
     708           0 :                                 return 0;
     709             :                         }
     710             :                 }
     711             : 
     712           0 :                 new_esi = bgp_evpn_attr_get_esi(newattr);
     713           0 :                 exist_esi = bgp_evpn_attr_get_esi(existattr);
     714           0 :                 if (bgp_evpn_is_esi_valid(new_esi) &&
     715           0 :                                 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
     716             :                         same_esi = true;
     717             :                 } else {
     718             :                         same_esi = false;
     719             :                 }
     720             : 
     721             :                 /* If both paths have the same non-zero ES and
     722             :                  * one path is local it wins.
     723             :                  * PS: Note the local path wins even if the remote
     724             :                  * has the higher MM seq. The local path's
     725             :                  * MM seq will be fixed up to match the highest
     726             :                  * rem seq, subsequently.
     727             :                  */
     728           0 :                 if (same_esi) {
     729           0 :                         char esi_buf[ESI_STR_LEN];
     730             : 
     731           0 :                         if (bgp_evpn_is_path_local(bgp, new)) {
     732           0 :                                 *reason = bgp_path_selection_evpn_local_path;
     733           0 :                                 if (debug)
     734           0 :                                         zlog_debug(
     735             :                                                 "%s: %s wins over %s as ES %s is same and local",
     736             :                                                 pfx_buf, new_buf, exist_buf,
     737             :                                                 esi_to_str(new_esi, esi_buf,
     738             :                                                 sizeof(esi_buf)));
     739           0 :                                 return 1;
     740             :                         }
     741           0 :                         if (bgp_evpn_is_path_local(bgp, exist)) {
     742           0 :                                 *reason = bgp_path_selection_evpn_local_path;
     743           0 :                                 if (debug)
     744           0 :                                         zlog_debug(
     745             :                                                 "%s: %s loses to %s as ES %s is same and local",
     746             :                                                 pfx_buf, new_buf, exist_buf,
     747             :                                                 esi_to_str(new_esi, esi_buf,
     748             :                                                 sizeof(esi_buf)));
     749           0 :                                 return 0;
     750             :                         }
     751             :                 }
     752             : 
     753           0 :                 new_mm_seq = mac_mobility_seqnum(newattr);
     754           0 :                 exist_mm_seq = mac_mobility_seqnum(existattr);
     755             : 
     756           0 :                 if (new_mm_seq > exist_mm_seq) {
     757           0 :                         *reason = bgp_path_selection_evpn_seq;
     758           0 :                         if (debug)
     759           0 :                                 zlog_debug(
     760             :                                         "%s: %s wins over %s due to MM seq %u > %u",
     761             :                                         pfx_buf, new_buf, exist_buf, new_mm_seq,
     762             :                                         exist_mm_seq);
     763           0 :                         return 1;
     764             :                 }
     765             : 
     766           0 :                 if (new_mm_seq < exist_mm_seq) {
     767           0 :                         *reason = bgp_path_selection_evpn_seq;
     768           0 :                         if (debug)
     769           0 :                                 zlog_debug(
     770             :                                         "%s: %s loses to %s due to MM seq %u < %u",
     771             :                                         pfx_buf, new_buf, exist_buf, new_mm_seq,
     772             :                                         exist_mm_seq);
     773           0 :                         return 0;
     774             :                 }
     775             : 
     776             :                 /* if the sequence numbers and ESI are the same and one path
     777             :                  * is non-proxy it wins (over proxy)
     778             :                  */
     779           0 :                 new_proxy = bgp_evpn_attr_is_proxy(newattr);
     780           0 :                 old_proxy = bgp_evpn_attr_is_proxy(existattr);
     781           0 :                 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
     782             :                                 old_proxy != new_proxy) {
     783           0 :                         if (!new_proxy) {
     784           0 :                                 *reason = bgp_path_selection_evpn_non_proxy;
     785           0 :                                 if (debug)
     786           0 :                                         zlog_debug(
     787             :                                                 "%s: %s wins over %s, same seq/es and non-proxy",
     788             :                                                 pfx_buf, new_buf, exist_buf);
     789           0 :                                 return 1;
     790             :                         }
     791             : 
     792           0 :                         *reason = bgp_path_selection_evpn_non_proxy;
     793           0 :                         if (debug)
     794           0 :                                 zlog_debug(
     795             :                                         "%s: %s loses to %s, same seq/es and non-proxy",
     796             :                                         pfx_buf, new_buf, exist_buf);
     797           0 :                         return 0;
     798             :                 }
     799             : 
     800             :                 /*
     801             :                  * if sequence numbers are the same path with the lowest IP
     802             :                  * wins
     803             :                  */
     804           0 :                 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
     805           0 :                 if (nh_cmp < 0) {
     806           0 :                         *reason = bgp_path_selection_evpn_lower_ip;
     807           0 :                         if (debug)
     808           0 :                                 zlog_debug(
     809             :                                         "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
     810             :                                         pfx_buf, new_buf, exist_buf, new_mm_seq,
     811             :                                         &new->attr->nexthop);
     812           0 :                         return 1;
     813             :                 }
     814           0 :                 if (nh_cmp > 0) {
     815           0 :                         *reason = bgp_path_selection_evpn_lower_ip;
     816           0 :                         if (debug)
     817           0 :                                 zlog_debug(
     818             :                                         "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
     819             :                                         pfx_buf, new_buf, exist_buf, new_mm_seq,
     820             :                                         &new->attr->nexthop);
     821           0 :                         return 0;
     822             :                 }
     823             :         }
     824             : 
     825             :         /* 1. Weight check. */
     826           0 :         new_weight = newattr->weight;
     827           0 :         exist_weight = existattr->weight;
     828             : 
     829           0 :         if (new_weight > exist_weight) {
     830           0 :                 *reason = bgp_path_selection_weight;
     831           0 :                 if (debug)
     832           0 :                         zlog_debug("%s: %s wins over %s due to weight %d > %d",
     833             :                                    pfx_buf, new_buf, exist_buf, new_weight,
     834             :                                    exist_weight);
     835           0 :                 return 1;
     836             :         }
     837             : 
     838           0 :         if (new_weight < exist_weight) {
     839           0 :                 *reason = bgp_path_selection_weight;
     840           0 :                 if (debug)
     841           0 :                         zlog_debug("%s: %s loses to %s due to weight %d < %d",
     842             :                                    pfx_buf, new_buf, exist_buf, new_weight,
     843             :                                    exist_weight);
     844           0 :                 return 0;
     845             :         }
     846             : 
     847             :         /* 2. Local preference check. */
     848           0 :         new_pref = exist_pref = bgp->default_local_pref;
     849             : 
     850           0 :         if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
     851           0 :                 new_pref = newattr->local_pref;
     852           0 :         if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
     853           0 :                 exist_pref = existattr->local_pref;
     854             : 
     855           0 :         if (new_pref > exist_pref) {
     856           0 :                 *reason = bgp_path_selection_local_pref;
     857           0 :                 if (debug)
     858           0 :                         zlog_debug(
     859             :                                 "%s: %s wins over %s due to localpref %d > %d",
     860             :                                 pfx_buf, new_buf, exist_buf, new_pref,
     861             :                                 exist_pref);
     862           0 :                 return 1;
     863             :         }
     864             : 
     865           0 :         if (new_pref < exist_pref) {
     866           0 :                 *reason = bgp_path_selection_local_pref;
     867           0 :                 if (debug)
     868           0 :                         zlog_debug(
     869             :                                 "%s: %s loses to %s due to localpref %d < %d",
     870             :                                 pfx_buf, new_buf, exist_buf, new_pref,
     871             :                                 exist_pref);
     872           0 :                 return 0;
     873             :         }
     874             : 
     875             :         /* If a BGP speaker supports ACCEPT_OWN and is configured for the
     876             :          * extensions defined in this document, the following step is inserted
     877             :          * after the LOCAL_PREF comparison step in the BGP decision process:
     878             :          *      When comparing a pair of routes for a BGP destination, the
     879             :          *      route with the ACCEPT_OWN community attached is preferred over
     880             :          *      the route that does not have the community.
     881             :          * This extra step MUST only be invoked during the best path selection
     882             :          * process of VPN-IP routes.
     883             :          */
     884           0 :         if (safi == SAFI_MPLS_VPN &&
     885           0 :             (CHECK_FLAG(new->peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN) ||
     886           0 :              CHECK_FLAG(exist->peer->af_flags[afi][safi],
     887             :                         PEER_FLAG_ACCEPT_OWN))) {
     888           0 :                 bool new_accept_own = false;
     889           0 :                 bool exist_accept_own = false;
     890           0 :                 uint32_t accept_own = COMMUNITY_ACCEPT_OWN;
     891             : 
     892           0 :                 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
     893           0 :                         new_accept_own = community_include(
     894             :                                 bgp_attr_get_community(newattr), accept_own);
     895           0 :                 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
     896           0 :                         exist_accept_own = community_include(
     897             :                                 bgp_attr_get_community(existattr), accept_own);
     898             : 
     899           0 :                 if (new_accept_own && !exist_accept_own) {
     900           0 :                         *reason = bgp_path_selection_accept_own;
     901           0 :                         if (debug)
     902           0 :                                 zlog_debug(
     903             :                                         "%s: %s wins over %s due to accept-own",
     904             :                                         pfx_buf, new_buf, exist_buf);
     905           0 :                         return 1;
     906             :                 }
     907             : 
     908           0 :                 if (!new_accept_own && exist_accept_own) {
     909           0 :                         *reason = bgp_path_selection_accept_own;
     910           0 :                         if (debug)
     911           0 :                                 zlog_debug(
     912             :                                         "%s: %s loses to %s due to accept-own",
     913             :                                         pfx_buf, new_buf, exist_buf);
     914           0 :                         return 0;
     915             :                 }
     916             :         }
     917             : 
     918             :         /* Tie-breaker - AIGP (Metric TLV) attribute */
     919           0 :         if (CHECK_FLAG(newattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
     920           0 :             CHECK_FLAG(existattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
     921           0 :             CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_AIGP)) {
     922           0 :                 uint64_t new_aigp = bgp_attr_get_aigp_metric(newattr);
     923           0 :                 uint64_t exist_aigp = bgp_attr_get_aigp_metric(existattr);
     924             : 
     925           0 :                 if (new_aigp < exist_aigp) {
     926           0 :                         *reason = bgp_path_selection_aigp;
     927           0 :                         if (debug)
     928           0 :                                 zlog_debug(
     929             :                                         "%s: %s wins over %s due to AIGP %" PRIu64
     930             :                                         " < %" PRIu64,
     931             :                                         pfx_buf, new_buf, exist_buf, new_aigp,
     932             :                                         exist_aigp);
     933           0 :                         return 1;
     934             :                 }
     935             : 
     936           0 :                 if (new_aigp > exist_aigp) {
     937           0 :                         *reason = bgp_path_selection_aigp;
     938           0 :                         if (debug)
     939           0 :                                 zlog_debug(
     940             :                                         "%s: %s loses to %s due to AIGP %" PRIu64
     941             :                                         " > %" PRIu64,
     942             :                                         pfx_buf, new_buf, exist_buf, new_aigp,
     943             :                                         exist_aigp);
     944           0 :                         return 0;
     945             :                 }
     946             :         }
     947             : 
     948             :         /* 3. Local route check. We prefer:
     949             :          *  - BGP_ROUTE_STATIC
     950             :          *  - BGP_ROUTE_AGGREGATE
     951             :          *  - BGP_ROUTE_REDISTRIBUTE
     952             :          */
     953           0 :         new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
     954             :                        new->sub_type == BGP_ROUTE_IMPORTED);
     955           0 :         exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
     956             :                          exist->sub_type == BGP_ROUTE_IMPORTED);
     957             : 
     958           0 :         if (new_origin && !exist_origin) {
     959           0 :                 *reason = bgp_path_selection_local_route;
     960           0 :                 if (debug)
     961           0 :                         zlog_debug(
     962             :                                 "%s: %s wins over %s due to preferred BGP_ROUTE type",
     963             :                                 pfx_buf, new_buf, exist_buf);
     964           0 :                 return 1;
     965             :         }
     966             : 
     967           0 :         if (!new_origin && exist_origin) {
     968           0 :                 *reason = bgp_path_selection_local_route;
     969           0 :                 if (debug)
     970           0 :                         zlog_debug(
     971             :                                 "%s: %s loses to %s due to preferred BGP_ROUTE type",
     972             :                                 pfx_buf, new_buf, exist_buf);
     973           0 :                 return 0;
     974             :         }
     975             : 
     976             :         /* Here if these are imported routes then get ultimate pi for
     977             :          * path compare.
     978             :          */
     979           0 :         new = bgp_get_imported_bpi_ultimate(new);
     980           0 :         exist = bgp_get_imported_bpi_ultimate(exist);
     981           0 :         newattr = new->attr;
     982           0 :         existattr = exist->attr;
     983             : 
     984             :         /* 4. AS path length check. */
     985           0 :         if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
     986           0 :                 int exist_hops = aspath_count_hops(existattr->aspath);
     987           0 :                 int exist_confeds = aspath_count_confeds(existattr->aspath);
     988             : 
     989           0 :                 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
     990           0 :                         int aspath_hops;
     991             : 
     992           0 :                         aspath_hops = aspath_count_hops(newattr->aspath);
     993           0 :                         aspath_hops += aspath_count_confeds(newattr->aspath);
     994             : 
     995           0 :                         if (aspath_hops < (exist_hops + exist_confeds)) {
     996           0 :                                 *reason = bgp_path_selection_confed_as_path;
     997           0 :                                 if (debug)
     998           0 :                                         zlog_debug(
     999             :                                                 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
    1000             :                                                 pfx_buf, new_buf, exist_buf,
    1001             :                                                 aspath_hops,
    1002             :                                                 (exist_hops + exist_confeds));
    1003           0 :                                 return 1;
    1004             :                         }
    1005             : 
    1006           0 :                         if (aspath_hops > (exist_hops + exist_confeds)) {
    1007           0 :                                 *reason = bgp_path_selection_confed_as_path;
    1008           0 :                                 if (debug)
    1009           0 :                                         zlog_debug(
    1010             :                                                 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
    1011             :                                                 pfx_buf, new_buf, exist_buf,
    1012             :                                                 aspath_hops,
    1013             :                                                 (exist_hops + exist_confeds));
    1014           0 :                                 return 0;
    1015             :                         }
    1016             :                 } else {
    1017           0 :                         int newhops = aspath_count_hops(newattr->aspath);
    1018             : 
    1019           0 :                         if (newhops < exist_hops) {
    1020           0 :                                 *reason = bgp_path_selection_as_path;
    1021           0 :                                 if (debug)
    1022           0 :                                         zlog_debug(
    1023             :                                                 "%s: %s wins over %s due to aspath hopcount %d < %d",
    1024             :                                                 pfx_buf, new_buf, exist_buf,
    1025             :                                                 newhops, exist_hops);
    1026           0 :                                 return 1;
    1027             :                         }
    1028             : 
    1029           0 :                         if (newhops > exist_hops) {
    1030           0 :                                 *reason = bgp_path_selection_as_path;
    1031           0 :                                 if (debug)
    1032           0 :                                         zlog_debug(
    1033             :                                                 "%s: %s loses to %s due to aspath hopcount %d > %d",
    1034             :                                                 pfx_buf, new_buf, exist_buf,
    1035             :                                                 newhops, exist_hops);
    1036           0 :                                 return 0;
    1037             :                         }
    1038             :                 }
    1039             :         }
    1040             : 
    1041             :         /* 5. Origin check. */
    1042           0 :         if (newattr->origin < existattr->origin) {
    1043           0 :                 *reason = bgp_path_selection_origin;
    1044           0 :                 if (debug)
    1045           0 :                         zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
    1046             :                                    pfx_buf, new_buf, exist_buf,
    1047             :                                    bgp_origin_long_str[newattr->origin],
    1048             :                                    bgp_origin_long_str[existattr->origin]);
    1049           0 :                 return 1;
    1050             :         }
    1051             : 
    1052           0 :         if (newattr->origin > existattr->origin) {
    1053           0 :                 *reason = bgp_path_selection_origin;
    1054           0 :                 if (debug)
    1055           0 :                         zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
    1056             :                                    pfx_buf, new_buf, exist_buf,
    1057             :                                    bgp_origin_long_str[newattr->origin],
    1058             :                                    bgp_origin_long_str[existattr->origin]);
    1059           0 :                 return 0;
    1060             :         }
    1061             : 
    1062             :         /* 6. MED check. */
    1063           0 :         internal_as_route = (aspath_count_hops(newattr->aspath) == 0
    1064           0 :                              && aspath_count_hops(existattr->aspath) == 0);
    1065           0 :         confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
    1066           0 :                            && aspath_count_confeds(existattr->aspath) > 0
    1067           0 :                            && aspath_count_hops(newattr->aspath) == 0
    1068           0 :                            && aspath_count_hops(existattr->aspath) == 0);
    1069             : 
    1070           0 :         if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
    1071           0 :             || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
    1072           0 :             || aspath_cmp_left(newattr->aspath, existattr->aspath)
    1073           0 :             || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
    1074           0 :             || internal_as_route) {
    1075           0 :                 new_med = bgp_med_value(new->attr, bgp);
    1076           0 :                 exist_med = bgp_med_value(exist->attr, bgp);
    1077             : 
    1078           0 :                 if (new_med < exist_med) {
    1079           0 :                         *reason = bgp_path_selection_med;
    1080           0 :                         if (debug)
    1081           0 :                                 zlog_debug(
    1082             :                                         "%s: %s wins over %s due to MED %d < %d",
    1083             :                                         pfx_buf, new_buf, exist_buf, new_med,
    1084             :                                         exist_med);
    1085           0 :                         return 1;
    1086             :                 }
    1087             : 
    1088           0 :                 if (new_med > exist_med) {
    1089           0 :                         *reason = bgp_path_selection_med;
    1090           0 :                         if (debug)
    1091           0 :                                 zlog_debug(
    1092             :                                         "%s: %s loses to %s due to MED %d > %d",
    1093             :                                         pfx_buf, new_buf, exist_buf, new_med,
    1094             :                                         exist_med);
    1095           0 :                         return 0;
    1096             :                 }
    1097             :         }
    1098             : 
    1099             :         /* 7. Peer type check. */
    1100           0 :         new_sort = new->peer->sort;
    1101           0 :         exist_sort = exist->peer->sort;
    1102             : 
    1103           0 :         if (new_sort == BGP_PEER_EBGP
    1104           0 :             && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
    1105           0 :                 *reason = bgp_path_selection_peer;
    1106           0 :                 if (debug)
    1107           0 :                         zlog_debug(
    1108             :                                 "%s: %s wins over %s due to eBGP peer > iBGP peer",
    1109             :                                 pfx_buf, new_buf, exist_buf);
    1110           0 :                 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
    1111             :                         return 1;
    1112             :                 peer_sort_ret = 1;
    1113             :         }
    1114             : 
    1115           0 :         if (exist_sort == BGP_PEER_EBGP
    1116           0 :             && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
    1117           0 :                 *reason = bgp_path_selection_peer;
    1118           0 :                 if (debug)
    1119           0 :                         zlog_debug(
    1120             :                                 "%s: %s loses to %s due to iBGP peer < eBGP peer",
    1121             :                                 pfx_buf, new_buf, exist_buf);
    1122           0 :                 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
    1123             :                         return 0;
    1124             :                 peer_sort_ret = 0;
    1125             :         }
    1126             : 
    1127             :         /* 8. IGP metric check. */
    1128           0 :         newm = existm = 0;
    1129             : 
    1130           0 :         if (new->extra)
    1131           0 :                 newm = new->extra->igpmetric;
    1132           0 :         if (exist->extra)
    1133           0 :                 existm = exist->extra->igpmetric;
    1134             : 
    1135           0 :         if (newm < existm) {
    1136           0 :                 if (debug && peer_sort_ret < 0)
    1137           0 :                         zlog_debug(
    1138             :                                 "%s: %s wins over %s due to IGP metric %u < %u",
    1139             :                                 pfx_buf, new_buf, exist_buf, newm, existm);
    1140             :                 igp_metric_ret = 1;
    1141             :         }
    1142             : 
    1143           0 :         if (newm > existm) {
    1144           0 :                 if (debug && peer_sort_ret < 0)
    1145           0 :                         zlog_debug(
    1146             :                                 "%s: %s loses to %s due to IGP metric %u > %u",
    1147             :                                 pfx_buf, new_buf, exist_buf, newm, existm);
    1148             :                 igp_metric_ret = 0;
    1149             :         }
    1150             : 
    1151             :         /* 9. Same IGP metric. Compare the cluster list length as
    1152             :            representative of IGP hops metric. Rewrite the metric value
    1153             :            pair (newm, existm) with the cluster list length. Prefer the
    1154             :            path with smaller cluster list length.                       */
    1155           0 :         if (newm == existm) {
    1156           0 :                 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP &&
    1157           0 :                     peer_sort_lookup(exist->peer) == BGP_PEER_IBGP &&
    1158           0 :                     (mpath_cfg == NULL || mpath_cfg->same_clusterlen)) {
    1159           0 :                         newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
    1160           0 :                         existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
    1161             : 
    1162           0 :                         if (newm < existm) {
    1163           0 :                                 if (debug && peer_sort_ret < 0)
    1164           0 :                                         zlog_debug(
    1165             :                                                 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
    1166             :                                                 pfx_buf, new_buf, exist_buf,
    1167             :                                                 newm, existm);
    1168             :                                 igp_metric_ret = 1;
    1169             :                         }
    1170             : 
    1171           0 :                         if (newm > existm) {
    1172           0 :                                 if (debug && peer_sort_ret < 0)
    1173           0 :                                         zlog_debug(
    1174             :                                                 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
    1175             :                                                 pfx_buf, new_buf, exist_buf,
    1176             :                                                 newm, existm);
    1177             :                                 igp_metric_ret = 0;
    1178             :                         }
    1179             :                 }
    1180             :         }
    1181             : 
    1182             :         /* 10. confed-external vs. confed-internal */
    1183           0 :         if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
    1184           0 :                 if (new_sort == BGP_PEER_CONFED
    1185           0 :                     && exist_sort == BGP_PEER_IBGP) {
    1186           0 :                         *reason = bgp_path_selection_confed;
    1187           0 :                         if (debug)
    1188           0 :                                 zlog_debug(
    1189             :                                         "%s: %s wins over %s due to confed-external peer > confed-internal peer",
    1190             :                                         pfx_buf, new_buf, exist_buf);
    1191           0 :                         if (!CHECK_FLAG(bgp->flags,
    1192             :                                         BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
    1193             :                                 return 1;
    1194             :                         peer_sort_ret = 1;
    1195             :                 }
    1196             : 
    1197           0 :                 if (exist_sort == BGP_PEER_CONFED
    1198           0 :                     && new_sort == BGP_PEER_IBGP) {
    1199           0 :                         *reason = bgp_path_selection_confed;
    1200           0 :                         if (debug)
    1201           0 :                                 zlog_debug(
    1202             :                                         "%s: %s loses to %s due to confed-internal peer < confed-external peer",
    1203             :                                         pfx_buf, new_buf, exist_buf);
    1204           0 :                         if (!CHECK_FLAG(bgp->flags,
    1205             :                                         BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
    1206             :                                 return 0;
    1207             :                         peer_sort_ret = 0;
    1208             :                 }
    1209             :         }
    1210             : 
    1211             :         /* 11. Maximum path check. */
    1212           0 :         if (newm == existm) {
    1213             :                 /* If one path has a label but the other does not, do not treat
    1214             :                  * them as equals for multipath
    1215             :                  */
    1216           0 :                 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
    1217           0 :                     != (exist->extra
    1218           0 :                         && bgp_is_valid_label(&exist->extra->label[0]))) {
    1219           0 :                         if (debug)
    1220           0 :                                 zlog_debug(
    1221             :                                         "%s: %s and %s cannot be multipath, one has a label while the other does not",
    1222             :                                         pfx_buf, new_buf, exist_buf);
    1223           0 :                 } else if (CHECK_FLAG(bgp->flags,
    1224             :                                       BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
    1225             : 
    1226             :                         /*
    1227             :                          * For the two paths, all comparison steps till IGP
    1228             :                          * metric
    1229             :                          * have succeeded - including AS_PATH hop count. Since
    1230             :                          * 'bgp
    1231             :                          * bestpath as-path multipath-relax' knob is on, we
    1232             :                          * don't need
    1233             :                          * an exact match of AS_PATH. Thus, mark the paths are
    1234             :                          * equal.
    1235             :                          * That will trigger both these paths to get into the
    1236             :                          * multipath
    1237             :                          * array.
    1238             :                          */
    1239           0 :                         *paths_eq = 1;
    1240             : 
    1241           0 :                         if (debug)
    1242           0 :                                 zlog_debug(
    1243             :                                         "%s: %s and %s are equal via multipath-relax",
    1244             :                                         pfx_buf, new_buf, exist_buf);
    1245           0 :                 } else if (new->peer->sort == BGP_PEER_IBGP) {
    1246           0 :                         if (aspath_cmp(new->attr->aspath,
    1247           0 :                                        exist->attr->aspath)) {
    1248           0 :                                 *paths_eq = 1;
    1249             : 
    1250           0 :                                 if (debug)
    1251           0 :                                         zlog_debug(
    1252             :                                                 "%s: %s and %s are equal via matching aspaths",
    1253             :                                                 pfx_buf, new_buf, exist_buf);
    1254             :                         }
    1255           0 :                 } else if (new->peer->as == exist->peer->as) {
    1256           0 :                         *paths_eq = 1;
    1257             : 
    1258           0 :                         if (debug)
    1259           0 :                                 zlog_debug(
    1260             :                                         "%s: %s and %s are equal via same remote-as",
    1261             :                                         pfx_buf, new_buf, exist_buf);
    1262             :                 }
    1263             :         } else {
    1264             :                 /*
    1265             :                  * TODO: If unequal cost ibgp multipath is enabled we can
    1266             :                  * mark the paths as equal here instead of returning
    1267             :                  */
    1268             : 
    1269             :                 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
    1270             :                  * if either step 7 or 10 (peer type checks) yielded a winner,
    1271             :                  * that result was returned immediately. Returning from step 10
    1272             :                  * ignored the return value computed in steps 8 and 9 (IGP
    1273             :                  * metric checks). In order to preserve that behavior, if
    1274             :                  * peer_sort_ret is set, return that rather than igp_metric_ret.
    1275             :                  */
    1276           0 :                 ret = peer_sort_ret;
    1277           0 :                 if (peer_sort_ret < 0) {
    1278           0 :                         ret = igp_metric_ret;
    1279           0 :                         if (debug) {
    1280           0 :                                 if (ret == 1)
    1281           0 :                                         zlog_debug(
    1282             :                                                 "%s: %s wins over %s after IGP metric comparison",
    1283             :                                                 pfx_buf, new_buf, exist_buf);
    1284             :                                 else
    1285           0 :                                         zlog_debug(
    1286             :                                                 "%s: %s loses to %s after IGP metric comparison",
    1287             :                                                 pfx_buf, new_buf, exist_buf);
    1288             :                         }
    1289           0 :                         *reason = bgp_path_selection_igp_metric;
    1290             :                 }
    1291           0 :                 return ret;
    1292             :         }
    1293             : 
    1294             :         /*
    1295             :          * At this point, the decision whether to set *paths_eq = 1 has been
    1296             :          * completed. If we deferred returning because of bestpath peer-type
    1297             :          * relax configuration, return now.
    1298             :          */
    1299           0 :         if (peer_sort_ret >= 0)
    1300             :                 return peer_sort_ret;
    1301             : 
    1302             :         /* 12. If both paths are external, prefer the path that was received
    1303             :            first (the oldest one).  This step minimizes route-flap, since a
    1304             :            newer path won't displace an older one, even if it was the
    1305             :            preferred route based on the additional decision criteria below.  */
    1306           0 :         if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
    1307           0 :             && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
    1308           0 :                 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
    1309           0 :                         *reason = bgp_path_selection_older;
    1310           0 :                         if (debug)
    1311           0 :                                 zlog_debug(
    1312             :                                         "%s: %s wins over %s due to oldest external",
    1313             :                                         pfx_buf, new_buf, exist_buf);
    1314           0 :                         return 1;
    1315             :                 }
    1316             : 
    1317           0 :                 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
    1318           0 :                         *reason = bgp_path_selection_older;
    1319           0 :                         if (debug)
    1320           0 :                                 zlog_debug(
    1321             :                                         "%s: %s loses to %s due to oldest external",
    1322             :                                         pfx_buf, new_buf, exist_buf);
    1323           0 :                         return 0;
    1324             :                 }
    1325             :         }
    1326             : 
    1327             :         /* 13. Router-ID comparison. */
    1328             :         /* If one of the paths is "stale", the corresponding peer router-id will
    1329             :          * be 0 and would always win over the other path. If originator id is
    1330             :          * used for the comparison, it will decide which path is better.
    1331             :          */
    1332           0 :         if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
    1333           0 :                 new_id.s_addr = newattr->originator_id.s_addr;
    1334             :         else
    1335           0 :                 new_id.s_addr = new->peer->remote_id.s_addr;
    1336           0 :         if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
    1337           0 :                 exist_id.s_addr = existattr->originator_id.s_addr;
    1338             :         else
    1339           0 :                 exist_id.s_addr = exist->peer->remote_id.s_addr;
    1340             : 
    1341           0 :         if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
    1342           0 :                 *reason = bgp_path_selection_router_id;
    1343           0 :                 if (debug)
    1344           0 :                         zlog_debug(
    1345             :                                 "%s: %s wins over %s due to Router-ID comparison",
    1346             :                                 pfx_buf, new_buf, exist_buf);
    1347           0 :                 return 1;
    1348             :         }
    1349             : 
    1350           0 :         if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
    1351           0 :                 *reason = bgp_path_selection_router_id;
    1352           0 :                 if (debug)
    1353           0 :                         zlog_debug(
    1354             :                                 "%s: %s loses to %s due to Router-ID comparison",
    1355             :                                 pfx_buf, new_buf, exist_buf);
    1356           0 :                 return 0;
    1357             :         }
    1358             : 
    1359             :         /* 14. Cluster length comparison. */
    1360           0 :         new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
    1361           0 :         exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
    1362             : 
    1363           0 :         if (new_cluster < exist_cluster) {
    1364           0 :                 *reason = bgp_path_selection_cluster_length;
    1365           0 :                 if (debug)
    1366           0 :                         zlog_debug(
    1367             :                                 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
    1368             :                                 pfx_buf, new_buf, exist_buf, new_cluster,
    1369             :                                 exist_cluster);
    1370           0 :                 return 1;
    1371             :         }
    1372             : 
    1373           0 :         if (new_cluster > exist_cluster) {
    1374           0 :                 *reason = bgp_path_selection_cluster_length;
    1375           0 :                 if (debug)
    1376           0 :                         zlog_debug(
    1377             :                                 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
    1378             :                                 pfx_buf, new_buf, exist_buf, new_cluster,
    1379             :                                 exist_cluster);
    1380           0 :                 return 0;
    1381             :         }
    1382             : 
    1383             :         /* 15. Neighbor address comparison. */
    1384             :         /* Do this only if neither path is "stale" as stale paths do not have
    1385             :          * valid peer information (as the connection may or may not be up).
    1386             :          */
    1387           0 :         if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
    1388           0 :                 *reason = bgp_path_selection_stale;
    1389           0 :                 if (debug)
    1390           0 :                         zlog_debug(
    1391             :                                 "%s: %s wins over %s due to latter path being STALE",
    1392             :                                 pfx_buf, new_buf, exist_buf);
    1393           0 :                 return 1;
    1394             :         }
    1395             : 
    1396           0 :         if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
    1397           0 :                 *reason = bgp_path_selection_stale;
    1398           0 :                 if (debug)
    1399           0 :                         zlog_debug(
    1400             :                                 "%s: %s loses to %s due to former path being STALE",
    1401             :                                 pfx_buf, new_buf, exist_buf);
    1402           0 :                 return 0;
    1403             :         }
    1404             : 
    1405             :         /* locally configured routes to advertise do not have su_remote */
    1406           0 :         if (new->peer->su_remote == NULL) {
    1407           0 :                 *reason = bgp_path_selection_local_configured;
    1408           0 :                 return 0;
    1409             :         }
    1410           0 :         if (exist->peer->su_remote == NULL) {
    1411           0 :                 *reason = bgp_path_selection_local_configured;
    1412           0 :                 return 1;
    1413             :         }
    1414             : 
    1415           0 :         ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
    1416             : 
    1417           0 :         if (ret == 1) {
    1418           0 :                 *reason = bgp_path_selection_neighbor_ip;
    1419           0 :                 if (debug)
    1420           0 :                         zlog_debug(
    1421             :                                 "%s: %s loses to %s due to Neighor IP comparison",
    1422             :                                 pfx_buf, new_buf, exist_buf);
    1423           0 :                 return 0;
    1424             :         }
    1425             : 
    1426           0 :         if (ret == -1) {
    1427           0 :                 *reason = bgp_path_selection_neighbor_ip;
    1428           0 :                 if (debug)
    1429           0 :                         zlog_debug(
    1430             :                                 "%s: %s wins over %s due to Neighor IP comparison",
    1431             :                                 pfx_buf, new_buf, exist_buf);
    1432           0 :                 return 1;
    1433             :         }
    1434             : 
    1435           0 :         *reason = bgp_path_selection_default;
    1436           0 :         if (debug)
    1437           0 :                 zlog_debug("%s: %s wins over %s due to nothing left to compare",
    1438             :                            pfx_buf, new_buf, exist_buf);
    1439             : 
    1440             :         return 1;
    1441             : }
    1442             : 
    1443             : 
    1444           0 : int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
    1445             :                              struct bgp_path_info *exist, int *paths_eq)
    1446             : {
    1447           0 :         enum bgp_path_selection_reason reason;
    1448           0 :         char pfx_buf[PREFIX2STR_BUFFER];
    1449             : 
    1450           0 :         return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
    1451             :                                 AFI_L2VPN, SAFI_EVPN, &reason);
    1452             : }
    1453             : 
    1454             : /* Compare two bgp route entity.  Return -1 if new is preferred, 1 if exist
    1455             :  * is preferred, or 0 if they are the same (usually will only occur if
    1456             :  * multipath is enabled
    1457             :  * This version is compatible with */
    1458           0 : int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
    1459             :                                  struct bgp_path_info *exist, char *pfx_buf,
    1460             :                                  afi_t afi, safi_t safi,
    1461             :                                  enum bgp_path_selection_reason *reason)
    1462             : {
    1463           0 :         int paths_eq;
    1464           0 :         int ret;
    1465           0 :         ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
    1466             :                                 afi, safi, reason);
    1467             : 
    1468           0 :         if (paths_eq)
    1469             :                 ret = 0;
    1470             :         else {
    1471           0 :                 if (ret == 1)
    1472             :                         ret = -1;
    1473             :                 else
    1474           0 :                         ret = 1;
    1475             :         }
    1476           0 :         return ret;
    1477             : }
    1478             : 
    1479          15 : static enum filter_type bgp_input_filter(struct peer *peer,
    1480             :                                          const struct prefix *p,
    1481             :                                          struct attr *attr, afi_t afi,
    1482             :                                          safi_t safi)
    1483             : {
    1484          15 :         struct bgp_filter *filter;
    1485          15 :         enum filter_type ret = FILTER_PERMIT;
    1486             : 
    1487          15 :         filter = &peer->filter[afi][safi];
    1488             : 
    1489             : #define FILTER_EXIST_WARN(F, f, filter)                                        \
    1490             :         if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter)))                 \
    1491             :                 zlog_debug("%s: Could not find configured input %s-list %s!",  \
    1492             :                            peer->host, #f, F##_IN_NAME(filter));
    1493             : 
    1494          15 :         if (DISTRIBUTE_IN_NAME(filter)) {
    1495           0 :                 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
    1496             : 
    1497           0 :                 if (access_list_apply(DISTRIBUTE_IN(filter), p)
    1498             :                     == FILTER_DENY) {
    1499           0 :                         ret = FILTER_DENY;
    1500           0 :                         goto done;
    1501             :                 }
    1502             :         }
    1503             : 
    1504          15 :         if (PREFIX_LIST_IN_NAME(filter)) {
    1505           0 :                 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
    1506             : 
    1507           0 :                 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
    1508             :                     == PREFIX_DENY) {
    1509           0 :                         ret = FILTER_DENY;
    1510           0 :                         goto done;
    1511             :                 }
    1512             :         }
    1513             : 
    1514          15 :         if (FILTER_LIST_IN_NAME(filter)) {
    1515           0 :                 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
    1516             : 
    1517           0 :                 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
    1518             :                     == AS_FILTER_DENY) {
    1519           0 :                         ret = FILTER_DENY;
    1520           0 :                         goto done;
    1521             :                 }
    1522             :         }
    1523             : 
    1524          15 : done:
    1525          15 :         if (frrtrace_enabled(frr_bgp, input_filter)) {
    1526          15 :                 char pfxprint[PREFIX2STR_BUFFER];
    1527             : 
    1528          15 :                 prefix2str(p, pfxprint, sizeof(pfxprint));
    1529          15 :                 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
    1530             :                          ret == FILTER_PERMIT ? "permit" : "deny");
    1531             :         }
    1532             : 
    1533          15 :         return ret;
    1534             : #undef FILTER_EXIST_WARN
    1535             : }
    1536             : 
    1537          16 : static enum filter_type bgp_output_filter(struct peer *peer,
    1538             :                                           const struct prefix *p,
    1539             :                                           struct attr *attr, afi_t afi,
    1540             :                                           safi_t safi)
    1541             : {
    1542          16 :         struct bgp_filter *filter;
    1543          16 :         enum filter_type ret = FILTER_PERMIT;
    1544             : 
    1545          16 :         filter = &peer->filter[afi][safi];
    1546             : 
    1547             : #define FILTER_EXIST_WARN(F, f, filter)                                        \
    1548             :         if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter)))               \
    1549             :                 zlog_debug("%s: Could not find configured output %s-list %s!", \
    1550             :                            peer->host, #f, F##_OUT_NAME(filter));
    1551             : 
    1552          16 :         if (DISTRIBUTE_OUT_NAME(filter)) {
    1553           0 :                 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
    1554             : 
    1555           0 :                 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
    1556             :                     == FILTER_DENY) {
    1557           0 :                         ret = FILTER_DENY;
    1558           0 :                         goto done;
    1559             :                 }
    1560             :         }
    1561             : 
    1562          16 :         if (PREFIX_LIST_OUT_NAME(filter)) {
    1563           0 :                 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
    1564             : 
    1565           0 :                 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
    1566             :                     == PREFIX_DENY) {
    1567           0 :                         ret = FILTER_DENY;
    1568           0 :                         goto done;
    1569             :                 }
    1570             :         }
    1571             : 
    1572          16 :         if (FILTER_LIST_OUT_NAME(filter)) {
    1573           0 :                 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
    1574             : 
    1575           0 :                 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
    1576             :                     == AS_FILTER_DENY) {
    1577           0 :                         ret = FILTER_DENY;
    1578           0 :                         goto done;
    1579             :                 }
    1580             :         }
    1581             : 
    1582          16 :         if (frrtrace_enabled(frr_bgp, output_filter)) {
    1583          16 :                 char pfxprint[PREFIX2STR_BUFFER];
    1584             : 
    1585          16 :                 prefix2str(p, pfxprint, sizeof(pfxprint));
    1586          16 :                 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
    1587             :                          ret == FILTER_PERMIT ? "permit" : "deny");
    1588             :         }
    1589             : 
    1590          16 : done:
    1591          16 :         return ret;
    1592             : #undef FILTER_EXIST_WARN
    1593             : }
    1594             : 
    1595             : /* If community attribute includes no_export then return 1. */
    1596          16 : static bool bgp_community_filter(struct peer *peer, struct attr *attr)
    1597             : {
    1598          16 :         if (bgp_attr_get_community(attr)) {
    1599             :                 /* NO_ADVERTISE check. */
    1600           0 :                 if (community_include(bgp_attr_get_community(attr),
    1601             :                                       COMMUNITY_NO_ADVERTISE))
    1602             :                         return true;
    1603             : 
    1604             :                 /* NO_EXPORT check. */
    1605           0 :                 if (peer->sort == BGP_PEER_EBGP &&
    1606           0 :                     community_include(bgp_attr_get_community(attr),
    1607             :                                       COMMUNITY_NO_EXPORT))
    1608             :                         return true;
    1609             : 
    1610             :                 /* NO_EXPORT_SUBCONFED check. */
    1611           0 :                 if (peer->sort == BGP_PEER_EBGP
    1612           0 :                     || peer->sort == BGP_PEER_CONFED)
    1613           0 :                         if (community_include(bgp_attr_get_community(attr),
    1614             :                                               COMMUNITY_NO_EXPORT_SUBCONFED))
    1615             :                                 return true;
    1616             :         }
    1617             :         return false;
    1618             : }
    1619             : 
    1620             : /* Route reflection loop check.  */
    1621          15 : static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
    1622             : {
    1623          15 :         struct in_addr cluster_id;
    1624          15 :         struct cluster_list *cluster = bgp_attr_get_cluster(attr);
    1625             : 
    1626          15 :         if (cluster) {
    1627           0 :                 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
    1628           0 :                         cluster_id = peer->bgp->cluster_id;
    1629             :                 else
    1630           0 :                         cluster_id = peer->bgp->router_id;
    1631             : 
    1632           0 :                 if (cluster_loop_check(cluster, cluster_id))
    1633             :                         return true;
    1634             :         }
    1635             :         return false;
    1636             : }
    1637             : 
    1638          11 : static bool bgp_otc_filter(struct peer *peer, struct attr *attr)
    1639             : {
    1640          11 :         if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
    1641           0 :                 if (peer->local_role == ROLE_PROVIDER ||
    1642             :                     peer->local_role == ROLE_RS_SERVER)
    1643             :                         return true;
    1644           0 :                 if (peer->local_role == ROLE_PEER && attr->otc != peer->as)
    1645             :                         return true;
    1646             :                 return false;
    1647             :         }
    1648          11 :         if (peer->local_role == ROLE_CUSTOMER ||
    1649          11 :             peer->local_role == ROLE_PEER ||
    1650             :             peer->local_role == ROLE_RS_CLIENT) {
    1651           0 :                 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
    1652           0 :                 attr->otc = peer->as;
    1653             :         }
    1654             :         return false;
    1655             : }
    1656             : 
    1657          16 : static bool bgp_otc_egress(struct peer *peer, struct attr *attr)
    1658             : {
    1659          16 :         if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
    1660           0 :                 if (peer->local_role == ROLE_CUSTOMER ||
    1661           0 :                     peer->local_role == ROLE_RS_CLIENT ||
    1662             :                     peer->local_role == ROLE_PEER)
    1663             :                         return true;
    1664             :                 return false;
    1665             :         }
    1666          16 :         if (peer->local_role == ROLE_PROVIDER ||
    1667          16 :             peer->local_role == ROLE_PEER ||
    1668             :             peer->local_role == ROLE_RS_SERVER) {
    1669           0 :                 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
    1670           0 :                 attr->otc = peer->bgp->as;
    1671             :         }
    1672             :         return false;
    1673             : }
    1674             : 
    1675          27 : static bool bgp_check_role_applicability(afi_t afi, safi_t safi)
    1676             : {
    1677          27 :         return ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST);
    1678             : }
    1679             : 
    1680          15 : static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
    1681             :                               struct attr *attr, afi_t afi, safi_t safi,
    1682             :                               const char *rmap_name, mpls_label_t *label,
    1683             :                               uint32_t num_labels, struct bgp_dest *dest)
    1684             : {
    1685          15 :         struct bgp_filter *filter;
    1686          15 :         struct bgp_path_info rmap_path = { 0 };
    1687          15 :         struct bgp_path_info_extra extra = { 0 };
    1688          15 :         route_map_result_t ret;
    1689          15 :         struct route_map *rmap = NULL;
    1690             : 
    1691          15 :         filter = &peer->filter[afi][safi];
    1692             : 
    1693             :         /* Apply default weight value. */
    1694          15 :         if (peer->weight[afi][safi])
    1695           0 :                 attr->weight = peer->weight[afi][safi];
    1696             : 
    1697          15 :         if (rmap_name) {
    1698           0 :                 rmap = route_map_lookup_by_name(rmap_name);
    1699             : 
    1700           0 :                 if (rmap == NULL)
    1701             :                         return RMAP_DENY;
    1702             :         } else {
    1703          15 :                 if (ROUTE_MAP_IN_NAME(filter)) {
    1704           8 :                         rmap = ROUTE_MAP_IN(filter);
    1705             : 
    1706           8 :                         if (rmap == NULL)
    1707             :                                 return RMAP_DENY;
    1708             :                 }
    1709             :         }
    1710             : 
    1711             :         /* Route map apply. */
    1712             :         if (rmap) {
    1713           4 :                 memset(&rmap_path, 0, sizeof(rmap_path));
    1714             :                 /* Duplicate current value to new structure for modification. */
    1715           4 :                 rmap_path.peer = peer;
    1716           4 :                 rmap_path.attr = attr;
    1717           4 :                 rmap_path.extra = &extra;
    1718           4 :                 rmap_path.net = dest;
    1719             : 
    1720           4 :                 extra.num_labels = num_labels;
    1721           4 :                 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
    1722           0 :                         memcpy(extra.label, label,
    1723             :                                 num_labels * sizeof(mpls_label_t));
    1724             : 
    1725           4 :                 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
    1726             : 
    1727             :                 /* Apply BGP route map to the attribute. */
    1728           4 :                 ret = route_map_apply(rmap, p, &rmap_path);
    1729             : 
    1730           4 :                 peer->rmap_type = 0;
    1731             : 
    1732           4 :                 if (ret == RMAP_DENYMATCH)
    1733             :                         return RMAP_DENY;
    1734             :         }
    1735             :         return RMAP_PERMIT;
    1736             : }
    1737             : 
    1738           0 : static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
    1739             :                                struct attr *attr, afi_t afi, safi_t safi,
    1740             :                                const char *rmap_name)
    1741             : {
    1742           0 :         struct bgp_path_info rmap_path;
    1743           0 :         route_map_result_t ret;
    1744           0 :         struct route_map *rmap = NULL;
    1745           0 :         uint8_t rmap_type;
    1746             : 
    1747             :         /*
    1748             :          * So if we get to this point and have no rmap_name
    1749             :          * we want to just show the output as it currently
    1750             :          * exists.
    1751             :          */
    1752           0 :         if (!rmap_name)
    1753             :                 return RMAP_PERMIT;
    1754             : 
    1755             :         /* Apply default weight value. */
    1756           0 :         if (peer->weight[afi][safi])
    1757           0 :                 attr->weight = peer->weight[afi][safi];
    1758             : 
    1759           0 :         rmap = route_map_lookup_by_name(rmap_name);
    1760             : 
    1761             :         /*
    1762             :          * If we have a route map name and we do not find
    1763             :          * the routemap that means we have an implicit
    1764             :          * deny.
    1765             :          */
    1766           0 :         if (rmap == NULL)
    1767             :                 return RMAP_DENY;
    1768             : 
    1769           0 :         memset(&rmap_path, 0, sizeof(rmap_path));
    1770             :         /* Route map apply. */
    1771             :         /* Duplicate current value to new structure for modification. */
    1772           0 :         rmap_path.peer = peer;
    1773           0 :         rmap_path.attr = attr;
    1774             : 
    1775           0 :         rmap_type = peer->rmap_type;
    1776           0 :         SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
    1777             : 
    1778             :         /* Apply BGP route map to the attribute. */
    1779           0 :         ret = route_map_apply(rmap, p, &rmap_path);
    1780             : 
    1781           0 :         peer->rmap_type = rmap_type;
    1782             : 
    1783           0 :         if (ret == RMAP_DENYMATCH)
    1784             :                 /*
    1785             :                  * caller has multiple error paths with bgp_attr_flush()
    1786             :                  */
    1787             :                 return RMAP_DENY;
    1788             : 
    1789             :         return RMAP_PERMIT;
    1790             : }
    1791             : 
    1792             : /* If this is an EBGP peer with remove-private-AS */
    1793          16 : static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
    1794             :                                        struct peer *peer, struct attr *attr)
    1795             : {
    1796          16 :         if (peer->sort == BGP_PEER_EBGP
    1797          16 :             && (peer_af_flag_check(peer, afi, safi,
    1798             :                                    PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
    1799          16 :                 || peer_af_flag_check(peer, afi, safi,
    1800             :                                       PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
    1801          16 :                 || peer_af_flag_check(peer, afi, safi,
    1802             :                                       PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
    1803          16 :                 || peer_af_flag_check(peer, afi, safi,
    1804             :                                       PEER_FLAG_REMOVE_PRIVATE_AS))) {
    1805             :                 // Take action on the entire aspath
    1806           0 :                 if (peer_af_flag_check(peer, afi, safi,
    1807             :                                        PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
    1808           0 :                     || peer_af_flag_check(peer, afi, safi,
    1809             :                                           PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
    1810           0 :                         if (peer_af_flag_check(
    1811             :                                     peer, afi, safi,
    1812             :                                     PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
    1813           0 :                                 attr->aspath = aspath_replace_private_asns(
    1814             :                                         attr->aspath, bgp->as, peer->as);
    1815             : 
    1816             :                         /*
    1817             :                          * Even if the aspath consists of just private ASNs we
    1818             :                          * need to walk the AS-Path to maintain all instances
    1819             :                          * of the peer's ASN to break possible loops.
    1820             :                          */
    1821             :                         else
    1822           0 :                                 attr->aspath = aspath_remove_private_asns(
    1823             :                                         attr->aspath, peer->as);
    1824             :                 }
    1825             : 
    1826             :                 // 'all' was not specified so the entire aspath must be private
    1827             :                 // ASNs
    1828             :                 // for us to do anything
    1829           0 :                 else if (aspath_private_as_check(attr->aspath)) {
    1830           0 :                         if (peer_af_flag_check(
    1831             :                                     peer, afi, safi,
    1832             :                                     PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
    1833           0 :                                 attr->aspath = aspath_replace_private_asns(
    1834             :                                         attr->aspath, bgp->as, peer->as);
    1835             :                         else
    1836             :                                 /*
    1837             :                                  * Walk the aspath to retain any instances of
    1838             :                                  * the peer_asn
    1839             :                                  */
    1840           0 :                                 attr->aspath = aspath_remove_private_asns(
    1841             :                                         attr->aspath, peer->as);
    1842             :                 }
    1843             :         }
    1844          16 : }
    1845             : 
    1846             : /* If this is an EBGP peer with as-override */
    1847          16 : static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
    1848             :                                  struct peer *peer, struct attr *attr)
    1849             : {
    1850          16 :         struct aspath *aspath;
    1851             : 
    1852          32 :         if (peer->sort == BGP_PEER_EBGP &&
    1853          16 :             peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
    1854           0 :                 if (attr->aspath->refcnt)
    1855           0 :                         aspath = aspath_dup(attr->aspath);
    1856             :                 else
    1857             :                         aspath = attr->aspath;
    1858             : 
    1859           0 :                 attr->aspath = aspath_intern(
    1860             :                         aspath_replace_specific_asn(aspath, peer->as, bgp->as));
    1861             : 
    1862           0 :                 aspath_free(aspath);
    1863             :         }
    1864          16 : }
    1865             : 
    1866           0 : void bgp_attr_add_llgr_community(struct attr *attr)
    1867             : {
    1868           0 :         struct community *old;
    1869           0 :         struct community *new;
    1870           0 :         struct community *merge;
    1871           0 :         struct community *llgr;
    1872             : 
    1873           0 :         old = bgp_attr_get_community(attr);
    1874           0 :         llgr = community_str2com("llgr-stale");
    1875             : 
    1876           0 :         assert(llgr);
    1877             : 
    1878           0 :         if (old) {
    1879           0 :                 merge = community_merge(community_dup(old), llgr);
    1880             : 
    1881           0 :                 if (old->refcnt == 0)
    1882           0 :                         community_free(&old);
    1883             : 
    1884           0 :                 new = community_uniq_sort(merge);
    1885           0 :                 community_free(&merge);
    1886             :         } else {
    1887           0 :                 new = community_dup(llgr);
    1888             :         }
    1889             : 
    1890           0 :         community_free(&llgr);
    1891             : 
    1892           0 :         bgp_attr_set_community(attr, new);
    1893           0 : }
    1894             : 
    1895           0 : void bgp_attr_add_gshut_community(struct attr *attr)
    1896             : {
    1897           0 :         struct community *old;
    1898           0 :         struct community *new;
    1899           0 :         struct community *merge;
    1900           0 :         struct community *gshut;
    1901             : 
    1902           0 :         old = bgp_attr_get_community(attr);
    1903           0 :         gshut = community_str2com("graceful-shutdown");
    1904             : 
    1905           0 :         assert(gshut);
    1906             : 
    1907           0 :         if (old) {
    1908           0 :                 merge = community_merge(community_dup(old), gshut);
    1909             : 
    1910           0 :                 if (old->refcnt == 0)
    1911           0 :                         community_free(&old);
    1912             : 
    1913           0 :                 new = community_uniq_sort(merge);
    1914           0 :                 community_free(&merge);
    1915             :         } else {
    1916           0 :                 new = community_dup(gshut);
    1917             :         }
    1918             : 
    1919           0 :         community_free(&gshut);
    1920           0 :         bgp_attr_set_community(attr, new);
    1921             : 
    1922             :         /* When we add the graceful-shutdown community we must also
    1923             :          * lower the local-preference */
    1924           0 :         attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
    1925           0 :         attr->local_pref = BGP_GSHUT_LOCAL_PREF;
    1926           0 : }
    1927             : 
    1928             : 
    1929             : /* Notify BGP Conditional advertisement scanner process. */
    1930           8 : void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
    1931             : {
    1932           8 :         struct peer *peer = SUBGRP_PEER(subgrp);
    1933           8 :         afi_t afi = SUBGRP_AFI(subgrp);
    1934           8 :         safi_t safi = SUBGRP_SAFI(subgrp);
    1935           8 :         struct bgp_filter *filter = &peer->filter[afi][safi];
    1936             : 
    1937           8 :         if (!ADVERTISE_MAP_NAME(filter))
    1938             :                 return;
    1939             : 
    1940           0 :         if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
    1941             :                 return;
    1942             : 
    1943           0 :         peer->advmap_table_change = true;
    1944             : }
    1945             : 
    1946             : 
    1947          16 : void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
    1948             : {
    1949          16 :         if (family == AF_INET) {
    1950          16 :                 attr->nexthop.s_addr = INADDR_ANY;
    1951          16 :                 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
    1952             :         }
    1953          16 :         if (family == AF_INET6)
    1954           0 :                 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
    1955          16 :         if (family == AF_EVPN)
    1956           0 :                 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
    1957          16 : }
    1958             : 
    1959          16 : bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
    1960             :                              struct update_subgroup *subgrp,
    1961             :                              const struct prefix *p, struct attr *attr,
    1962             :                              struct attr *post_attr)
    1963             : {
    1964          16 :         struct bgp_filter *filter;
    1965          16 :         struct peer *from;
    1966          16 :         struct peer *peer;
    1967          16 :         struct peer *onlypeer;
    1968          16 :         struct bgp *bgp;
    1969          16 :         struct attr *piattr;
    1970          16 :         route_map_result_t ret;
    1971          16 :         int transparent;
    1972          16 :         int reflect;
    1973          16 :         afi_t afi;
    1974          16 :         safi_t safi;
    1975          16 :         int samepeer_safe = 0; /* for synthetic mplsvpns routes */
    1976          16 :         bool nh_reset = false;
    1977          16 :         uint64_t cum_bw;
    1978             : 
    1979          16 :         if (DISABLE_BGP_ANNOUNCE)
    1980             :                 return false;
    1981             : 
    1982          16 :         afi = SUBGRP_AFI(subgrp);
    1983          16 :         safi = SUBGRP_SAFI(subgrp);
    1984          16 :         peer = SUBGRP_PEER(subgrp);
    1985          16 :         onlypeer = NULL;
    1986          16 :         if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
    1987           0 :                 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
    1988             : 
    1989          16 :         from = pi->peer;
    1990          16 :         filter = &peer->filter[afi][safi];
    1991          16 :         bgp = SUBGRP_INST(subgrp);
    1992          16 :         piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
    1993          16 :                                                : pi->attr;
    1994             : 
    1995          16 :         if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
    1996           0 :             peer->pmax_out[afi][safi] != 0 &&
    1997           0 :             subgrp->pscount >= peer->pmax_out[afi][safi]) {
    1998           0 :                 if (BGP_DEBUG(update, UPDATE_OUT) ||
    1999             :                     BGP_DEBUG(update, UPDATE_PREFIX)) {
    2000           0 :                         zlog_debug("%s reached maximum prefix to be send (%u)",
    2001             :                                    peer->host, peer->pmax_out[afi][safi]);
    2002             :                 }
    2003           0 :                 return false;
    2004             :         }
    2005             : 
    2006             : #ifdef ENABLE_BGP_VNC
    2007          16 :         if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
    2008           0 :             && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
    2009           0 :                 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
    2010             : 
    2011             :                 /*
    2012             :                  * direct and direct_ext type routes originate internally even
    2013             :                  * though they can have peer pointers that reference other
    2014             :                  * systems
    2015             :                  */
    2016           0 :                 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
    2017             :                            __func__, p);
    2018           0 :                 samepeer_safe = 1;
    2019             :         }
    2020             : #endif
    2021             : 
    2022          16 :         if (((afi == AFI_IP) || (afi == AFI_IP6))
    2023          16 :             && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
    2024             :             && (pi->type == ZEBRA_ROUTE_BGP)
    2025          16 :             && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
    2026             : 
    2027             :                 /* Applies to routes leaked vpn->vrf and vrf->vpn */
    2028             : 
    2029          16 :                 samepeer_safe = 1;
    2030             :         }
    2031             : 
    2032             :         /* With addpath we may be asked to TX all kinds of paths so make sure
    2033             :          * pi is valid */
    2034          16 :         if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
    2035             :             || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
    2036          16 :             || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
    2037             :                 return false;
    2038             :         }
    2039             : 
    2040             :         /* If this is not the bestpath then check to see if there is an enabled
    2041             :          * addpath
    2042             :          * feature that requires us to advertise it */
    2043          16 :         if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
    2044           0 :                 if (!bgp_addpath_capable(pi, peer, afi, safi))
    2045             :                         return false;
    2046             : 
    2047             :         /* Aggregate-address suppress check. */
    2048          16 :         if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
    2049             :                 return false;
    2050             : 
    2051             :         /*
    2052             :          * If we are doing VRF 2 VRF leaking via the import
    2053             :          * statement, we want to prevent the route going
    2054             :          * off box as that the RT and RD created are localy
    2055             :          * significant and globaly useless.
    2056             :          */
    2057          16 :         if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
    2058           0 :             && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
    2059             :                 return false;
    2060             : 
    2061             :         /* If it's labeled safi, make sure the route has a valid label. */
    2062          16 :         if (safi == SAFI_LABELED_UNICAST) {
    2063           0 :                 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
    2064           0 :                 if (!bgp_is_valid_label(&label)) {
    2065           0 :                         if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
    2066           0 :                                 zlog_debug("u%" PRIu64 ":s%" PRIu64
    2067             :                                            " %pFX is filtered - no label (%p)",
    2068             :                                            subgrp->update_group->id, subgrp->id,
    2069             :                                            p, &label);
    2070           0 :                         return false;
    2071             :                 }
    2072             :         }
    2073             : 
    2074             :         /* Do not send back route to sender. */
    2075          16 :         if (onlypeer && from == onlypeer) {
    2076             :                 return false;
    2077             :         }
    2078             : 
    2079             :         /* Do not send the default route in the BGP table if the neighbor is
    2080             :          * configured for default-originate */
    2081          16 :         if (CHECK_FLAG(peer->af_flags[afi][safi],
    2082             :                        PEER_FLAG_DEFAULT_ORIGINATE)) {
    2083           0 :                 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
    2084             :                         return false;
    2085           0 :                 else if (p->family == AF_INET6 && p->prefixlen == 0)
    2086             :                         return false;
    2087             :         }
    2088             : 
    2089             :         /* Transparency check. */
    2090          16 :         if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
    2091           0 :             && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
    2092             :                 transparent = 1;
    2093             :         else
    2094          16 :                 transparent = 0;
    2095             : 
    2096             :         /* If community is not disabled check the no-export and local. */
    2097          16 :         if (!transparent && bgp_community_filter(peer, piattr)) {
    2098           0 :                 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
    2099           0 :                         zlog_debug("%s: community filter check fail for %pFX",
    2100             :                                    __func__, p);
    2101           0 :                 return false;
    2102             :         }
    2103             : 
    2104             :         /* If the attribute has originator-id and it is same as remote
    2105             :            peer's id. */
    2106          16 :         if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
    2107           0 :             && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
    2108           0 :                 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
    2109           0 :                         zlog_debug(
    2110             :                                 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
    2111             :                                 onlypeer, p);
    2112           0 :                 return false;
    2113             :         }
    2114             : 
    2115             :         /* ORF prefix-list filter check */
    2116          16 :         if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
    2117           0 :             && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
    2118           0 :                 || CHECK_FLAG(peer->af_cap[afi][safi],
    2119             :                               PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
    2120           0 :                 if (peer->orf_plist[afi][safi]) {
    2121           0 :                         if (prefix_list_apply(peer->orf_plist[afi][safi], p)
    2122             :                             == PREFIX_DENY) {
    2123           0 :                                 if (bgp_debug_update(NULL, p,
    2124             :                                                      subgrp->update_group, 0))
    2125           0 :                                         zlog_debug(
    2126             :                                                 "%pBP [Update:SEND] %pFX is filtered via ORF",
    2127             :                                                 peer, p);
    2128           0 :                                 return false;
    2129             :                         }
    2130             :                 }
    2131             : 
    2132             :         /* Output filter check. */
    2133          16 :         if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
    2134           0 :                 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
    2135           0 :                         zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer,
    2136             :                                    p);
    2137           0 :                 return false;
    2138             :         }
    2139             : 
    2140             :         /* AS path loop check. */
    2141          16 :         if (peer->as_path_loop_detection &&
    2142           0 :             aspath_loop_check(piattr->aspath, peer->as)) {
    2143           0 :                 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
    2144           0 :                         zlog_debug(
    2145             :                                 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
    2146             :                                 peer, peer->as);
    2147           0 :                 return false;
    2148             :         }
    2149             : 
    2150             :         /* If we're a CONFED we need to loop check the CONFED ID too */
    2151          16 :         if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
    2152           0 :                 if (aspath_loop_check_confed(piattr->aspath, bgp->confed_id)) {
    2153           0 :                         if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
    2154           0 :                                 zlog_debug(
    2155             :                                         "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
    2156             :                                         peer, bgp->confed_id);
    2157           0 :                         return false;
    2158             :                 }
    2159             :         }
    2160             : 
    2161             :         /* Route-Reflect check. */
    2162          16 :         if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
    2163             :                 reflect = 1;
    2164             :         else
    2165          16 :                 reflect = 0;
    2166             : 
    2167             :         /* IBGP reflection check. */
    2168          16 :         if (reflect && !samepeer_safe) {
    2169             :                 /* A route from a Client peer. */
    2170           0 :                 if (CHECK_FLAG(from->af_flags[afi][safi],
    2171             :                                PEER_FLAG_REFLECTOR_CLIENT)) {
    2172             :                         /* Reflect to all the Non-Client peers and also to the
    2173             :                            Client peers other than the originator.  Originator
    2174             :                            check
    2175             :                            is already done.  So there is noting to do. */
    2176             :                         /* no bgp client-to-client reflection check. */
    2177           0 :                         if (CHECK_FLAG(bgp->flags,
    2178             :                                        BGP_FLAG_NO_CLIENT_TO_CLIENT))
    2179           0 :                                 if (CHECK_FLAG(peer->af_flags[afi][safi],
    2180             :                                                PEER_FLAG_REFLECTOR_CLIENT))
    2181             :                                         return false;
    2182             :                 } else {
    2183             :                         /* A route from a Non-client peer. Reflect to all other
    2184             :                            clients. */
    2185           0 :                         if (!CHECK_FLAG(peer->af_flags[afi][safi],
    2186             :                                         PEER_FLAG_REFLECTOR_CLIENT))
    2187             :                                 return false;
    2188             :                 }
    2189             :         }
    2190             : 
    2191             :         /* For modify attribute, copy it to temporary structure.
    2192             :          * post_attr comes from BGP conditional advertisements, where
    2193             :          * attributes are already processed by advertise-map route-map,
    2194             :          * and this needs to be saved instead of overwriting from the
    2195             :          * path attributes.
    2196             :          */
    2197          16 :         if (post_attr)
    2198           0 :                 *attr = *post_attr;
    2199             :         else
    2200          16 :                 *attr = *piattr;
    2201             : 
    2202             :         /* If local-preference is not set. */
    2203          16 :         if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
    2204           0 :             && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
    2205           0 :                 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
    2206           0 :                 attr->local_pref = bgp->default_local_pref;
    2207             :         }
    2208             : 
    2209             :         /* If originator-id is not set and the route is to be reflected,
    2210             :            set the originator id */
    2211          16 :         if (reflect
    2212           0 :             && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
    2213           0 :                 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
    2214           0 :                 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
    2215             :         }
    2216             : 
    2217             :         /* Remove MED if its an EBGP peer - will get overwritten by route-maps
    2218             :          */
    2219          16 :         if (peer->sort == BGP_PEER_EBGP
    2220          16 :             && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
    2221          12 :                 if (from != bgp->peer_self && !transparent
    2222           8 :                     && !CHECK_FLAG(peer->af_flags[afi][safi],
    2223             :                                    PEER_FLAG_MED_UNCHANGED))
    2224           8 :                         attr->flag &=
    2225             :                                 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
    2226             :         }
    2227             : 
    2228             :         /* Since the nexthop attribute can vary per peer, it is not explicitly
    2229             :          * set
    2230             :          * in announce check, only certain flags and length (or number of
    2231             :          * nexthops
    2232             :          * -- for IPv6/MP_REACH) are set here in order to guide the update
    2233             :          * formation
    2234             :          * code in setting the nexthop(s) on a per peer basis in
    2235             :          * reformat_peer().
    2236             :          * Typically, the source nexthop in the attribute is preserved but in
    2237             :          * the
    2238             :          * scenarios where we know it will always be overwritten, we reset the
    2239             :          * nexthop to "0" in an attempt to achieve better Update packing. An
    2240             :          * example of this is when a prefix from each of 2 IBGP peers needs to
    2241             :          * be
    2242             :          * announced to an EBGP peer (and they have the same attributes barring
    2243             :          * their nexthop).
    2244             :          */
    2245          16 :         if (reflect)
    2246           0 :                 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
    2247             : 
    2248             : #define NEXTHOP_IS_V6                                                          \
    2249             :         ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN                          \
    2250             :           && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)))        \
    2251             :          || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN)                     \
    2252             :              && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
    2253             : 
    2254             :         /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
    2255             :          * if
    2256             :          * the peer (group) is configured to receive link-local nexthop
    2257             :          * unchanged
    2258             :          * and it is available in the prefix OR we're not reflecting the route,
    2259             :          * link-local nexthop address is valid and
    2260             :          * the peer (group) to whom we're going to announce is on a shared
    2261             :          * network
    2262             :          * and this is either a self-originated route or the peer is EBGP.
    2263             :          * By checking if nexthop LL address is valid we are sure that
    2264             :          * we do not announce LL address as `::`.
    2265             :          */
    2266          16 :         if (NEXTHOP_IS_V6) {
    2267           0 :                 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
    2268           0 :                 if ((CHECK_FLAG(peer->af_flags[afi][safi],
    2269             :                                 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
    2270           0 :                      && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
    2271           0 :                     || (!reflect && !transparent
    2272           0 :                         && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
    2273           0 :                         && peer->shared_network
    2274           0 :                         && (from == bgp->peer_self
    2275           0 :                             || peer->sort == BGP_PEER_EBGP))) {
    2276           0 :                         if (safi == SAFI_MPLS_VPN)
    2277           0 :                                 attr->mp_nexthop_len =
    2278             :                                         BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL;
    2279             :                         else
    2280           0 :                                 attr->mp_nexthop_len =
    2281             :                                         BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
    2282             :                 }
    2283             : 
    2284             :                 /* Clear off link-local nexthop in source, whenever it is not
    2285             :                  * needed to
    2286             :                  * ensure more prefixes share the same attribute for
    2287             :                  * announcement.
    2288             :                  */
    2289           0 :                 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
    2290             :                                  PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
    2291           0 :                         memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
    2292             :         }
    2293             : 
    2294          32 :         if (bgp_check_role_applicability(afi, safi) &&
    2295          16 :             bgp_otc_egress(peer, attr))
    2296             :                 return false;
    2297             : 
    2298          16 :         bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
    2299          16 :         bgp_peer_as_override(bgp, afi, safi, peer, attr);
    2300             : 
    2301          16 :         if (filter->advmap.update_type == UPDATE_TYPE_WITHDRAW &&
    2302          16 :             filter->advmap.aname &&
    2303           0 :             route_map_lookup_by_name(filter->advmap.aname)) {
    2304           0 :                 struct bgp_path_info rmap_path = {0};
    2305           0 :                 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
    2306           0 :                 struct attr dummy_attr = *attr;
    2307             : 
    2308             :                 /* Fill temp path_info */
    2309           0 :                 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
    2310             :                                     pi, peer, &dummy_attr);
    2311             : 
    2312           0 :                 struct route_map *amap =
    2313           0 :                         route_map_lookup_by_name(filter->advmap.aname);
    2314             : 
    2315           0 :                 ret = route_map_apply(amap, p, &rmap_path);
    2316             : 
    2317           0 :                 bgp_attr_flush(&dummy_attr);
    2318             : 
    2319             :                 /*
    2320             :                  * The conditional advertisement mode is Withdraw and this
    2321             :                  * prefix is a conditional prefix. Don't advertise it
    2322             :                  */
    2323           0 :                 if (ret == RMAP_PERMITMATCH)
    2324           0 :                         return false;
    2325             :         }
    2326             : 
    2327             :         /* Route map & unsuppress-map apply. */
    2328          16 :         if (!post_attr &&
    2329          16 :             (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
    2330           0 :                 struct bgp_path_info rmap_path = {0};
    2331           0 :                 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
    2332           0 :                 struct attr dummy_attr = {0};
    2333             : 
    2334             :                 /* Fill temp path_info */
    2335           0 :                 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
    2336             :                                     pi, peer, attr);
    2337             : 
    2338             :                 /* don't confuse inbound and outbound setting */
    2339           0 :                 RESET_FLAG(attr->rmap_change_flags);
    2340             : 
    2341             :                 /*
    2342             :                  * The route reflector is not allowed to modify the attributes
    2343             :                  * of the reflected IBGP routes unless explicitly allowed.
    2344             :                  */
    2345           0 :                 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
    2346           0 :                     && !CHECK_FLAG(bgp->flags,
    2347             :                                    BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
    2348           0 :                         dummy_attr = *attr;
    2349           0 :                         rmap_path.attr = &dummy_attr;
    2350             :                 }
    2351             : 
    2352           0 :                 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
    2353             : 
    2354           0 :                 if (bgp_path_suppressed(pi))
    2355           0 :                         ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
    2356             :                                               &rmap_path);
    2357             :                 else
    2358           0 :                         ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
    2359             :                                               &rmap_path);
    2360             : 
    2361           0 :                 bgp_attr_flush(&dummy_attr);
    2362           0 :                 peer->rmap_type = 0;
    2363             : 
    2364           0 :                 if (ret == RMAP_DENYMATCH) {
    2365           0 :                         if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
    2366           0 :                                 zlog_debug(
    2367             :                                         "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
    2368             :                                         peer, p, ROUTE_MAP_OUT_NAME(filter));
    2369           0 :                         bgp_attr_flush(rmap_path.attr);
    2370           0 :                         return false;
    2371             :                 }
    2372             :         }
    2373             : 
    2374             :         /* RFC 8212 to prevent route leaks.
    2375             :          * This specification intends to improve this situation by requiring the
    2376             :          * explicit configuration of both BGP Import and Export Policies for any
    2377             :          * External BGP (EBGP) session such as customers, peers, or
    2378             :          * confederation boundaries for all enabled address families. Through
    2379             :          * codification of the aforementioned requirement, operators will
    2380             :          * benefit from consistent behavior across different BGP
    2381             :          * implementations.
    2382             :          */
    2383          16 :         if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
    2384           0 :                 if (!bgp_outbound_policy_exists(peer, filter)) {
    2385           0 :                         if (monotime_since(&bgp->ebgprequirespolicywarning,
    2386           0 :                                            NULL) > FIFTEENMINUTE2USEC ||
    2387           0 :                             bgp->ebgprequirespolicywarning.tv_sec == 0) {
    2388           0 :                                 zlog_warn(
    2389             :                                         "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
    2390           0 :                                 monotime(&bgp->ebgprequirespolicywarning);
    2391             :                         }
    2392           0 :                         return false;
    2393             :                 }
    2394             : 
    2395             :         /* draft-ietf-idr-deprecate-as-set-confed-set
    2396             :          * Filter routes having AS_SET or AS_CONFED_SET in the path.
    2397             :          * Eventually, This document (if approved) updates RFC 4271
    2398             :          * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
    2399             :          * and obsoletes RFC 6472.
    2400             :          */
    2401          16 :         if (peer->bgp->reject_as_sets)
    2402           0 :                 if (aspath_check_as_sets(attr->aspath))
    2403             :                         return false;
    2404             : 
    2405             :         /* If neighbor soo is configured, then check if the route has
    2406             :          * SoO extended community and validate against the configured
    2407             :          * one. If they match, do not announce, to prevent routing
    2408             :          * loops.
    2409             :          */
    2410          16 :         if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) &&
    2411           0 :             peer->soo[afi][safi]) {
    2412           0 :                 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
    2413           0 :                 struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
    2414             : 
    2415           0 :                 if ((ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS,
    2416           0 :                                        ECOMMUNITY_SITE_ORIGIN) ||
    2417           0 :                      ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS4,
    2418           0 :                                        ECOMMUNITY_SITE_ORIGIN) ||
    2419           0 :                      ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_IP,
    2420           0 :                                        ECOMMUNITY_SITE_ORIGIN)) &&
    2421           0 :                     ecommunity_include(ecomm, ecomm_soo)) {
    2422           0 :                         if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
    2423           0 :                                 zlog_debug(
    2424             :                                         "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
    2425             :                                         peer, p, ecommunity_str(ecomm_soo));
    2426           0 :                         return false;
    2427             :                 }
    2428             :         }
    2429             : 
    2430             :         /* Codification of AS 0 Processing */
    2431          16 :         if (aspath_check_as_zero(attr->aspath))
    2432             :                 return false;
    2433             : 
    2434          16 :         if (bgp_in_graceful_shutdown(bgp)) {
    2435           0 :                 if (peer->sort == BGP_PEER_IBGP
    2436           0 :                     || peer->sort == BGP_PEER_CONFED) {
    2437           0 :                         attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
    2438           0 :                         attr->local_pref = BGP_GSHUT_LOCAL_PREF;
    2439             :                 } else {
    2440           0 :                         bgp_attr_add_gshut_community(attr);
    2441             :                 }
    2442             :         }
    2443             : 
    2444             :         /* A BGP speaker that has advertised the "Long-lived Graceful Restart
    2445             :          * Capability" to a neighbor MUST perform the following upon receiving
    2446             :          * a route from that neighbor with the "LLGR_STALE" community, or upon
    2447             :          * attaching the "LLGR_STALE" community itself per Section 4.2:
    2448             :          *
    2449             :          * The route SHOULD NOT be advertised to any neighbor from which the
    2450             :          * Long-lived Graceful Restart Capability has not been received.
    2451             :          */
    2452          16 :         if (bgp_attr_get_community(attr) &&
    2453           0 :             community_include(bgp_attr_get_community(attr),
    2454             :                               COMMUNITY_LLGR_STALE) &&
    2455           0 :             !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
    2456             :             !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
    2457             :                 return false;
    2458             : 
    2459             :         /* After route-map has been applied, we check to see if the nexthop to
    2460             :          * be carried in the attribute (that is used for the announcement) can
    2461             :          * be cleared off or not. We do this in all cases where we would be
    2462             :          * setting the nexthop to "ourselves". For IPv6, we only need to
    2463             :          * consider
    2464             :          * the global nexthop here; the link-local nexthop would have been
    2465             :          * cleared
    2466             :          * already, and if not, it is required by the update formation code.
    2467             :          * Also see earlier comments in this function.
    2468             :          */
    2469             :         /*
    2470             :          * If route-map has performed some operation on the nexthop or the peer
    2471             :          * configuration says to pass it unchanged, we cannot reset the nexthop
    2472             :          * here, so only attempt to do it if these aren't true. Note that the
    2473             :          * route-map handler itself might have cleared the nexthop, if for
    2474             :          * example,
    2475             :          * it is configured as 'peer-address'.
    2476             :          */
    2477          32 :         if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
    2478             :                                    piattr->rmap_change_flags)
    2479          16 :             && !transparent
    2480          16 :             && !CHECK_FLAG(peer->af_flags[afi][safi],
    2481             :                            PEER_FLAG_NEXTHOP_UNCHANGED)) {
    2482             :                 /* We can reset the nexthop, if setting (or forcing) it to
    2483             :                  * 'self' */
    2484          16 :                 if (CHECK_FLAG(peer->af_flags[afi][safi],
    2485             :                                PEER_FLAG_NEXTHOP_SELF)
    2486          16 :                     || CHECK_FLAG(peer->af_flags[afi][safi],
    2487             :                                   PEER_FLAG_FORCE_NEXTHOP_SELF)) {
    2488           0 :                         if (!reflect
    2489           0 :                             || CHECK_FLAG(peer->af_flags[afi][safi],
    2490             :                                           PEER_FLAG_FORCE_NEXTHOP_SELF)) {
    2491           0 :                                 subgroup_announce_reset_nhop(
    2492           0 :                                         (peer_cap_enhe(peer, afi, safi)
    2493             :                                                  ? AF_INET6
    2494           0 :                                                  : p->family),
    2495             :                                         attr);
    2496           0 :                                 nh_reset = true;
    2497             :                         }
    2498          16 :                 } else if (peer->sort == BGP_PEER_EBGP) {
    2499             :                         /* Can also reset the nexthop if announcing to EBGP, but
    2500             :                          * only if
    2501             :                          * no peer in the subgroup is on a shared subnet.
    2502             :                          * Note: 3rd party nexthop currently implemented for
    2503             :                          * IPv4 only.
    2504             :                          */
    2505          32 :                         if ((p->family == AF_INET) &&
    2506          16 :                                 (!bgp_subgrp_multiaccess_check_v4(
    2507             :                                         piattr->nexthop,
    2508             :                                         subgrp, from))) {
    2509          16 :                                 subgroup_announce_reset_nhop(
    2510          16 :                                         (peer_cap_enhe(peer, afi, safi)
    2511             :                                                  ? AF_INET6
    2512          16 :                                                  : p->family),
    2513             :                                                 attr);
    2514          16 :                                 nh_reset = true;
    2515             :                         }
    2516             : 
    2517          16 :                         if ((p->family == AF_INET6) &&
    2518           0 :                                 (!bgp_subgrp_multiaccess_check_v6(
    2519             :                                         piattr->mp_nexthop_global,
    2520             :                                         subgrp, from))) {
    2521           0 :                                 subgroup_announce_reset_nhop(
    2522           0 :                                         (peer_cap_enhe(peer, afi, safi)
    2523             :                                                 ? AF_INET6
    2524           0 :                                                 : p->family),
    2525             :                                                 attr);
    2526           0 :                                 nh_reset = true;
    2527             :                         }
    2528             : 
    2529             : 
    2530             : 
    2531           0 :                 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
    2532             :                         /*
    2533             :                          * This flag is used for leaked vpn-vrf routes
    2534             :                          */
    2535           0 :                         int family = p->family;
    2536             : 
    2537           0 :                         if (peer_cap_enhe(peer, afi, safi))
    2538           0 :                                 family = AF_INET6;
    2539             : 
    2540           0 :                         if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
    2541           0 :                                 zlog_debug(
    2542             :                                         "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
    2543             :                                         __func__, p, family2str(family));
    2544           0 :                         subgroup_announce_reset_nhop(family, attr);
    2545           0 :                         nh_reset = true;
    2546             :                 }
    2547             :         }
    2548             : 
    2549             :         /* If IPv6/MP and nexthop does not have any override and happens
    2550             :          * to
    2551             :          * be a link-local address, reset it so that we don't pass along
    2552             :          * the
    2553             :          * source's link-local IPv6 address to recipients who may not be
    2554             :          * on
    2555             :          * the same interface.
    2556             :          */
    2557          16 :         if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
    2558           0 :                 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
    2559           0 :                         subgroup_announce_reset_nhop(AF_INET6, attr);
    2560           0 :                                 nh_reset = true;
    2561             :                         }
    2562             :         }
    2563             : 
    2564             :         /* If this is an iBGP, send Origin Validation State (OVS)
    2565             :          * extended community (rfc8097).
    2566             :          */
    2567          16 :         if (peer->sort == BGP_PEER_IBGP) {
    2568           0 :                 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
    2569             : 
    2570           0 :                 rpki_state = hook_call(bgp_rpki_prefix_status, peer, attr, p);
    2571             : 
    2572           0 :                 if (rpki_state != RPKI_NOT_BEING_USED)
    2573           0 :                         bgp_attr_set_ecommunity(
    2574             :                                 attr, ecommunity_add_origin_validation_state(
    2575             :                                               rpki_state,
    2576             :                                               bgp_attr_get_ecommunity(attr)));
    2577             :         }
    2578             : 
    2579             :         /*
    2580             :          * When the next hop is set to ourselves, if all multipaths have
    2581             :          * link-bandwidth announce the cumulative bandwidth as that makes
    2582             :          * the most sense. However, don't modify if the link-bandwidth has
    2583             :          * been explicitly set by user policy.
    2584             :          */
    2585          32 :         if (nh_reset &&
    2586          16 :             bgp_path_info_mpath_chkwtd(bgp, pi) &&
    2587           0 :             (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
    2588           0 :             !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
    2589           0 :                 bgp_attr_set_ecommunity(
    2590             :                         attr,
    2591             :                         ecommunity_replace_linkbw(
    2592             :                                 bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
    2593           0 :                                 CHECK_FLAG(
    2594             :                                         peer->flags,
    2595             :                                         PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
    2596             : 
    2597             :         return true;
    2598             : }
    2599             : 
    2600           0 : static void bgp_route_select_timer_expire(struct thread *thread)
    2601             : {
    2602           0 :         struct afi_safi_info *info;
    2603           0 :         afi_t afi;
    2604           0 :         safi_t safi;
    2605           0 :         struct bgp *bgp;
    2606             : 
    2607           0 :         info = THREAD_ARG(thread);
    2608           0 :         afi = info->afi;
    2609           0 :         safi = info->safi;
    2610           0 :         bgp = info->bgp;
    2611             : 
    2612           0 :         bgp->gr_info[afi][safi].t_route_select = NULL;
    2613           0 :         XFREE(MTYPE_TMP, info);
    2614             : 
    2615             :         /* Best path selection */
    2616           0 :         bgp_best_path_select_defer(bgp, afi, safi);
    2617           0 : }
    2618             : 
    2619          20 : void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
    2620             :                         struct bgp_maxpaths_cfg *mpath_cfg,
    2621             :                         struct bgp_path_info_pair *result, afi_t afi,
    2622             :                         safi_t safi)
    2623             : {
    2624          20 :         struct bgp_path_info *new_select;
    2625          20 :         struct bgp_path_info *old_select;
    2626          20 :         struct bgp_path_info *pi;
    2627          20 :         struct bgp_path_info *pi1;
    2628          20 :         struct bgp_path_info *pi2;
    2629          20 :         struct bgp_path_info *nextpi = NULL;
    2630          20 :         int paths_eq, do_mpath, debug;
    2631          20 :         struct list mp_list;
    2632          20 :         char pfx_buf[PREFIX2STR_BUFFER];
    2633          20 :         char path_buf[PATH_ADDPATH_STR_BUFFER];
    2634             : 
    2635          20 :         bgp_mp_list_init(&mp_list);
    2636          40 :         do_mpath =
    2637          20 :                 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
    2638             : 
    2639          20 :         debug = bgp_debug_bestpath(dest);
    2640             : 
    2641          20 :         if (debug)
    2642           0 :                 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
    2643             : 
    2644          20 :         dest->reason = bgp_path_selection_none;
    2645             :         /* bgp deterministic-med */
    2646          20 :         new_select = NULL;
    2647          20 :         if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
    2648             : 
    2649             :                 /* Clear BGP_PATH_DMED_SELECTED for all paths */
    2650           0 :                 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
    2651           0 :                      pi1 = pi1->next)
    2652           0 :                         bgp_path_info_unset_flag(dest, pi1,
    2653             :                                                  BGP_PATH_DMED_SELECTED);
    2654             : 
    2655           0 :                 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
    2656           0 :                      pi1 = pi1->next) {
    2657           0 :                         if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
    2658           0 :                                 continue;
    2659           0 :                         if (BGP_PATH_HOLDDOWN(pi1))
    2660           0 :                                 continue;
    2661           0 :                         if (pi1->peer != bgp->peer_self)
    2662           0 :                                 if (!peer_established(pi1->peer))
    2663           0 :                                         continue;
    2664             : 
    2665           0 :                         new_select = pi1;
    2666           0 :                         if (pi1->next) {
    2667           0 :                                 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
    2668           0 :                                         if (CHECK_FLAG(pi2->flags,
    2669             :                                                        BGP_PATH_DMED_CHECK))
    2670           0 :                                                 continue;
    2671           0 :                                         if (BGP_PATH_HOLDDOWN(pi2))
    2672           0 :                                                 continue;
    2673           0 :                                         if (pi2->peer != bgp->peer_self
    2674           0 :                                             && !CHECK_FLAG(
    2675             :                                                     pi2->peer->sflags,
    2676             :                                                     PEER_STATUS_NSF_WAIT))
    2677           0 :                                                 if (pi2->peer->status
    2678             :                                                     != Established)
    2679           0 :                                                         continue;
    2680             : 
    2681           0 :                                         if (!aspath_cmp_left(pi1->attr->aspath,
    2682           0 :                                                              pi2->attr->aspath)
    2683           0 :                                             && !aspath_cmp_left_confed(
    2684           0 :                                                        pi1->attr->aspath,
    2685           0 :                                                        pi2->attr->aspath))
    2686           0 :                                                 continue;
    2687             : 
    2688           0 :                                         if (bgp_path_info_cmp(
    2689             :                                                     bgp, pi2, new_select,
    2690             :                                                     &paths_eq, mpath_cfg, debug,
    2691             :                                                     pfx_buf, afi, safi,
    2692             :                                                     &dest->reason)) {
    2693           0 :                                                 bgp_path_info_unset_flag(
    2694             :                                                         dest, new_select,
    2695             :                                                         BGP_PATH_DMED_SELECTED);
    2696           0 :                                                 new_select = pi2;
    2697             :                                         }
    2698             : 
    2699           0 :                                         bgp_path_info_set_flag(
    2700             :                                                 dest, pi2, BGP_PATH_DMED_CHECK);
    2701             :                                 }
    2702             :                         }
    2703           0 :                         bgp_path_info_set_flag(dest, new_select,
    2704             :                                                BGP_PATH_DMED_CHECK);
    2705           0 :                         bgp_path_info_set_flag(dest, new_select,
    2706             :                                                BGP_PATH_DMED_SELECTED);
    2707             : 
    2708           0 :                         if (debug) {
    2709           0 :                                 bgp_path_info_path_with_addpath_rx_str(
    2710             :                                         new_select, path_buf, sizeof(path_buf));
    2711           0 :                                 zlog_debug(
    2712             :                                         "%pBD(%s): %s is the bestpath from AS %u",
    2713             :                                         dest, bgp->name_pretty, path_buf,
    2714             :                                         aspath_get_first_as(
    2715             :                                                 new_select->attr->aspath));
    2716             :                         }
    2717             :                 }
    2718             :         }
    2719             : 
    2720             :         /* Check old selected route and new selected route. */
    2721          20 :         old_select = NULL;
    2722          20 :         new_select = NULL;
    2723          20 :         for (pi = bgp_dest_get_bgp_path_info(dest);
    2724          43 :              (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
    2725          23 :                 enum bgp_path_selection_reason reason;
    2726             : 
    2727          23 :                 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
    2728           6 :                         old_select = pi;
    2729             : 
    2730          23 :                 if (BGP_PATH_HOLDDOWN(pi)) {
    2731             :                         /* reap REMOVED routes, if needs be
    2732             :                          * selected route must stay for a while longer though
    2733             :                          */
    2734           9 :                         if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
    2735           9 :                             && (pi != old_select))
    2736           3 :                                 bgp_path_info_reap(dest, pi);
    2737             : 
    2738           9 :                         if (debug)
    2739           0 :                                 zlog_debug("%s: pi %p in holddown", __func__,
    2740             :                                            pi);
    2741             : 
    2742           9 :                         continue;
    2743             :                 }
    2744             : 
    2745          14 :                 if (pi->peer && pi->peer != bgp->peer_self
    2746           8 :                     && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
    2747           8 :                         if (!peer_established(pi->peer)) {
    2748             : 
    2749           0 :                                 if (debug)
    2750           0 :                                         zlog_debug(
    2751             :                                                 "%s: pi %p non self peer %s not estab state",
    2752             :                                                 __func__, pi, pi->peer->host);
    2753             : 
    2754           0 :                                 continue;
    2755             :                         }
    2756             : 
    2757          14 :                 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
    2758           0 :                     && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
    2759           0 :                         bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
    2760           0 :                         if (debug)
    2761           0 :                                 zlog_debug("%s: pi %p dmed", __func__, pi);
    2762           0 :                         continue;
    2763             :                 }
    2764             : 
    2765          14 :                 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
    2766             : 
    2767          14 :                 reason = dest->reason;
    2768          14 :                 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
    2769             :                                       debug, pfx_buf, afi, safi,
    2770             :                                       &dest->reason)) {
    2771          14 :                         if (new_select == NULL &&
    2772          14 :                             reason != bgp_path_selection_none)
    2773           0 :                                 dest->reason = reason;
    2774             :                         new_select = pi;
    2775             :                 }
    2776             :         }
    2777             : 
    2778             :         /* Now that we know which path is the bestpath see if any of the other
    2779             :          * paths
    2780             :          * qualify as multipaths
    2781             :          */
    2782          20 :         if (debug) {
    2783           0 :                 if (new_select)
    2784           0 :                         bgp_path_info_path_with_addpath_rx_str(
    2785             :                                 new_select, path_buf, sizeof(path_buf));
    2786             :                 else
    2787           0 :                         snprintf(path_buf, sizeof(path_buf), "NONE");
    2788           0 :                 zlog_debug(
    2789             :                         "%pBD(%s): After path selection, newbest is %s oldbest was %s",
    2790             :                         dest, bgp->name_pretty, path_buf,
    2791             :                         old_select ? old_select->peer->host : "NONE");
    2792             :         }
    2793             : 
    2794          20 :         if (do_mpath && new_select) {
    2795          14 :                 for (pi = bgp_dest_get_bgp_path_info(dest);
    2796          28 :                      (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
    2797             : 
    2798          14 :                         if (debug)
    2799           0 :                                 bgp_path_info_path_with_addpath_rx_str(
    2800             :                                         pi, path_buf, sizeof(path_buf));
    2801             : 
    2802          14 :                         if (pi == new_select) {
    2803          14 :                                 if (debug)
    2804           0 :                                         zlog_debug(
    2805             :                                                 "%pBD(%s): %s is the bestpath, add to the multipath list",
    2806             :                                                 dest, bgp->name_pretty,
    2807             :                                                 path_buf);
    2808          14 :                                 bgp_mp_list_add(&mp_list, pi);
    2809          14 :                                 continue;
    2810             :                         }
    2811             : 
    2812           0 :                         if (BGP_PATH_HOLDDOWN(pi))
    2813           0 :                                 continue;
    2814             : 
    2815           0 :                         if (pi->peer && pi->peer != bgp->peer_self
    2816           0 :                             && !CHECK_FLAG(pi->peer->sflags,
    2817             :                                            PEER_STATUS_NSF_WAIT))
    2818           0 :                                 if (!peer_established(pi->peer))
    2819           0 :                                         continue;
    2820             : 
    2821           0 :                         if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
    2822           0 :                                 if (debug)
    2823           0 :                                         zlog_debug(
    2824             :                                                 "%pBD: %s has the same nexthop as the bestpath, skip it",
    2825             :                                                 dest, path_buf);
    2826           0 :                                 continue;
    2827             :                         }
    2828             : 
    2829           0 :                         bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
    2830             :                                           mpath_cfg, debug, pfx_buf, afi, safi,
    2831             :                                           &dest->reason);
    2832             : 
    2833           0 :                         if (paths_eq) {
    2834           0 :                                 if (debug)
    2835           0 :                                         zlog_debug(
    2836             :                                                 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
    2837             :                                                 dest, path_buf);
    2838           0 :                                 bgp_mp_list_add(&mp_list, pi);
    2839             :                         }
    2840             :                 }
    2841             :         }
    2842             : 
    2843          20 :         bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
    2844             :                                    mpath_cfg);
    2845          20 :         bgp_path_info_mpath_aggregate_update(new_select, old_select);
    2846          20 :         bgp_mp_list_clear(&mp_list);
    2847             : 
    2848          20 :         bgp_addpath_update_ids(bgp, dest, afi, safi);
    2849             : 
    2850          20 :         result->old = old_select;
    2851          20 :         result->new = new_select;
    2852             : 
    2853          20 :         return;
    2854             : }
    2855             : 
    2856             : /*
    2857             :  * A new route/change in bestpath of an existing route. Evaluate the path
    2858             :  * for advertisement to the subgroup.
    2859             :  */
    2860           4 : void subgroup_process_announce_selected(struct update_subgroup *subgrp,
    2861             :                                         struct bgp_path_info *selected,
    2862             :                                         struct bgp_dest *dest,
    2863             :                                         uint32_t addpath_tx_id)
    2864             : {
    2865           4 :         const struct prefix *p;
    2866           4 :         struct peer *onlypeer;
    2867           4 :         struct attr attr;
    2868           4 :         afi_t afi;
    2869           4 :         safi_t safi;
    2870           4 :         struct bgp *bgp;
    2871           4 :         bool advertise;
    2872             : 
    2873           4 :         p = bgp_dest_get_prefix(dest);
    2874           4 :         afi = SUBGRP_AFI(subgrp);
    2875           4 :         safi = SUBGRP_SAFI(subgrp);
    2876           4 :         bgp = SUBGRP_INST(subgrp);
    2877          12 :         onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
    2878           4 :                                                  : NULL);
    2879             : 
    2880           4 :         if (BGP_DEBUG(update, UPDATE_OUT))
    2881           0 :                 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
    2882             : 
    2883             :         /* First update is deferred until ORF or ROUTE-REFRESH is received */
    2884           4 :         if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
    2885             :                                    PEER_STATUS_ORF_WAIT_REFRESH))
    2886           0 :                 return;
    2887             : 
    2888           4 :         memset(&attr, 0, sizeof(attr));
    2889             :         /* It's initialized in bgp_announce_check() */
    2890             : 
    2891             :         /* Announcement to the subgroup. If the route is filtered withdraw it.
    2892             :          * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
    2893             :          * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
    2894             :          * route
    2895             :          */
    2896           4 :         advertise = bgp_check_advertise(bgp, dest);
    2897             : 
    2898           4 :         if (selected) {
    2899           4 :                 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
    2900             :                                             NULL)) {
    2901             :                         /* Route is selected, if the route is already installed
    2902             :                          * in FIB, then it is advertised
    2903             :                          */
    2904           4 :                         if (advertise) {
    2905           4 :                                 if (!bgp_check_withdrawal(bgp, dest))
    2906           4 :                                         bgp_adj_out_set_subgroup(
    2907             :                                                 dest, subgrp, &attr, selected);
    2908             :                                 else
    2909           0 :                                         bgp_adj_out_unset_subgroup(
    2910             :                                                 dest, subgrp, 1, addpath_tx_id);
    2911             :                         }
    2912             :                 } else
    2913           0 :                         bgp_adj_out_unset_subgroup(dest, subgrp, 1,
    2914             :                                                    addpath_tx_id);
    2915             :         }
    2916             : 
    2917             :         /* If selected is NULL we must withdraw the path using addpath_tx_id */
    2918             :         else {
    2919           0 :                 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
    2920             :         }
    2921             : }
    2922             : 
    2923             : /*
    2924             :  * Clear IGP changed flag and attribute changed flag for a route (all paths).
    2925             :  * This is called at the end of route processing.
    2926             :  */
    2927          20 : void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
    2928             : {
    2929          20 :         struct bgp_path_info *pi;
    2930             : 
    2931          60 :         for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
    2932          20 :                 if (BGP_PATH_HOLDDOWN(pi))
    2933           6 :                         continue;
    2934          14 :                 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
    2935          14 :                 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
    2936             :         }
    2937          20 : }
    2938             : 
    2939             : /*
    2940             :  * Has the route changed from the RIB's perspective? This is invoked only
    2941             :  * if the route selection returns the same best route as earlier - to
    2942             :  * determine if we need to update zebra or not.
    2943             :  */
    2944           0 : bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
    2945             : {
    2946           0 :         struct bgp_path_info *mpinfo;
    2947             : 
    2948             :         /* If this is multipath, check all selected paths for any nexthop
    2949             :          * change or attribute change. Some attribute changes (e.g., community)
    2950             :          * aren't of relevance to the RIB, but we'll update zebra to ensure
    2951             :          * we handle the case of BGP nexthop change. This is the behavior
    2952             :          * when the best path has an attribute change anyway.
    2953             :          */
    2954           0 :         if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
    2955             :             || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
    2956           0 :             || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
    2957             :                 return true;
    2958             : 
    2959             :         /*
    2960             :          * If this is multipath, check all selected paths for any nexthop change
    2961             :          */
    2962           0 :         for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
    2963           0 :              mpinfo = bgp_path_info_mpath_next(mpinfo)) {
    2964           0 :                 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
    2965           0 :                     || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
    2966             :                         return true;
    2967             :         }
    2968             : 
    2969             :         /* Nothing has changed from the RIB's perspective. */
    2970             :         return false;
    2971             : }
    2972             : 
    2973             : struct bgp_process_queue {
    2974             :         struct bgp *bgp;
    2975             :         STAILQ_HEAD(, bgp_dest) pqueue;
    2976             : #define BGP_PROCESS_QUEUE_EOIU_MARKER           (1 << 0)
    2977             :         unsigned int flags;
    2978             :         unsigned int queued;
    2979             : };
    2980             : 
    2981          20 : static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
    2982             :                                              safi_t safi, struct bgp_dest *dest,
    2983             :                                              struct bgp_path_info *new_select,
    2984             :                                              struct bgp_path_info *old_select)
    2985             : {
    2986          20 :         const struct prefix *p = bgp_dest_get_prefix(dest);
    2987             : 
    2988          20 :         if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
    2989             :                 return;
    2990             : 
    2991          20 :         if (advertise_type5_routes(bgp, afi) && new_select
    2992           0 :             && is_route_injectable_into_evpn(new_select)) {
    2993             : 
    2994             :                 /* apply the route-map */
    2995           0 :                 if (bgp->adv_cmd_rmap[afi][safi].map) {
    2996           0 :                         route_map_result_t ret;
    2997           0 :                         struct bgp_path_info rmap_path;
    2998           0 :                         struct bgp_path_info_extra rmap_path_extra;
    2999           0 :                         struct attr dummy_attr;
    3000             : 
    3001           0 :                         dummy_attr = *new_select->attr;
    3002             : 
    3003             :                         /* Fill temp path_info */
    3004           0 :                         prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
    3005             :                                             new_select, new_select->peer,
    3006             :                                             &dummy_attr);
    3007             : 
    3008           0 :                         RESET_FLAG(dummy_attr.rmap_change_flags);
    3009             : 
    3010           0 :                         ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
    3011             :                                               p, &rmap_path);
    3012             : 
    3013           0 :                         if (ret == RMAP_DENYMATCH) {
    3014           0 :                                 bgp_attr_flush(&dummy_attr);
    3015           0 :                                 bgp_evpn_withdraw_type5_route(bgp, p, afi,
    3016             :                                                               safi);
    3017             :                         } else
    3018           0 :                                 bgp_evpn_advertise_type5_route(
    3019             :                                         bgp, p, &dummy_attr, afi, safi);
    3020             :                 } else {
    3021           0 :                         bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
    3022             :                                                        afi, safi);
    3023             :                 }
    3024          20 :         } else if (advertise_type5_routes(bgp, afi) && old_select
    3025           0 :                    && is_route_injectable_into_evpn(old_select))
    3026           0 :                 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
    3027             : }
    3028             : 
    3029             : /*
    3030             :  * Utility to determine whether a particular path_info should use
    3031             :  * the IMPLICIT_NULL label. This is pretty specialized: it's only called
    3032             :  * in a path where we basically _know_ this is a BGP-LU route.
    3033             :  */
    3034           0 : static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
    3035             : {
    3036             :         /* Certain types get imp null; so do paths where the nexthop is
    3037             :          * not labeled.
    3038             :          */
    3039           0 :         if (new_select->sub_type == BGP_ROUTE_STATIC
    3040             :             || new_select->sub_type == BGP_ROUTE_AGGREGATE
    3041           0 :             || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
    3042             :                 return true;
    3043           0 :         else if (new_select->extra == NULL ||
    3044           0 :                  !bgp_is_valid_label(&new_select->extra->label[0]))
    3045             :                 /* TODO -- should be configurable? */
    3046             :                 return true;
    3047             :         else
    3048           0 :                 return false;
    3049             : }
    3050             : 
    3051             : /*
    3052             :  * old_select = The old best path
    3053             :  * new_select = the new best path
    3054             :  *
    3055             :  * if (!old_select && new_select)
    3056             :  *     We are sending new information on.
    3057             :  *
    3058             :  * if (old_select && new_select) {
    3059             :  *         if (new_select != old_select)
    3060             :  *                 We have a new best path send a change
    3061             :  *         else
    3062             :  *                 We've received a update with new attributes that needs
    3063             :  *                 to be passed on.
    3064             :  * }
    3065             :  *
    3066             :  * if (old_select && !new_select)
    3067             :  *     We have no eligible route that we can announce or the rn
    3068             :  *     is being removed.
    3069             :  */
    3070          20 : static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
    3071             :                                  afi_t afi, safi_t safi)
    3072             : {
    3073          20 :         struct bgp_path_info *new_select;
    3074          20 :         struct bgp_path_info *old_select;
    3075          20 :         struct bgp_path_info_pair old_and_new;
    3076          20 :         int debug = 0;
    3077             : 
    3078          20 :         if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
    3079           0 :                 if (dest)
    3080           0 :                         debug = bgp_debug_bestpath(dest);
    3081           0 :                 if (debug)
    3082           0 :                         zlog_debug(
    3083             :                                 "%s: bgp delete in progress, ignoring event, p=%pBD",
    3084             :                                 __func__, dest);
    3085           0 :                 return;
    3086             :         }
    3087             :         /* Is it end of initial update? (after startup) */
    3088          20 :         if (!dest) {
    3089           0 :                 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
    3090             :                               sizeof(bgp->update_delay_zebra_resume_time));
    3091             : 
    3092           0 :                 bgp->main_zebra_update_hold = 0;
    3093           0 :                 FOREACH_AFI_SAFI (afi, safi) {
    3094           0 :                         if (bgp_fibupd_safi(safi))
    3095           0 :                                 bgp_zebra_announce_table(bgp, afi, safi);
    3096             :                 }
    3097           0 :                 bgp->main_peers_update_hold = 0;
    3098             : 
    3099           0 :                 bgp_start_routeadv(bgp);
    3100           0 :                 return;
    3101             :         }
    3102             : 
    3103          20 :         const struct prefix *p = bgp_dest_get_prefix(dest);
    3104             : 
    3105          20 :         debug = bgp_debug_bestpath(dest);
    3106          20 :         if (debug)
    3107           0 :                 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__,
    3108             :                            dest, bgp->name_pretty, afi2str(afi),
    3109             :                            safi2str(safi));
    3110             : 
    3111             :         /* The best path calculation for the route is deferred if
    3112             :          * BGP_NODE_SELECT_DEFER is set
    3113             :          */
    3114          20 :         if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
    3115           0 :                 if (BGP_DEBUG(update, UPDATE_OUT))
    3116           0 :                         zlog_debug("SELECT_DEFER flag set for route %p", dest);
    3117           0 :                 return;
    3118             :         }
    3119             : 
    3120             :         /* Best path selection. */
    3121          20 :         bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
    3122             :                            afi, safi);
    3123          20 :         old_select = old_and_new.old;
    3124          20 :         new_select = old_and_new.new;
    3125             : 
    3126             :         /* Do we need to allocate or free labels?
    3127             :          * Right now, since we only deal with per-prefix labels, it is not
    3128             :          * necessary to do this upon changes to best path. Exceptions:
    3129             :          * - label index has changed -> recalculate resulting label
    3130             :          * - path_info sub_type changed -> switch to/from implicit-null
    3131             :          * - no valid label (due to removed static label binding) -> get new one
    3132             :          */
    3133          20 :         if (bgp->allocate_mpls_labels[afi][safi]) {
    3134           0 :                 if (new_select) {
    3135           0 :                         if (!old_select
    3136           0 :                             || bgp_label_index_differs(new_select, old_select)
    3137           0 :                             || new_select->sub_type != old_select->sub_type
    3138           0 :                             || !bgp_is_valid_label(&dest->local_label)) {
    3139             :                                 /* Enforced penultimate hop popping:
    3140             :                                  * implicit-null for local routes, aggregate
    3141             :                                  * and redistributed routes
    3142             :                                  */
    3143           0 :                                 if (bgp_lu_need_imp_null(new_select)) {
    3144           0 :                                         if (CHECK_FLAG(
    3145             :                                                     dest->flags,
    3146             :                                                     BGP_NODE_REGISTERED_FOR_LABEL)
    3147             :                                             || CHECK_FLAG(
    3148             :                                                     dest->flags,
    3149             :                                                     BGP_NODE_LABEL_REQUESTED))
    3150           0 :                                                 bgp_unregister_for_label(dest);
    3151           0 :                                         dest->local_label = mpls_lse_encode(
    3152             :                                                 MPLS_LABEL_IMPLICIT_NULL, 0, 0,
    3153             :                                                 1);
    3154           0 :                                         bgp_set_valid_label(&dest->local_label);
    3155             :                                 } else
    3156           0 :                                         bgp_register_for_label(dest,
    3157             :                                                                new_select);
    3158             :                         }
    3159           0 :                 } else if (CHECK_FLAG(dest->flags,
    3160             :                                       BGP_NODE_REGISTERED_FOR_LABEL)
    3161             :                            || CHECK_FLAG(dest->flags,
    3162             :                                          BGP_NODE_LABEL_REQUESTED)) {
    3163           0 :                         bgp_unregister_for_label(dest);
    3164             :                 }
    3165          20 :         } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
    3166             :                    || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
    3167           0 :                 bgp_unregister_for_label(dest);
    3168             :         }
    3169             : 
    3170          20 :         if (debug)
    3171           0 :                 zlog_debug(
    3172             :                         "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
    3173             :                         __func__, dest, bgp->name_pretty, afi2str(afi),
    3174             :                         safi2str(safi), old_select, new_select);
    3175             : 
    3176             :         /* If best route remains the same and this is not due to user-initiated
    3177             :          * clear, see exactly what needs to be done.
    3178             :          */
    3179          20 :         if (old_select && old_select == new_select
    3180           0 :             && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
    3181           0 :             && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
    3182           0 :             && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
    3183           0 :                 if (bgp_zebra_has_route_changed(old_select)) {
    3184             : #ifdef ENABLE_BGP_VNC
    3185           0 :                         vnc_import_bgp_add_route(bgp, p, old_select);
    3186           0 :                         vnc_import_bgp_exterior_add_route(bgp, p, old_select);
    3187             : #endif
    3188           0 :                         if (bgp_fibupd_safi(safi)
    3189           0 :                             && !bgp_option_check(BGP_OPT_NO_FIB)) {
    3190             : 
    3191           0 :                                 if (BGP_SUPPRESS_FIB_ENABLED(bgp)
    3192           0 :                                     && new_select->sub_type == BGP_ROUTE_NORMAL)
    3193           0 :                                         SET_FLAG(dest->flags,
    3194             :                                                  BGP_NODE_FIB_INSTALL_PENDING);
    3195             : 
    3196           0 :                                 if (new_select->type == ZEBRA_ROUTE_BGP
    3197           0 :                                     && (new_select->sub_type == BGP_ROUTE_NORMAL
    3198           0 :                                         || new_select->sub_type
    3199             :                                                    == BGP_ROUTE_IMPORTED))
    3200             : 
    3201           0 :                                         bgp_zebra_announce(dest, p, old_select,
    3202             :                                                            bgp, afi, safi);
    3203             :                         }
    3204             :                 }
    3205             : 
    3206             :                 /* If there is a change of interest to peers, reannounce the
    3207             :                  * route. */
    3208           0 :                 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
    3209           0 :                     || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
    3210           0 :                     || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
    3211           0 :                         group_announce_route(bgp, afi, safi, dest, new_select);
    3212             : 
    3213             :                         /* unicast routes must also be annouced to
    3214             :                          * labeled-unicast update-groups */
    3215           0 :                         if (safi == SAFI_UNICAST)
    3216           0 :                                 group_announce_route(bgp, afi,
    3217             :                                                      SAFI_LABELED_UNICAST, dest,
    3218             :                                                      new_select);
    3219             : 
    3220           0 :                         UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
    3221           0 :                         UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
    3222             :                 }
    3223             : 
    3224             :                 /* advertise/withdraw type-5 routes */
    3225           0 :                 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
    3226           0 :                     || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
    3227           0 :                         bgp_process_evpn_route_injection(
    3228             :                                 bgp, afi, safi, dest, old_select, old_select);
    3229             : 
    3230           0 :                 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
    3231           0 :                 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
    3232           0 :                 bgp_zebra_clear_route_change_flags(dest);
    3233           0 :                 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
    3234           0 :                 return;
    3235             :         }
    3236             : 
    3237             :         /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
    3238             :          */
    3239          20 :         UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
    3240             : 
    3241             :         /* bestpath has changed; bump version */
    3242          20 :         if (old_select || new_select) {
    3243          20 :                 bgp_bump_version(dest);
    3244             : 
    3245          20 :                 if (!bgp->t_rmap_def_originate_eval) {
    3246           3 :                         bgp_lock(bgp);
    3247           3 :                         thread_add_timer(
    3248             :                                 bm->master,
    3249             :                                 update_group_refresh_default_originate_route_map,
    3250             :                                 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
    3251             :                                 &bgp->t_rmap_def_originate_eval);
    3252             :                 }
    3253             :         }
    3254             : 
    3255          20 :         if (old_select)
    3256           6 :                 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
    3257          20 :         if (new_select) {
    3258          14 :                 if (debug)
    3259           0 :                         zlog_debug("%s: setting SELECTED flag", __func__);
    3260          14 :                 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
    3261          14 :                 bgp_path_info_unset_flag(dest, new_select,
    3262             :                                          BGP_PATH_ATTR_CHANGED);
    3263          14 :                 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
    3264          14 :                 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
    3265             :         }
    3266             : 
    3267             : #ifdef ENABLE_BGP_VNC
    3268          20 :         if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
    3269          20 :                 if (old_select != new_select) {
    3270          20 :                         if (old_select) {
    3271           6 :                                 vnc_import_bgp_exterior_del_route(bgp, p,
    3272             :                                                                   old_select);
    3273           6 :                                 vnc_import_bgp_del_route(bgp, p, old_select);
    3274             :                         }
    3275          20 :                         if (new_select) {
    3276          14 :                                 vnc_import_bgp_exterior_add_route(bgp, p,
    3277             :                                                                   new_select);
    3278          14 :                                 vnc_import_bgp_add_route(bgp, p, new_select);
    3279             :                         }
    3280             :                 }
    3281             :         }
    3282             : #endif
    3283             : 
    3284          20 :         group_announce_route(bgp, afi, safi, dest, new_select);
    3285             : 
    3286             :         /* unicast routes must also be annouced to labeled-unicast update-groups
    3287             :          */
    3288          20 :         if (safi == SAFI_UNICAST)
    3289          20 :                 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
    3290             :                                      new_select);
    3291             : 
    3292             :         /* FIB update. */
    3293          20 :         if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
    3294          20 :             && !bgp_option_check(BGP_OPT_NO_FIB)) {
    3295             : 
    3296          20 :                 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
    3297           8 :                     && (new_select->sub_type == BGP_ROUTE_NORMAL
    3298           8 :                         || new_select->sub_type == BGP_ROUTE_AGGREGATE
    3299           0 :                         || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
    3300             : 
    3301           8 :                         if (BGP_SUPPRESS_FIB_ENABLED(bgp))
    3302           0 :                                 SET_FLAG(dest->flags,
    3303             :                                          BGP_NODE_FIB_INSTALL_PENDING);
    3304             : 
    3305             :                         /* if this is an evpn imported type-5 prefix,
    3306             :                          * we need to withdraw the route first to clear
    3307             :                          * the nh neigh and the RMAC entry.
    3308             :                          */
    3309           8 :                         if (old_select &&
    3310           0 :                             is_route_parent_evpn(old_select))
    3311           0 :                                 bgp_zebra_withdraw(p, old_select, bgp, safi);
    3312             : 
    3313           8 :                         bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
    3314             :                 } else {
    3315             :                         /* Withdraw the route from the kernel. */
    3316          12 :                         if (old_select && old_select->type == ZEBRA_ROUTE_BGP
    3317           4 :                             && (old_select->sub_type == BGP_ROUTE_NORMAL
    3318           4 :                                 || old_select->sub_type == BGP_ROUTE_AGGREGATE
    3319           0 :                                 || old_select->sub_type == BGP_ROUTE_IMPORTED))
    3320             : 
    3321           4 :                                 bgp_zebra_withdraw(p, old_select, bgp, safi);
    3322             :                 }
    3323             :         }
    3324             : 
    3325          20 :         bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
    3326             :                                          old_select);
    3327             : 
    3328             :         /* Clear any route change flags. */
    3329          20 :         bgp_zebra_clear_route_change_flags(dest);
    3330             : 
    3331             :         /* Reap old select bgp_path_info, if it has been removed */
    3332          20 :         if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
    3333           6 :                 bgp_path_info_reap(dest, old_select);
    3334             : 
    3335          20 :         UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
    3336          20 :         return;
    3337             : }
    3338             : 
    3339             : /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
    3340           4 : void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
    3341             : {
    3342           4 :         struct bgp_dest *dest;
    3343           4 :         int cnt = 0;
    3344           4 :         struct afi_safi_info *thread_info;
    3345             : 
    3346           4 :         if (bgp->gr_info[afi][safi].t_route_select) {
    3347           0 :                 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
    3348             : 
    3349           0 :                 thread_info = THREAD_ARG(t);
    3350           0 :                 XFREE(MTYPE_TMP, thread_info);
    3351           0 :                 THREAD_OFF(bgp->gr_info[afi][safi].t_route_select);
    3352             :         }
    3353             : 
    3354           4 :         if (BGP_DEBUG(update, UPDATE_OUT)) {
    3355           0 :                 zlog_debug("%s: processing route for %s : cnt %d", __func__,
    3356             :                            get_afi_safi_str(afi, safi, false),
    3357             :                            bgp->gr_info[afi][safi].gr_deferred);
    3358             :         }
    3359             : 
    3360             :         /* Process the route list */
    3361           4 :         for (dest = bgp_table_top(bgp->rib[afi][safi]);
    3362           4 :              dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
    3363             :              cnt < BGP_MAX_BEST_ROUTE_SELECT;
    3364           0 :              dest = bgp_route_next(dest)) {
    3365           0 :                 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
    3366           0 :                         continue;
    3367             : 
    3368           0 :                 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
    3369           0 :                 bgp->gr_info[afi][safi].gr_deferred--;
    3370           0 :                 bgp_process_main_one(bgp, dest, afi, safi);
    3371           0 :                 cnt++;
    3372             :         }
    3373             :         /* If iteration stopped before the entire table was traversed then the
    3374             :          * node needs to be unlocked.
    3375             :          */
    3376           4 :         if (dest) {
    3377           3 :                 bgp_dest_unlock_node(dest);
    3378           3 :                 dest = NULL;
    3379             :         }
    3380             : 
    3381             :         /* Send EOR message when all routes are processed */
    3382           4 :         if (!bgp->gr_info[afi][safi].gr_deferred) {
    3383           4 :                 bgp_send_delayed_eor(bgp);
    3384             :                 /* Send route processing complete message to RIB */
    3385           4 :                 bgp_zebra_update(afi, safi, bgp->vrf_id,
    3386             :                                  ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
    3387           4 :                 return;
    3388             :         }
    3389             : 
    3390           0 :         thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
    3391             : 
    3392           0 :         thread_info->afi = afi;
    3393           0 :         thread_info->safi = safi;
    3394           0 :         thread_info->bgp = bgp;
    3395             : 
    3396             :         /* If there are more routes to be processed, start the
    3397             :          * selection timer
    3398             :          */
    3399           0 :         thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
    3400             :                         BGP_ROUTE_SELECT_DELAY,
    3401             :                         &bgp->gr_info[afi][safi].t_route_select);
    3402             : }
    3403             : 
    3404           6 : static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
    3405             : {
    3406           6 :         struct bgp_process_queue *pqnode = data;
    3407           6 :         struct bgp *bgp = pqnode->bgp;
    3408           6 :         struct bgp_table *table;
    3409           6 :         struct bgp_dest *dest;
    3410             : 
    3411             :         /* eoiu marker */
    3412           6 :         if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
    3413           0 :                 bgp_process_main_one(bgp, NULL, 0, 0);
    3414             :                 /* should always have dedicated wq call */
    3415           0 :                 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
    3416             :                 return WQ_SUCCESS;
    3417             :         }
    3418             : 
    3419          26 :         while (!STAILQ_EMPTY(&pqnode->pqueue)) {
    3420          20 :                 dest = STAILQ_FIRST(&pqnode->pqueue);
    3421          20 :                 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
    3422          20 :                 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
    3423          20 :                 table = bgp_dest_table(dest);
    3424             :                 /* note, new DESTs may be added as part of processing */
    3425          20 :                 bgp_process_main_one(bgp, dest, table->afi, table->safi);
    3426             : 
    3427          20 :                 bgp_dest_unlock_node(dest);
    3428          20 :                 bgp_table_unlock(table);
    3429             :         }
    3430             : 
    3431             :         return WQ_SUCCESS;
    3432             : }
    3433             : 
    3434           6 : static void bgp_processq_del(struct work_queue *wq, void *data)
    3435             : {
    3436           6 :         struct bgp_process_queue *pqnode = data;
    3437             : 
    3438           6 :         bgp_unlock(pqnode->bgp);
    3439             : 
    3440           6 :         XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
    3441           6 : }
    3442             : 
    3443           3 : void bgp_process_queue_init(struct bgp *bgp)
    3444             : {
    3445           3 :         if (!bgp->process_queue) {
    3446           3 :                 char name[BUFSIZ];
    3447             : 
    3448           3 :                 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
    3449           3 :                 bgp->process_queue = work_queue_new(bm->master, name);
    3450             :         }
    3451             : 
    3452           3 :         bgp->process_queue->spec.workfunc = &bgp_process_wq;
    3453           3 :         bgp->process_queue->spec.del_item_data = &bgp_processq_del;
    3454           3 :         bgp->process_queue->spec.max_retries = 0;
    3455           3 :         bgp->process_queue->spec.hold = 50;
    3456             :         /* Use a higher yield value of 50ms for main queue processing */
    3457           3 :         bgp->process_queue->spec.yield = 50 * 1000L;
    3458           3 : }
    3459             : 
    3460           6 : static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
    3461             : {
    3462           6 :         struct bgp_process_queue *pqnode;
    3463             : 
    3464           6 :         pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
    3465             :                          sizeof(struct bgp_process_queue));
    3466             : 
    3467             :         /* unlocked in bgp_processq_del */
    3468           6 :         pqnode->bgp = bgp_lock(bgp);
    3469           6 :         STAILQ_INIT(&pqnode->pqueue);
    3470             : 
    3471           6 :         return pqnode;
    3472             : }
    3473             : 
    3474          28 : void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
    3475             : {
    3476             : #define ARBITRARY_PROCESS_QLEN          10000
    3477          28 :         struct work_queue *wq = bgp->process_queue;
    3478          28 :         struct bgp_process_queue *pqnode;
    3479          28 :         int pqnode_reuse = 0;
    3480             : 
    3481             :         /* already scheduled for processing? */
    3482          28 :         if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
    3483             :                 return;
    3484             : 
    3485             :         /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
    3486             :          * the workqueue
    3487             :          */
    3488          20 :         if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
    3489           0 :                 if (BGP_DEBUG(update, UPDATE_OUT))
    3490           0 :                         zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
    3491             :                                    dest);
    3492           0 :                 return;
    3493             :         }
    3494             : 
    3495          20 :         if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
    3496           0 :                 if (BGP_DEBUG(update, UPDATE_OUT))
    3497           0 :                         zlog_debug(
    3498             :                                 "Soft reconfigure table in progress for route %p",
    3499             :                                 dest);
    3500           0 :                 return;
    3501             :         }
    3502             : 
    3503          20 :         if (wq == NULL)
    3504             :                 return;
    3505             : 
    3506             :         /* Add route nodes to an existing work queue item until reaching the
    3507             :            limit only if is from the same BGP view and it's not an EOIU marker
    3508             :          */
    3509          20 :         if (work_queue_item_count(wq)) {
    3510          14 :                 struct work_queue_item *item = work_queue_last_item(wq);
    3511          14 :                 pqnode = item->data;
    3512             : 
    3513          14 :                 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
    3514          14 :                     || pqnode->bgp != bgp
    3515          14 :                     || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
    3516           0 :                         pqnode = bgp_processq_alloc(bgp);
    3517             :                 else
    3518             :                         pqnode_reuse = 1;
    3519             :         } else
    3520           6 :                 pqnode = bgp_processq_alloc(bgp);
    3521             :         /* all unlocked in bgp_process_wq */
    3522          20 :         bgp_table_lock(bgp_dest_table(dest));
    3523             : 
    3524          20 :         SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
    3525          20 :         bgp_dest_lock_node(dest);
    3526             : 
    3527             :         /* can't be enqueued twice */
    3528          20 :         assert(STAILQ_NEXT(dest, pq) == NULL);
    3529          20 :         STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
    3530          20 :         pqnode->queued++;
    3531             : 
    3532          20 :         if (!pqnode_reuse)
    3533           6 :                 work_queue_add(wq, pqnode);
    3534             : 
    3535             :         return;
    3536             : }
    3537             : 
    3538           0 : void bgp_add_eoiu_mark(struct bgp *bgp)
    3539             : {
    3540           0 :         struct bgp_process_queue *pqnode;
    3541             : 
    3542           0 :         if (bgp->process_queue == NULL)
    3543             :                 return;
    3544             : 
    3545           0 :         pqnode = bgp_processq_alloc(bgp);
    3546             : 
    3547           0 :         SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
    3548           0 :         work_queue_add(bgp->process_queue, pqnode);
    3549             : }
    3550             : 
    3551           0 : static void bgp_maximum_prefix_restart_timer(struct thread *thread)
    3552             : {
    3553           0 :         struct peer *peer;
    3554             : 
    3555           0 :         peer = THREAD_ARG(thread);
    3556           0 :         peer->t_pmax_restart = NULL;
    3557             : 
    3558           0 :         if (bgp_debug_neighbor_events(peer))
    3559           0 :                 zlog_debug(
    3560             :                         "%s Maximum-prefix restart timer expired, restore peering",
    3561             :                         peer->host);
    3562             : 
    3563           0 :         if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
    3564           0 :                 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
    3565           0 : }
    3566             : 
    3567           0 : static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
    3568             :                                           safi_t safi)
    3569             : {
    3570           0 :         uint32_t count = 0;
    3571           0 :         bool filtered = false;
    3572           0 :         struct bgp_dest *dest;
    3573           0 :         struct bgp_adj_in *ain;
    3574           0 :         struct attr attr = {};
    3575           0 :         struct bgp_table *table = peer->bgp->rib[afi][safi];
    3576             : 
    3577           0 :         for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
    3578           0 :                 for (ain = dest->adj_in; ain; ain = ain->next) {
    3579           0 :                         const struct prefix *rn_p = bgp_dest_get_prefix(dest);
    3580             : 
    3581           0 :                         attr = *ain->attr;
    3582             : 
    3583           0 :                         if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
    3584             :                             == FILTER_DENY)
    3585           0 :                                 filtered = true;
    3586             : 
    3587           0 :                         if (bgp_input_modifier(
    3588             :                                     peer, rn_p, &attr, afi, safi,
    3589           0 :                                     ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
    3590             :                                     NULL, 0, NULL)
    3591             :                             == RMAP_DENY)
    3592             :                                 filtered = true;
    3593             : 
    3594           0 :                         if (filtered)
    3595           0 :                                 count++;
    3596             : 
    3597           0 :                         bgp_attr_flush(&attr);
    3598             :                 }
    3599             :         }
    3600             : 
    3601           0 :         return count;
    3602             : }
    3603             : 
    3604          11 : bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
    3605             :                                  int always)
    3606             : {
    3607          11 :         iana_afi_t pkt_afi;
    3608          11 :         iana_safi_t pkt_safi;
    3609          22 :         uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
    3610             :                                       PEER_FLAG_MAX_PREFIX_FORCE))
    3611           0 :                                   ? bgp_filtered_routes_count(peer, afi, safi)
    3612           0 :                                             + peer->pcount[afi][safi]
    3613          11 :                                   : peer->pcount[afi][safi];
    3614             : 
    3615          11 :         if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
    3616             :                 return false;
    3617             : 
    3618           0 :         if (pcount > peer->pmax[afi][safi]) {
    3619           0 :                 if (CHECK_FLAG(peer->af_sflags[afi][safi],
    3620             :                                PEER_STATUS_PREFIX_LIMIT)
    3621           0 :                     && !always)
    3622             :                         return false;
    3623             : 
    3624           0 :                 zlog_info(
    3625             :                         "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
    3626             :                         get_afi_safi_str(afi, safi, false), peer, pcount,
    3627             :                         peer->pmax[afi][safi]);
    3628           0 :                 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
    3629             : 
    3630           0 :                 if (CHECK_FLAG(peer->af_flags[afi][safi],
    3631             :                                PEER_FLAG_MAX_PREFIX_WARNING))
    3632             :                         return false;
    3633             : 
    3634             :                 /* Convert AFI, SAFI to values for packet. */
    3635           0 :                 pkt_afi = afi_int2iana(afi);
    3636           0 :                 pkt_safi = safi_int2iana(safi);
    3637             :                 {
    3638           0 :                         uint8_t ndata[7];
    3639             : 
    3640           0 :                         ndata[0] = (pkt_afi >> 8);
    3641           0 :                         ndata[1] = pkt_afi;
    3642           0 :                         ndata[2] = pkt_safi;
    3643           0 :                         ndata[3] = (peer->pmax[afi][safi] >> 24);
    3644           0 :                         ndata[4] = (peer->pmax[afi][safi] >> 16);
    3645           0 :                         ndata[5] = (peer->pmax[afi][safi] >> 8);
    3646           0 :                         ndata[6] = (peer->pmax[afi][safi]);
    3647             : 
    3648           0 :                         SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
    3649           0 :                         bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
    3650             :                                                   BGP_NOTIFY_CEASE_MAX_PREFIX,
    3651             :                                                   ndata, 7);
    3652             :                 }
    3653             : 
    3654             :                 /* Dynamic peers will just close their connection. */
    3655           0 :                 if (peer_dynamic_neighbor(peer))
    3656             :                         return true;
    3657             : 
    3658             :                 /* restart timer start */
    3659           0 :                 if (peer->pmax_restart[afi][safi]) {
    3660           0 :                         peer->v_pmax_restart =
    3661           0 :                                 peer->pmax_restart[afi][safi] * 60;
    3662             : 
    3663           0 :                         if (bgp_debug_neighbor_events(peer))
    3664           0 :                                 zlog_debug(
    3665             :                                         "%pBP Maximum-prefix restart timer started for %d secs",
    3666             :                                         peer, peer->v_pmax_restart);
    3667             : 
    3668           0 :                         BGP_TIMER_ON(peer->t_pmax_restart,
    3669             :                                      bgp_maximum_prefix_restart_timer,
    3670             :                                      peer->v_pmax_restart);
    3671             :                 }
    3672             : 
    3673           0 :                 return true;
    3674             :         } else
    3675           0 :                 UNSET_FLAG(peer->af_sflags[afi][safi],
    3676             :                            PEER_STATUS_PREFIX_LIMIT);
    3677             : 
    3678           0 :         if (pcount
    3679           0 :             > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
    3680           0 :                 if (CHECK_FLAG(peer->af_sflags[afi][safi],
    3681             :                                PEER_STATUS_PREFIX_THRESHOLD)
    3682           0 :                     && !always)
    3683             :                         return false;
    3684             : 
    3685           0 :                 zlog_info(
    3686             :                         "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
    3687             :                         get_afi_safi_str(afi, safi, false), peer, pcount,
    3688             :                         peer->pmax[afi][safi]);
    3689           0 :                 SET_FLAG(peer->af_sflags[afi][safi],
    3690             :                          PEER_STATUS_PREFIX_THRESHOLD);
    3691             :         } else
    3692           0 :                 UNSET_FLAG(peer->af_sflags[afi][safi],
    3693             :                            PEER_STATUS_PREFIX_THRESHOLD);
    3694             :         return false;
    3695             : }
    3696             : 
    3697             : /* Unconditionally remove the route from the RIB, without taking
    3698             :  * damping into consideration (eg, because the session went down)
    3699             :  */
    3700           7 : void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
    3701             :                     struct peer *peer, afi_t afi, safi_t safi)
    3702             : {
    3703             : 
    3704           7 :         struct bgp *bgp = NULL;
    3705           7 :         bool delete_route = false;
    3706             : 
    3707           7 :         bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
    3708             :                                 safi);
    3709             : 
    3710           7 :         if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
    3711           7 :                 bgp_path_info_delete(dest, pi); /* keep historical info */
    3712             : 
    3713             :                 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
    3714             :                  * flag
    3715             :                  */
    3716           7 :                 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
    3717             :                         delete_route = true;
    3718           3 :                 else if (bgp_dest_set_defer_flag(dest, true) < 0)
    3719             :                         delete_route = true;
    3720             :                 if (delete_route) {
    3721           4 :                         if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
    3722           0 :                                 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
    3723           0 :                                 bgp = pi->peer->bgp;
    3724           0 :                                 bgp->gr_info[afi][safi].gr_deferred--;
    3725             :                         }
    3726             :                 }
    3727             :         }
    3728             : 
    3729           7 :         hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
    3730           7 :         bgp_process(peer->bgp, dest, afi, safi);
    3731           7 : }
    3732             : 
    3733           0 : static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
    3734             :                              struct peer *peer, afi_t afi, safi_t safi,
    3735             :                              struct prefix_rd *prd)
    3736             : {
    3737           0 :         const struct prefix *p = bgp_dest_get_prefix(dest);
    3738             : 
    3739             :         /* apply dampening, if result is suppressed, we'll be retaining
    3740             :          * the bgp_path_info in the RIB for historical reference.
    3741             :          */
    3742           0 :         if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
    3743           0 :             && peer->sort == BGP_PEER_EBGP)
    3744           0 :                 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
    3745             :                     == BGP_DAMP_SUPPRESSED) {
    3746           0 :                         bgp_aggregate_decrement(peer->bgp, p, pi, afi,
    3747             :                                                 safi);
    3748           0 :                         return;
    3749             :                 }
    3750             : 
    3751             : #ifdef ENABLE_BGP_VNC
    3752           0 :         if (safi == SAFI_MPLS_VPN) {
    3753           0 :                 struct bgp_dest *pdest = NULL;
    3754           0 :                 struct bgp_table *table = NULL;
    3755             : 
    3756           0 :                 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
    3757             :                                      (struct prefix *)prd);
    3758           0 :                 if (bgp_dest_has_bgp_path_info_data(pdest)) {
    3759           0 :                         table = bgp_dest_get_bgp_table_info(pdest);
    3760             : 
    3761           0 :                         vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
    3762             :                                 peer->bgp, prd, table, p, pi);
    3763             :                 }
    3764           0 :                 bgp_dest_unlock_node(pdest);
    3765             :         }
    3766           0 :         if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
    3767           0 :                 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
    3768             : 
    3769           0 :                         vnc_import_bgp_del_route(peer->bgp, p, pi);
    3770           0 :                         vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
    3771             :                 }
    3772             :         }
    3773             : #endif
    3774             : 
    3775             :         /* If this is an EVPN route, process for un-import. */
    3776           0 :         if (safi == SAFI_EVPN)
    3777           0 :                 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
    3778             : 
    3779           0 :         bgp_rib_remove(dest, pi, peer, afi, safi);
    3780             : }
    3781             : 
    3782          17 : struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
    3783             :                                 struct peer *peer, struct attr *attr,
    3784             :                                 struct bgp_dest *dest)
    3785             : {
    3786          17 :         struct bgp_path_info *new;
    3787             : 
    3788             :         /* Make new BGP info. */
    3789          17 :         new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
    3790          17 :         new->type = type;
    3791          17 :         new->instance = instance;
    3792          17 :         new->sub_type = sub_type;
    3793          17 :         new->peer = peer;
    3794          17 :         new->attr = attr;
    3795          17 :         new->uptime = monotime(NULL);
    3796          17 :         new->net = dest;
    3797          17 :         return new;
    3798             : }
    3799             : 
    3800             : /* Check if received nexthop is valid or not. */
    3801          11 : bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
    3802             :                                 uint8_t type, uint8_t stype, struct attr *attr,
    3803             :                                 struct bgp_dest *dest)
    3804             : {
    3805          11 :         bool ret = false;
    3806          11 :         bool is_bgp_static_route =
    3807          11 :                 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
    3808          11 :                                                                        : false;
    3809             : 
    3810             :         /*
    3811             :          * Only validated for unicast and multicast currently.
    3812             :          * Also valid for EVPN where the nexthop is an IP address.
    3813             :          * If we are a bgp static route being checked then there is
    3814             :          * no need to check to see if the nexthop is martian as
    3815             :          * that it should be ok.
    3816             :          */
    3817          11 :         if (is_bgp_static_route ||
    3818          11 :             (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
    3819             :                 return false;
    3820             : 
    3821             :         /* If NEXT_HOP is present, validate it. */
    3822          11 :         if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
    3823          22 :                 if (attr->nexthop.s_addr == INADDR_ANY ||
    3824          22 :                     !ipv4_unicast_valid(&attr->nexthop) ||
    3825          11 :                     bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
    3826           0 :                         return true;
    3827             :         }
    3828             : 
    3829             :         /* If MP_NEXTHOP is present, validate it. */
    3830             :         /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
    3831             :          * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
    3832             :          * it is not an IPv6 link-local address.
    3833             :          *
    3834             :          * If we receive an UPDATE with nexthop length set to 32 bytes
    3835             :          * we shouldn't discard an UPDATE if it's set to (::).
    3836             :          * The link-local (2st) is validated along the code path later.
    3837             :          */
    3838          11 :         if (attr->mp_nexthop_len) {
    3839           0 :                 switch (attr->mp_nexthop_len) {
    3840           0 :                 case BGP_ATTR_NHLEN_IPV4:
    3841             :                 case BGP_ATTR_NHLEN_VPNV4:
    3842           0 :                         ret = (attr->mp_nexthop_global_in.s_addr ==
    3843           0 :                                        INADDR_ANY ||
    3844           0 :                                !ipv4_unicast_valid(
    3845           0 :                                        &attr->mp_nexthop_global_in) ||
    3846           0 :                                bgp_nexthop_self(bgp, afi, type, stype, attr,
    3847             :                                                 dest));
    3848           0 :                         break;
    3849             : 
    3850           0 :                 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
    3851             :                 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
    3852           0 :                         ret = (IN6_IS_ADDR_UNSPECIFIED(
    3853             :                                         &attr->mp_nexthop_global)
    3854           0 :                                || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
    3855           0 :                                || IN6_IS_ADDR_MULTICAST(
    3856             :                                        &attr->mp_nexthop_global)
    3857           0 :                                || bgp_nexthop_self(bgp, afi, type, stype, attr,
    3858             :                                                    dest));
    3859           0 :                         break;
    3860           0 :                 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
    3861           0 :                         ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
    3862           0 :                                || IN6_IS_ADDR_MULTICAST(
    3863             :                                        &attr->mp_nexthop_global)
    3864           0 :                                || bgp_nexthop_self(bgp, afi, type, stype, attr,
    3865             :                                                    dest));
    3866           0 :                         break;
    3867             : 
    3868             :                 default:
    3869             :                         ret = true;
    3870             :                         break;
    3871             :                 }
    3872             :         }
    3873             : 
    3874             :         return ret;
    3875             : }
    3876             : 
    3877           0 : static void bgp_attr_add_no_export_community(struct attr *attr)
    3878             : {
    3879           0 :         struct community *old;
    3880           0 :         struct community *new;
    3881           0 :         struct community *merge;
    3882           0 :         struct community *no_export;
    3883             : 
    3884           0 :         old = bgp_attr_get_community(attr);
    3885           0 :         no_export = community_str2com("no-export");
    3886             : 
    3887           0 :         assert(no_export);
    3888             : 
    3889           0 :         if (old) {
    3890           0 :                 merge = community_merge(community_dup(old), no_export);
    3891             : 
    3892           0 :                 if (!old->refcnt)
    3893           0 :                         community_free(&old);
    3894             : 
    3895           0 :                 new = community_uniq_sort(merge);
    3896           0 :                 community_free(&merge);
    3897             :         } else {
    3898           0 :                 new = community_dup(no_export);
    3899             :         }
    3900             : 
    3901           0 :         community_free(&no_export);
    3902             : 
    3903           0 :         bgp_attr_set_community(attr, new);
    3904           0 : }
    3905             : 
    3906           0 : static bool bgp_accept_own(struct peer *peer, afi_t afi, safi_t safi,
    3907             :                            struct attr *attr, const struct prefix *prefix,
    3908             :                            int *sub_type)
    3909             : {
    3910           0 :         struct listnode *node, *nnode;
    3911           0 :         struct bgp *bgp;
    3912           0 :         bool accept_own_found = false;
    3913             : 
    3914           0 :         if (safi != SAFI_MPLS_VPN)
    3915             :                 return false;
    3916             : 
    3917             :         /* Processing of the ACCEPT_OWN community is enabled by configuration */
    3918           0 :         if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN))
    3919             :                 return false;
    3920             : 
    3921             :         /* The route in question carries the ACCEPT_OWN community */
    3922           0 :         if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
    3923           0 :                 struct community *comm = bgp_attr_get_community(attr);
    3924             : 
    3925           0 :                 if (community_include(comm, COMMUNITY_ACCEPT_OWN))
    3926           0 :                         accept_own_found = true;
    3927             :         }
    3928             : 
    3929             :         /* The route in question is targeted to one or more destination VRFs
    3930             :          * on the router (as determined by inspecting the Route Target(s)).
    3931             :          */
    3932           0 :         for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
    3933           0 :                 if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
    3934           0 :                         continue;
    3935             : 
    3936           0 :                 if (accept_own_found &&
    3937           0 :                     ecommunity_include(
    3938             :                             bgp->vpn_policy[afi]
    3939             :                                     .rtlist[BGP_VPN_POLICY_DIR_TOVPN],
    3940             :                             bgp_attr_get_ecommunity(attr))) {
    3941           0 :                         if (bgp_debug_update(peer, prefix, NULL, 1))
    3942           0 :                                 zlog_debug(
    3943             :                                         "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
    3944             :                                         peer, prefix);
    3945             : 
    3946             :                         /* Treat this route as imported, because it's leaked
    3947             :                          * already from another VRF, and we got an updated
    3948             :                          * version from route-reflector with ACCEPT_OWN
    3949             :                          * community.
    3950             :                          */
    3951           0 :                         *sub_type = BGP_ROUTE_IMPORTED;
    3952             : 
    3953           0 :                         return true;
    3954             :                 }
    3955             :         }
    3956             : 
    3957             :         return false;
    3958             : }
    3959             : 
    3960          20 : void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
    3961             :                 struct attr *attr, afi_t afi, safi_t safi, int type,
    3962             :                 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
    3963             :                 uint32_t num_labels, int soft_reconfig,
    3964             :                 struct bgp_route_evpn *evpn)
    3965             : {
    3966          20 :         int ret;
    3967          20 :         int aspath_loop_count = 0;
    3968          20 :         struct bgp_dest *dest;
    3969          20 :         struct bgp *bgp;
    3970          20 :         struct attr new_attr;
    3971          20 :         struct attr *attr_new;
    3972          20 :         struct bgp_path_info *pi;
    3973          20 :         struct bgp_path_info *new = NULL;
    3974          20 :         struct bgp_path_info_extra *extra;
    3975          20 :         const char *reason;
    3976          20 :         char pfx_buf[BGP_PRD_PATH_STRLEN];
    3977          20 :         int connected = 0;
    3978          20 :         int do_loop_check = 1;
    3979          20 :         int has_valid_label = 0;
    3980          20 :         afi_t nh_afi;
    3981          20 :         bool force_evpn_import = false;
    3982          20 :         safi_t orig_safi = safi;
    3983          20 :         bool leak_success = true;
    3984          20 :         int allowas_in = 0;
    3985             : 
    3986          20 :         if (frrtrace_enabled(frr_bgp, process_update)) {
    3987          20 :                 char pfxprint[PREFIX2STR_BUFFER];
    3988             : 
    3989          20 :                 prefix2str(p, pfxprint, sizeof(pfxprint));
    3990          20 :                 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
    3991             :                          afi, safi, attr);
    3992             :         }
    3993             : 
    3994             : #ifdef ENABLE_BGP_VNC
    3995          20 :         int vnc_implicit_withdraw = 0;
    3996             : #endif
    3997          20 :         int same_attr = 0;
    3998          20 :         const struct prefix *bgp_nht_param_prefix;
    3999             : 
    4000             :         /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
    4001          20 :         if (orig_safi == SAFI_LABELED_UNICAST)
    4002           0 :                 safi = SAFI_UNICAST;
    4003             : 
    4004          20 :         memset(&new_attr, 0, sizeof(new_attr));
    4005          20 :         new_attr.label_index = BGP_INVALID_LABEL_INDEX;
    4006          20 :         new_attr.label = MPLS_INVALID_LABEL;
    4007             : 
    4008          20 :         bgp = peer->bgp;
    4009          20 :         dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
    4010             :         /* TODO: Check to see if we can get rid of "is_valid_label" */
    4011          20 :         if (afi == AFI_L2VPN && safi == SAFI_EVPN)
    4012           0 :                 has_valid_label = (num_labels > 0) ? 1 : 0;
    4013             :         else
    4014          20 :                 has_valid_label = bgp_is_valid_label(label);
    4015             : 
    4016           0 :         if (has_valid_label)
    4017           0 :                 assert(label != NULL);
    4018             : 
    4019             :         /* Update overlay index of the attribute */
    4020          20 :         if (afi == AFI_L2VPN && evpn)
    4021           0 :                 memcpy(&attr->evpn_overlay, evpn,
    4022             :                        sizeof(struct bgp_route_evpn));
    4023             : 
    4024             :         /* When peer's soft reconfiguration enabled.  Record input packet in
    4025             :            Adj-RIBs-In.  */
    4026          20 :         if (!soft_reconfig
    4027          20 :             && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
    4028           0 :             && peer != bgp->peer_self)
    4029           0 :                 bgp_adj_in_set(dest, peer, attr, addpath_id);
    4030             : 
    4031             :         /* Update permitted loop count */
    4032          20 :         if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
    4033           0 :                 allowas_in = peer->allowas_in[afi][safi];
    4034             : 
    4035             :         /* Check previously received route. */
    4036          48 :         for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
    4037           8 :                 if (pi->peer == peer && pi->type == type
    4038           0 :                     && pi->sub_type == sub_type
    4039           0 :                     && pi->addpath_rx_id == addpath_id)
    4040             :                         break;
    4041             : 
    4042             :         /* AS path local-as loop check. */
    4043          20 :         if (peer->change_local_as) {
    4044           0 :                 if (allowas_in)
    4045             :                         aspath_loop_count = allowas_in;
    4046           0 :                 else if (!CHECK_FLAG(peer->flags,
    4047             :                                      PEER_FLAG_LOCAL_AS_NO_PREPEND))
    4048           0 :                         aspath_loop_count = 1;
    4049             : 
    4050           0 :                 if (aspath_loop_check(attr->aspath, peer->change_local_as)
    4051             :                     > aspath_loop_count) {
    4052           0 :                         peer->stat_pfx_aspath_loop++;
    4053           0 :                         reason = "as-path contains our own AS;";
    4054           0 :                         goto filtered;
    4055             :                 }
    4056             :         }
    4057             : 
    4058             :         /* If the peer is configured for "allowas-in origin" and the last ASN in
    4059             :          * the
    4060             :          * as-path is our ASN then we do not need to call aspath_loop_check
    4061             :          */
    4062          20 :         if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
    4063           0 :                 if (aspath_get_last_as(attr->aspath) == bgp->as)
    4064          20 :                         do_loop_check = 0;
    4065             : 
    4066          20 :         if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
    4067             :                 bgp_nht_param_prefix = NULL;
    4068             :         else
    4069          20 :                 bgp_nht_param_prefix = p;
    4070             : 
    4071             :         /* AS path loop check. */
    4072          20 :         if (do_loop_check) {
    4073          20 :                 if (aspath_loop_check(attr->aspath, bgp->as) >
    4074          20 :                     peer->allowas_in[afi][safi]) {
    4075           5 :                         peer->stat_pfx_aspath_loop++;
    4076           5 :                         reason = "as-path contains our own AS;";
    4077           5 :                         goto filtered;
    4078             :                 }
    4079             :         }
    4080             : 
    4081             :         /* If we're a CONFED we need to loop check the CONFED ID too */
    4082          15 :         if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) && do_loop_check)
    4083           0 :                 if (aspath_loop_check_confed(attr->aspath, bgp->confed_id) >
    4084           0 :                     peer->allowas_in[afi][safi]) {
    4085           0 :                         peer->stat_pfx_aspath_loop++;
    4086           0 :                         reason = "as-path contains our own confed AS;";
    4087           0 :                         goto filtered;
    4088             :                 }
    4089             : 
    4090             :         /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
    4091             :          * enabled, then take care of that too.
    4092             :          */
    4093          15 :         bool accept_own = false;
    4094             : 
    4095          15 :         if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
    4096           0 :             && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
    4097           0 :                 accept_own =
    4098           0 :                         bgp_accept_own(peer, afi, safi, attr, p, &sub_type);
    4099           0 :                 if (!accept_own) {
    4100           0 :                         peer->stat_pfx_originator_loop++;
    4101           0 :                         reason = "originator is us;";
    4102           0 :                         goto filtered;
    4103             :                 }
    4104             :         }
    4105             : 
    4106             :         /* Route reflector cluster ID check.  */
    4107          15 :         if (bgp_cluster_filter(peer, attr)) {
    4108           0 :                 peer->stat_pfx_cluster_loop++;
    4109           0 :                 reason = "reflected from the same cluster;";
    4110           0 :                 goto filtered;
    4111             :         }
    4112             : 
    4113             :         /* Apply incoming filter.  */
    4114          15 :         if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
    4115           0 :                 peer->stat_pfx_filter++;
    4116           0 :                 reason = "filter;";
    4117           0 :                 goto filtered;
    4118             :         }
    4119             : 
    4120             :         /* RFC 8212 to prevent route leaks.
    4121             :          * This specification intends to improve this situation by requiring the
    4122             :          * explicit configuration of both BGP Import and Export Policies for any
    4123             :          * External BGP (EBGP) session such as customers, peers, or
    4124             :          * confederation boundaries for all enabled address families. Through
    4125             :          * codification of the aforementioned requirement, operators will
    4126             :          * benefit from consistent behavior across different BGP
    4127             :          * implementations.
    4128             :          */
    4129          15 :         if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
    4130           0 :                 if (!bgp_inbound_policy_exists(peer,
    4131             :                                                &peer->filter[afi][safi])) {
    4132           0 :                         reason = "inbound policy missing";
    4133           0 :                         if (monotime_since(&bgp->ebgprequirespolicywarning,
    4134           0 :                                            NULL) > FIFTEENMINUTE2USEC ||
    4135           0 :                             bgp->ebgprequirespolicywarning.tv_sec == 0) {
    4136           0 :                                 zlog_warn(
    4137             :                                         "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
    4138           0 :                                 monotime(&bgp->ebgprequirespolicywarning);
    4139             :                         }
    4140           0 :                         goto filtered;
    4141             :                 }
    4142             : 
    4143             :         /* draft-ietf-idr-deprecate-as-set-confed-set
    4144             :          * Filter routes having AS_SET or AS_CONFED_SET in the path.
    4145             :          * Eventually, This document (if approved) updates RFC 4271
    4146             :          * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
    4147             :          * and obsoletes RFC 6472.
    4148             :          */
    4149          15 :         if (peer->bgp->reject_as_sets)
    4150           0 :                 if (aspath_check_as_sets(attr->aspath)) {
    4151           0 :                         reason =
    4152             :                                 "as-path contains AS_SET or AS_CONFED_SET type;";
    4153           0 :                         goto filtered;
    4154             :                 }
    4155             : 
    4156          15 :         new_attr = *attr;
    4157             : 
    4158             :         /* Apply incoming route-map.
    4159             :          * NB: new_attr may now contain newly allocated values from route-map
    4160             :          * "set"
    4161             :          * commands, so we need bgp_attr_flush in the error paths, until we
    4162             :          * intern
    4163             :          * the attr (which takes over the memory references) */
    4164          15 :         if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
    4165             :                                num_labels, dest)
    4166             :             == RMAP_DENY) {
    4167           4 :                 peer->stat_pfx_filter++;
    4168           4 :                 reason = "route-map;";
    4169           4 :                 bgp_attr_flush(&new_attr);
    4170           4 :                 goto filtered;
    4171             :         }
    4172             : 
    4173          11 :         if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
    4174           0 :                 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
    4175             :                         /* remove from RIB previous entry */
    4176           0 :                         bgp_zebra_withdraw(p, pi, bgp, safi);
    4177             :         }
    4178             : 
    4179          11 :         if (peer->sort == BGP_PEER_EBGP) {
    4180             : 
    4181             :                 /* rfc7999:
    4182             :                  * A BGP speaker receiving an announcement tagged with the
    4183             :                  * BLACKHOLE community SHOULD add the NO_ADVERTISE or
    4184             :                  * NO_EXPORT community as defined in RFC1997, or a
    4185             :                  * similar community, to prevent propagation of the
    4186             :                  * prefix outside the local AS. The community to prevent
    4187             :                  * propagation SHOULD be chosen according to the operator's
    4188             :                  * routing policy.
    4189             :                  */
    4190          11 :                 if (bgp_attr_get_community(&new_attr) &&
    4191           0 :                     community_include(bgp_attr_get_community(&new_attr),
    4192             :                                       COMMUNITY_BLACKHOLE))
    4193           0 :                         bgp_attr_add_no_export_community(&new_attr);
    4194             : 
    4195             :                 /* If we receive the graceful-shutdown community from an eBGP
    4196             :                  * peer we must lower local-preference */
    4197          11 :                 if (bgp_attr_get_community(&new_attr) &&
    4198           0 :                     community_include(bgp_attr_get_community(&new_attr),
    4199             :                                       COMMUNITY_GSHUT)) {
    4200           0 :                         new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
    4201           0 :                         new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
    4202             : 
    4203             :                         /* If graceful-shutdown is configured globally or
    4204             :                          * per neighbor, then add the GSHUT community to
    4205             :                          * all paths received from eBGP peers. */
    4206          11 :                 } else if (bgp_in_graceful_shutdown(peer->bgp) ||
    4207          11 :                            CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_SHUTDOWN))
    4208           0 :                         bgp_attr_add_gshut_community(&new_attr);
    4209             :         }
    4210             : 
    4211             :         /* next hop check.  */
    4212          22 :         if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD) &&
    4213          11 :             bgp_update_martian_nexthop(bgp, afi, safi, type, sub_type,
    4214             :                                        &new_attr, dest)) {
    4215           0 :                 peer->stat_pfx_nh_invalid++;
    4216           0 :                 reason = "martian or self next-hop;";
    4217           0 :                 bgp_attr_flush(&new_attr);
    4218           0 :                 goto filtered;
    4219             :         }
    4220             : 
    4221          11 :         if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
    4222           0 :                 peer->stat_pfx_nh_invalid++;
    4223           0 :                 reason = "self mac;";
    4224           0 :                 bgp_attr_flush(&new_attr);
    4225           0 :                 goto filtered;
    4226             :         }
    4227             : 
    4228          22 :         if (bgp_check_role_applicability(afi, safi) &&
    4229          11 :             bgp_otc_filter(peer, &new_attr)) {
    4230           0 :                 reason = "failing otc validation";
    4231           0 :                 bgp_attr_flush(&new_attr);
    4232           0 :                 goto filtered;
    4233             :         }
    4234             :         /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
    4235             :          * condition :
    4236             :          * Suppress fib is enabled
    4237             :          * BGP_OPT_NO_FIB is not enabled
    4238             :          * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
    4239             :          * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
    4240             :          */
    4241          11 :         if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
    4242           0 :             && (sub_type == BGP_ROUTE_NORMAL)
    4243           0 :             && (!bgp_option_check(BGP_OPT_NO_FIB))
    4244           0 :             && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
    4245           0 :                 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
    4246             : 
    4247             :         /* If neighbor soo is configured, tag all incoming routes with
    4248             :          * this SoO tag and then filter out advertisements in
    4249             :          * subgroup_announce_check() if it matches the configured SoO
    4250             :          * on the other peer.
    4251             :          */
    4252          11 :         if (peer->soo[afi][safi]) {
    4253           0 :                 struct ecommunity *old_ecomm =
    4254           0 :                         bgp_attr_get_ecommunity(&new_attr);
    4255           0 :                 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
    4256           0 :                 struct ecommunity *new_ecomm;
    4257             : 
    4258           0 :                 if (old_ecomm) {
    4259           0 :                         new_ecomm = ecommunity_merge(ecommunity_dup(old_ecomm),
    4260             :                                                      ecomm_soo);
    4261             : 
    4262           0 :                         if (!old_ecomm->refcnt)
    4263           0 :                                 ecommunity_free(&old_ecomm);
    4264             :                 } else {
    4265           0 :                         new_ecomm = ecommunity_dup(ecomm_soo);
    4266             :                 }
    4267             : 
    4268           0 :                 bgp_attr_set_ecommunity(&new_attr, new_ecomm);
    4269             :         }
    4270             : 
    4271          11 :         attr_new = bgp_attr_intern(&new_attr);
    4272             : 
    4273             :         /* If the update is implicit withdraw. */
    4274          11 :         if (pi) {
    4275           0 :                 pi->uptime = monotime(NULL);
    4276           0 :                 same_attr = attrhash_cmp(pi->attr, attr_new);
    4277             : 
    4278           0 :                 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
    4279             : 
    4280             :                 /* Same attribute comes in. */
    4281           0 :                 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
    4282           0 :                     && same_attr
    4283           0 :                     && (!has_valid_label
    4284           0 :                         || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
    4285             :                                   num_labels * sizeof(mpls_label_t))
    4286             :                                    == 0)) {
    4287           0 :                         if (CHECK_FLAG(bgp->af_flags[afi][safi],
    4288             :                                        BGP_CONFIG_DAMPENING)
    4289           0 :                             && peer->sort == BGP_PEER_EBGP
    4290           0 :                             && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
    4291           0 :                                 if (bgp_debug_update(peer, p, NULL, 1)) {
    4292           0 :                                         bgp_debug_rdpfxpath2str(
    4293             :                                                 afi, safi, prd, p, label,
    4294             :                                                 num_labels, addpath_id ? 1 : 0,
    4295             :                                                 addpath_id, evpn, pfx_buf,
    4296             :                                                 sizeof(pfx_buf));
    4297           0 :                                         zlog_debug("%pBP rcvd %s", peer,
    4298             :                                                    pfx_buf);
    4299             :                                 }
    4300             : 
    4301           0 :                                 if (bgp_damp_update(pi, dest, afi, safi)
    4302             :                                     != BGP_DAMP_SUPPRESSED) {
    4303           0 :                                         bgp_aggregate_increment(bgp, p, pi, afi,
    4304             :                                                                 safi);
    4305           0 :                                         bgp_process(bgp, dest, afi, safi);
    4306             :                                 }
    4307             :                         } else /* Duplicate - odd */
    4308             :                         {
    4309           0 :                                 if (bgp_debug_update(peer, p, NULL, 1)) {
    4310           0 :                                         if (!peer->rcvd_attr_printed) {
    4311           0 :                                                 zlog_debug(
    4312             :                                                         "%pBP rcvd UPDATE w/ attr: %s",
    4313             :                                                         peer,
    4314             :                                                         peer->rcvd_attr_str);
    4315           0 :                                                 peer->rcvd_attr_printed = 1;
    4316             :                                         }
    4317             : 
    4318           0 :                                         bgp_debug_rdpfxpath2str(
    4319             :                                                 afi, safi, prd, p, label,
    4320             :                                                 num_labels, addpath_id ? 1 : 0,
    4321             :                                                 addpath_id, evpn, pfx_buf,
    4322             :                                                 sizeof(pfx_buf));
    4323           0 :                                         zlog_debug(
    4324             :                                                 "%pBP rcvd %s...duplicate ignored",
    4325             :                                                 peer, pfx_buf);
    4326             :                                 }
    4327             : 
    4328             :                                 /* graceful restart STALE flag unset. */
    4329           0 :                                 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
    4330           0 :                                         bgp_path_info_unset_flag(
    4331             :                                                 dest, pi, BGP_PATH_STALE);
    4332           0 :                                         bgp_dest_set_defer_flag(dest, false);
    4333           0 :                                         bgp_process(bgp, dest, afi, safi);
    4334             :                                 }
    4335             :                         }
    4336             : 
    4337           0 :                         bgp_dest_unlock_node(dest);
    4338           0 :                         bgp_attr_unintern(&attr_new);
    4339             : 
    4340           0 :                         return;
    4341             :                 }
    4342             : 
    4343             :                 /* Withdraw/Announce before we fully processed the withdraw */
    4344           0 :                 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
    4345           0 :                         if (bgp_debug_update(peer, p, NULL, 1)) {
    4346           0 :                                 bgp_debug_rdpfxpath2str(
    4347             :                                         afi, safi, prd, p, label, num_labels,
    4348             :                                         addpath_id ? 1 : 0, addpath_id, evpn,
    4349             :                                         pfx_buf, sizeof(pfx_buf));
    4350           0 :                                 zlog_debug(
    4351             :                                         "%pBP rcvd %s, flapped quicker than processing",
    4352             :                                         peer, pfx_buf);
    4353             :                         }
    4354             : 
    4355           0 :                         bgp_path_info_restore(dest, pi);
    4356             : 
    4357             :                         /*
    4358             :                          * If the BGP_PATH_REMOVED flag is set, then EVPN
    4359             :                          * routes would have been unimported already when a
    4360             :                          * prior BGP withdraw processing happened. Such routes
    4361             :                          * need to be imported again, so flag accordingly.
    4362             :                          */
    4363           0 :                         force_evpn_import = true;
    4364             :                 } else {
    4365             :                         /* implicit withdraw, decrement aggregate and pcount
    4366             :                          * here. only if update is accepted, they'll increment
    4367             :                          * below.
    4368             :                          */
    4369           0 :                         bgp_aggregate_decrement(bgp, p, pi, afi, safi);
    4370             :                 }
    4371             : 
    4372             :                 /* Received Logging. */
    4373           0 :                 if (bgp_debug_update(peer, p, NULL, 1)) {
    4374           0 :                         bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
    4375             :                                                 num_labels, addpath_id ? 1 : 0,
    4376             :                                                 addpath_id, evpn, pfx_buf,
    4377             :                                                 sizeof(pfx_buf));
    4378           0 :                         zlog_debug("%pBP rcvd %s", peer, pfx_buf);
    4379             :                 }
    4380             : 
    4381             :                 /* graceful restart STALE flag unset. */
    4382           0 :                 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
    4383           0 :                         bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
    4384           0 :                         bgp_dest_set_defer_flag(dest, false);
    4385             :                 }
    4386             : 
    4387             :                 /* The attribute is changed. */
    4388           0 :                 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
    4389             : 
    4390             :                 /* Update bgp route dampening information.  */
    4391           0 :                 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
    4392           0 :                     && peer->sort == BGP_PEER_EBGP) {
    4393             :                         /* This is implicit withdraw so we should update
    4394             :                            dampening
    4395             :                            information.  */
    4396           0 :                         if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
    4397           0 :                                 bgp_damp_withdraw(pi, dest, afi, safi, 1);
    4398             :                 }
    4399             : #ifdef ENABLE_BGP_VNC
    4400           0 :                 if (safi == SAFI_MPLS_VPN) {
    4401           0 :                         struct bgp_dest *pdest = NULL;
    4402           0 :                         struct bgp_table *table = NULL;
    4403             : 
    4404           0 :                         pdest = bgp_node_get(bgp->rib[afi][safi],
    4405             :                                              (struct prefix *)prd);
    4406           0 :                         if (bgp_dest_has_bgp_path_info_data(pdest)) {
    4407           0 :                                 table = bgp_dest_get_bgp_table_info(pdest);
    4408             : 
    4409           0 :                                 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
    4410             :                                         bgp, prd, table, p, pi);
    4411             :                         }
    4412           0 :                         bgp_dest_unlock_node(pdest);
    4413             :                 }
    4414           0 :                 if ((afi == AFI_IP || afi == AFI_IP6)
    4415           0 :                     && (safi == SAFI_UNICAST)) {
    4416           0 :                         if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
    4417             :                                 /*
    4418             :                                  * Implicit withdraw case.
    4419             :                                  */
    4420           0 :                                 ++vnc_implicit_withdraw;
    4421           0 :                                 vnc_import_bgp_del_route(bgp, p, pi);
    4422           0 :                                 vnc_import_bgp_exterior_del_route(bgp, p, pi);
    4423             :                         }
    4424             :                 }
    4425             : #endif
    4426             : 
    4427             :                 /* Special handling for EVPN update of an existing route. If the
    4428             :                  * extended community attribute has changed, we need to
    4429             :                  * un-import
    4430             :                  * the route using its existing extended community. It will be
    4431             :                  * subsequently processed for import with the new extended
    4432             :                  * community.
    4433             :                  */
    4434           0 :                 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
    4435           0 :                     && !same_attr) {
    4436           0 :                         if ((pi->attr->flag
    4437           0 :                              & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
    4438           0 :                             && (attr_new->flag
    4439           0 :                                 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
    4440           0 :                                 int cmp;
    4441             : 
    4442           0 :                                 cmp = ecommunity_cmp(
    4443           0 :                                         bgp_attr_get_ecommunity(pi->attr),
    4444           0 :                                         bgp_attr_get_ecommunity(attr_new));
    4445           0 :                                 if (!cmp) {
    4446           0 :                                         if (bgp_debug_update(peer, p, NULL, 1))
    4447           0 :                                                 zlog_debug(
    4448             :                                                         "Change in EXT-COMM, existing %s new %s",
    4449             :                                                         ecommunity_str(
    4450             :                                                                 bgp_attr_get_ecommunity(
    4451             :                                                                         pi->attr)),
    4452             :                                                         ecommunity_str(
    4453             :                                                                 bgp_attr_get_ecommunity(
    4454             :                                                                         attr_new)));
    4455           0 :                                         if (safi == SAFI_EVPN)
    4456           0 :                                                 bgp_evpn_unimport_route(
    4457             :                                                         bgp, afi, safi, p, pi);
    4458             :                                         else /* SAFI_MPLS_VPN */
    4459           0 :                                                 vpn_leak_to_vrf_withdraw(pi);
    4460             :                                 }
    4461             :                         }
    4462             :                 }
    4463             : 
    4464             :                 /* Update to new attribute.  */
    4465           0 :                 bgp_attr_unintern(&pi->attr);
    4466           0 :                 pi->attr = attr_new;
    4467             : 
    4468             :                 /* Update MPLS label */
    4469           0 :                 if (has_valid_label) {
    4470           0 :                         extra = bgp_path_info_extra_get(pi);
    4471           0 :                         if (extra->label != label) {
    4472           0 :                                 memcpy(&extra->label, label,
    4473             :                                        num_labels * sizeof(mpls_label_t));
    4474           0 :                                 extra->num_labels = num_labels;
    4475             :                         }
    4476           0 :                         if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
    4477           0 :                                 bgp_set_valid_label(&extra->label[0]);
    4478             :                 }
    4479             : 
    4480             :                 /* Update SRv6 SID */
    4481           0 :                 if (attr->srv6_l3vpn) {
    4482           0 :                         extra = bgp_path_info_extra_get(pi);
    4483           0 :                         if (sid_diff(&extra->sid[0].sid,
    4484           0 :                                      &attr->srv6_l3vpn->sid)) {
    4485           0 :                                 sid_copy(&extra->sid[0].sid,
    4486           0 :                                          &attr->srv6_l3vpn->sid);
    4487           0 :                                 extra->num_sids = 1;
    4488             : 
    4489           0 :                                 extra->sid[0].loc_block_len = 0;
    4490           0 :                                 extra->sid[0].loc_node_len = 0;
    4491           0 :                                 extra->sid[0].func_len = 0;
    4492           0 :                                 extra->sid[0].arg_len = 0;
    4493           0 :                                 extra->sid[0].transposition_len = 0;
    4494           0 :                                 extra->sid[0].transposition_offset = 0;
    4495             : 
    4496           0 :                                 if (attr->srv6_l3vpn->loc_block_len != 0) {
    4497           0 :                                         extra->sid[0].loc_block_len =
    4498             :                                                 attr->srv6_l3vpn->loc_block_len;
    4499           0 :                                         extra->sid[0].loc_node_len =
    4500           0 :                                                 attr->srv6_l3vpn->loc_node_len;
    4501           0 :                                         extra->sid[0].func_len =
    4502           0 :                                                 attr->srv6_l3vpn->func_len;
    4503           0 :                                         extra->sid[0].arg_len =
    4504           0 :                                                 attr->srv6_l3vpn->arg_len;
    4505           0 :                                         extra->sid[0].transposition_len =
    4506             :                                                 attr->srv6_l3vpn
    4507           0 :                                                         ->transposition_len;
    4508           0 :                                         extra->sid[0].transposition_offset =
    4509             :                                                 attr->srv6_l3vpn
    4510           0 :                                                         ->transposition_offset;
    4511             :                                 }
    4512             :                         }
    4513           0 :                 } else if (attr->srv6_vpn) {
    4514           0 :                         extra = bgp_path_info_extra_get(pi);
    4515           0 :                         if (sid_diff(&extra->sid[0].sid,
    4516           0 :                                      &attr->srv6_vpn->sid)) {
    4517           0 :                                 sid_copy(&extra->sid[0].sid,
    4518           0 :                                          &attr->srv6_vpn->sid);
    4519           0 :                                 extra->num_sids = 1;
    4520             :                         }
    4521             :                 }
    4522             : 
    4523             : #ifdef ENABLE_BGP_VNC
    4524           0 :                 if ((afi == AFI_IP || afi == AFI_IP6)
    4525           0 :                     && (safi == SAFI_UNICAST)) {
    4526           0 :                         if (vnc_implicit_withdraw) {
    4527             :                                 /*
    4528             :                                  * Add back the route with its new attributes
    4529             :                                  * (e.g., nexthop).
    4530             :                                  * The route is still selected, until the route
    4531             :                                  * selection
    4532             :                                  * queued by bgp_process actually runs. We have
    4533             :                                  * to make this
    4534             :                                  * update to the VNC side immediately to avoid
    4535             :                                  * racing against
    4536             :                                  * configuration changes (e.g., route-map
    4537             :                                  * changes) which
    4538             :                                  * trigger re-importation of the entire RIB.
    4539             :                                  */
    4540           0 :                                 vnc_import_bgp_add_route(bgp, p, pi);
    4541           0 :                                 vnc_import_bgp_exterior_add_route(bgp, p, pi);
    4542             :                         }
    4543             :                 }
    4544             : #endif
    4545             : 
    4546             :                 /* Update bgp route dampening information.  */
    4547           0 :                 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
    4548           0 :                     && peer->sort == BGP_PEER_EBGP) {
    4549             :                         /* Now we do normal update dampening.  */
    4550           0 :                         ret = bgp_damp_update(pi, dest, afi, safi);
    4551           0 :                         if (ret == BGP_DAMP_SUPPRESSED) {
    4552           0 :                                 bgp_dest_unlock_node(dest);
    4553           0 :                                 return;
    4554             :                         }
    4555             :                 }
    4556             : 
    4557             :                 /* Nexthop reachability check - for unicast and
    4558             :                  * labeled-unicast.. */
    4559           0 :                 if (((afi == AFI_IP || afi == AFI_IP6)
    4560           0 :                     && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
    4561           0 :                     || (safi == SAFI_EVPN &&
    4562           0 :                         bgp_evpn_is_prefix_nht_supported(p))) {
    4563           0 :                         if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
    4564           0 :                             && peer->ttl == BGP_DEFAULT_TTL
    4565           0 :                             && !CHECK_FLAG(peer->flags,
    4566             :                                            PEER_FLAG_DISABLE_CONNECTED_CHECK)
    4567           0 :                             && !CHECK_FLAG(bgp->flags,
    4568             :                                            BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
    4569             :                                 connected = 1;
    4570             :                         else
    4571             :                                 connected = 0;
    4572             : 
    4573           0 :                         struct bgp *bgp_nexthop = bgp;
    4574             : 
    4575           0 :                         if (pi->extra && pi->extra->bgp_orig)
    4576           0 :                                 bgp_nexthop = pi->extra->bgp_orig;
    4577             : 
    4578           0 :                         nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
    4579             : 
    4580           0 :                         if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
    4581             :                                                     safi, pi, NULL, connected,
    4582           0 :                                                     bgp_nht_param_prefix) ||
    4583           0 :                             CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
    4584           0 :                                 bgp_path_info_set_flag(dest, pi,
    4585             :                                                        BGP_PATH_VALID);
    4586             :                         else {
    4587           0 :                                 if (BGP_DEBUG(nht, NHT)) {
    4588           0 :                                         zlog_debug("%s(%pI4): NH unresolved",
    4589             :                                                    __func__,
    4590             :                                                    (in_addr_t *)&attr_new->nexthop);
    4591             :                                 }
    4592           0 :                                 bgp_path_info_unset_flag(dest, pi,
    4593             :                                                          BGP_PATH_VALID);
    4594             :                         }
    4595             :                 } else {
    4596           0 :                         if (accept_own)
    4597           0 :                                 bgp_path_info_set_flag(dest, pi,
    4598             :                                                        BGP_PATH_ACCEPT_OWN);
    4599             : 
    4600           0 :                         bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
    4601             :                 }
    4602             : 
    4603             : #ifdef ENABLE_BGP_VNC
    4604           0 :                 if (safi == SAFI_MPLS_VPN) {
    4605           0 :                         struct bgp_dest *pdest = NULL;
    4606           0 :                         struct bgp_table *table = NULL;
    4607             : 
    4608           0 :                         pdest = bgp_node_get(bgp->rib[afi][safi],
    4609             :                                              (struct prefix *)prd);
    4610           0 :                         if (bgp_dest_has_bgp_path_info_data(pdest)) {
    4611           0 :                                 table = bgp_dest_get_bgp_table_info(pdest);
    4612             : 
    4613           0 :                                 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
    4614             :                                         bgp, prd, table, p, pi);
    4615             :                         }
    4616           0 :                         bgp_dest_unlock_node(pdest);
    4617             :                 }
    4618             : #endif
    4619             : 
    4620             :                 /* If this is an EVPN route and some attribute has changed,
    4621             :                  * or we are explicitly told to perform a route import, process
    4622             :                  * route for import. If the extended community has changed, we
    4623             :                  * would
    4624             :                  * have done the un-import earlier and the import would result
    4625             :                  * in the
    4626             :                  * route getting injected into appropriate L2 VNIs. If it is
    4627             :                  * just
    4628             :                  * some other attribute change, the import will result in
    4629             :                  * updating
    4630             :                  * the attributes for the route in the VNI(s).
    4631             :                  */
    4632           0 :                 if (safi == SAFI_EVPN &&
    4633           0 :                     (!same_attr || force_evpn_import) &&
    4634           0 :                     CHECK_FLAG(pi->flags, BGP_PATH_VALID))
    4635           0 :                         bgp_evpn_import_route(bgp, afi, safi, p, pi);
    4636             : 
    4637             :                 /* Process change. */
    4638           0 :                 bgp_aggregate_increment(bgp, p, pi, afi, safi);
    4639             : 
    4640           0 :                 bgp_process(bgp, dest, afi, safi);
    4641           0 :                 bgp_dest_unlock_node(dest);
    4642             : 
    4643           0 :                 if (SAFI_UNICAST == safi
    4644           0 :                     && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
    4645             :                         || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
    4646             : 
    4647           0 :                         vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
    4648             :                 }
    4649           0 :                 if ((SAFI_MPLS_VPN == safi)
    4650           0 :                     && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
    4651           0 :                         leak_success = vpn_leak_to_vrf_update(bgp, pi, prd);
    4652             :                 }
    4653             : 
    4654             : #ifdef ENABLE_BGP_VNC
    4655           0 :                 if (SAFI_MPLS_VPN == safi) {
    4656           0 :                         mpls_label_t label_decoded = decode_label(label);
    4657             : 
    4658           0 :                         rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
    4659             :                                            type, sub_type, &label_decoded);
    4660             :                 }
    4661           0 :                 if (SAFI_ENCAP == safi) {
    4662           0 :                         rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
    4663             :                                            type, sub_type, NULL);
    4664             :                 }
    4665             : #endif
    4666           0 :                 if ((safi == SAFI_MPLS_VPN) &&
    4667           0 :                     !CHECK_FLAG(bgp->af_flags[afi][safi],
    4668           0 :                                 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
    4669             :                     !leak_success) {
    4670           0 :                         bgp_unlink_nexthop(pi);
    4671           0 :                         bgp_path_info_delete(dest, pi);
    4672             :                 }
    4673           0 :                 return;
    4674             :         } // End of implicit withdraw
    4675             : 
    4676             :         /* Received Logging. */
    4677          11 :         if (bgp_debug_update(peer, p, NULL, 1)) {
    4678           0 :                 if (!peer->rcvd_attr_printed) {
    4679           0 :                         zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
    4680             :                                    peer->rcvd_attr_str);
    4681           0 :                         peer->rcvd_attr_printed = 1;
    4682             :                 }
    4683             : 
    4684           0 :                 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
    4685             :                                         addpath_id ? 1 : 0, addpath_id, evpn,
    4686             :                                         pfx_buf, sizeof(pfx_buf));
    4687           0 :                 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
    4688             :         }
    4689             : 
    4690             :         /* Make new BGP info. */
    4691          11 :         new = info_make(type, sub_type, 0, peer, attr_new, dest);
    4692             : 
    4693             :         /* Update MPLS label */
    4694          11 :         if (has_valid_label) {
    4695           0 :                 extra = bgp_path_info_extra_get(new);
    4696           0 :                 if (extra->label != label) {
    4697           0 :                         memcpy(&extra->label, label,
    4698             :                                num_labels * sizeof(mpls_label_t));
    4699           0 :                         extra->num_labels = num_labels;
    4700             :                 }
    4701           0 :                 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
    4702           0 :                         bgp_set_valid_label(&extra->label[0]);
    4703             :         }
    4704             : 
    4705             :         /* Update SRv6 SID */
    4706          11 :         if (safi == SAFI_MPLS_VPN) {
    4707           0 :                 extra = bgp_path_info_extra_get(new);
    4708           0 :                 if (attr->srv6_l3vpn) {
    4709           0 :                         sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
    4710           0 :                         extra->num_sids = 1;
    4711             : 
    4712           0 :                         extra->sid[0].loc_block_len =
    4713           0 :                                 attr->srv6_l3vpn->loc_block_len;
    4714           0 :                         extra->sid[0].loc_node_len =
    4715           0 :                                 attr->srv6_l3vpn->loc_node_len;
    4716           0 :                         extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
    4717           0 :                         extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
    4718           0 :                         extra->sid[0].transposition_len =
    4719           0 :                                 attr->srv6_l3vpn->transposition_len;
    4720           0 :                         extra->sid[0].transposition_offset =
    4721           0 :                                 attr->srv6_l3vpn->transposition_offset;
    4722           0 :                 } else if (attr->srv6_vpn) {
    4723           0 :                         sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
    4724           0 :                         extra->num_sids = 1;
    4725             :                 }
    4726             :         }
    4727             : 
    4728             :         /* Nexthop reachability check. */
    4729          11 :         if (((afi == AFI_IP || afi == AFI_IP6)
    4730          11 :             && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
    4731           0 :             || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
    4732          11 :                 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
    4733          11 :                     && peer->ttl == BGP_DEFAULT_TTL
    4734          11 :                     && !CHECK_FLAG(peer->flags,
    4735             :                                    PEER_FLAG_DISABLE_CONNECTED_CHECK)
    4736          11 :                     && !CHECK_FLAG(bgp->flags,
    4737             :                                    BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
    4738             :                         connected = 1;
    4739             :                 else
    4740             :                         connected = 0;
    4741             : 
    4742          11 :                 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
    4743             : 
    4744          11 :                 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
    4745           0 :                                             connected, bgp_nht_param_prefix) ||
    4746           0 :                     CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
    4747          11 :                         bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
    4748             :                 else {
    4749           0 :                         if (BGP_DEBUG(nht, NHT))
    4750           0 :                                 zlog_debug("%s(%pI4): NH unresolved", __func__,
    4751             :                                            &attr_new->nexthop);
    4752           0 :                         bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
    4753             :                 }
    4754             :         } else {
    4755           0 :                 if (accept_own)
    4756           0 :                         bgp_path_info_set_flag(dest, new, BGP_PATH_ACCEPT_OWN);
    4757             : 
    4758           0 :                 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
    4759             :         }
    4760             : 
    4761             :         /* If maximum prefix count is configured and current prefix
    4762             :          * count exeed it.
    4763             :          */
    4764          11 :         if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
    4765           0 :                 reason = "maximum-prefix overflow";
    4766           0 :                 bgp_attr_flush(&new_attr);
    4767           0 :                 goto filtered;
    4768             :         }
    4769             : 
    4770             :         /* Addpath ID */
    4771          11 :         new->addpath_rx_id = addpath_id;
    4772             : 
    4773             :         /* Increment prefix */
    4774          11 :         bgp_aggregate_increment(bgp, p, new, afi, safi);
    4775             : 
    4776             :         /* Register new BGP information. */
    4777          11 :         bgp_path_info_add(dest, new);
    4778             : 
    4779             :         /* route_node_get lock */
    4780          11 :         bgp_dest_unlock_node(dest);
    4781             : 
    4782             : #ifdef ENABLE_BGP_VNC
    4783          11 :         if (safi == SAFI_MPLS_VPN) {
    4784           0 :                 struct bgp_dest *pdest = NULL;
    4785           0 :                 struct bgp_table *table = NULL;
    4786             : 
    4787           0 :                 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
    4788           0 :                 if (bgp_dest_has_bgp_path_info_data(pdest)) {
    4789           0 :                         table = bgp_dest_get_bgp_table_info(pdest);
    4790             : 
    4791           0 :                         vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
    4792             :                                 bgp, prd, table, p, new);
    4793             :                 }
    4794           0 :                 bgp_dest_unlock_node(pdest);
    4795             :         }
    4796             : #endif
    4797             : 
    4798             :         /* If this is an EVPN route, process for import. */
    4799          11 :         if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
    4800           0 :                 bgp_evpn_import_route(bgp, afi, safi, p, new);
    4801             : 
    4802          11 :         hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
    4803             : 
    4804             :         /* Process change. */
    4805          11 :         bgp_process(bgp, dest, afi, safi);
    4806             : 
    4807          11 :         if (SAFI_UNICAST == safi
    4808          11 :             && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
    4809             :                 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
    4810          11 :                 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
    4811             :         }
    4812          11 :         if ((SAFI_MPLS_VPN == safi)
    4813           0 :             && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
    4814           0 :                 leak_success = vpn_leak_to_vrf_update(bgp, new, prd);
    4815             :         }
    4816             : #ifdef ENABLE_BGP_VNC
    4817           0 :         if (SAFI_MPLS_VPN == safi) {
    4818           0 :                 mpls_label_t label_decoded = decode_label(label);
    4819             : 
    4820           0 :                 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
    4821             :                                    sub_type, &label_decoded);
    4822             :         }
    4823          11 :         if (SAFI_ENCAP == safi) {
    4824           0 :                 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
    4825             :                                    sub_type, NULL);
    4826             :         }
    4827             : #endif
    4828          11 :         if ((safi == SAFI_MPLS_VPN) &&
    4829           0 :             !CHECK_FLAG(bgp->af_flags[afi][safi],
    4830           0 :                         BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
    4831             :             !leak_success) {
    4832           0 :                 bgp_unlink_nexthop(new);
    4833           0 :                 bgp_path_info_delete(dest, new);
    4834             :         }
    4835             : 
    4836             :         return;
    4837             : 
    4838             : /* This BGP update is filtered.  Log the reason then update BGP
    4839             :    entry.  */
    4840           0 : filtered:
    4841           9 :         if (new) {
    4842           0 :                 bgp_unlink_nexthop(new);
    4843           0 :                 bgp_path_info_delete(dest, new);
    4844           0 :                 bgp_path_info_extra_free(&new->extra);
    4845           0 :                 XFREE(MTYPE_BGP_ROUTE, new);
    4846             :         }
    4847             : 
    4848           9 :         hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
    4849             : 
    4850           9 :         if (bgp_debug_update(peer, p, NULL, 1)) {
    4851           0 :                 if (!peer->rcvd_attr_printed) {
    4852           0 :                         zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
    4853             :                                    peer->rcvd_attr_str);
    4854           0 :                         peer->rcvd_attr_printed = 1;
    4855             :                 }
    4856             : 
    4857           0 :                 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
    4858             :                                         addpath_id ? 1 : 0, addpath_id, evpn,
    4859             :                                         pfx_buf, sizeof(pfx_buf));
    4860           0 :                 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
    4861             :                            peer, pfx_buf, reason);
    4862             :         }
    4863             : 
    4864           9 :         if (pi) {
    4865             :                 /* If this is an EVPN route, un-import it as it is now filtered.
    4866             :                  */
    4867           0 :                 if (safi == SAFI_EVPN)
    4868           0 :                         bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
    4869             : 
    4870           0 :                 if (SAFI_UNICAST == safi
    4871           0 :                     && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
    4872             :                         || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
    4873             : 
    4874           0 :                         vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
    4875             :                 }
    4876           0 :                 if ((SAFI_MPLS_VPN == safi)
    4877           0 :                     && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
    4878             : 
    4879           0 :                         vpn_leak_to_vrf_withdraw(pi);
    4880             :                 }
    4881             : 
    4882           0 :                 bgp_rib_remove(dest, pi, peer, afi, safi);
    4883             :         }
    4884             : 
    4885           9 :         bgp_dest_unlock_node(dest);
    4886             : 
    4887             : #ifdef ENABLE_BGP_VNC
    4888             :         /*
    4889             :          * Filtered update is treated as an implicit withdrawal (see
    4890             :          * bgp_rib_remove()
    4891             :          * a few lines above)
    4892             :          */
    4893           9 :         if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
    4894           0 :                 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
    4895             :                                      0);
    4896             :         }
    4897             : #endif
    4898             : 
    4899             :         return;
    4900             : }
    4901             : 
    4902           0 : void bgp_withdraw(struct peer *peer, const struct prefix *p,
    4903             :                   uint32_t addpath_id, struct attr *attr, afi_t afi,
    4904             :                   safi_t safi, int type, int sub_type, struct prefix_rd *prd,
    4905             :                   mpls_label_t *label, uint32_t num_labels,
    4906             :                   struct bgp_route_evpn *evpn)
    4907             : {
    4908           0 :         struct bgp *bgp;
    4909           0 :         char pfx_buf[BGP_PRD_PATH_STRLEN];
    4910           0 :         struct bgp_dest *dest;
    4911           0 :         struct bgp_path_info *pi;
    4912             : 
    4913             : #ifdef ENABLE_BGP_VNC
    4914           0 :         if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
    4915           0 :                 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
    4916             :                                      0);
    4917             :         }
    4918             : #endif
    4919             : 
    4920           0 :         bgp = peer->bgp;
    4921             : 
    4922             :         /* Lookup node. */
    4923           0 :         dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
    4924             : 
    4925             :         /* If peer is soft reconfiguration enabled.  Record input packet for
    4926             :          * further calculation.
    4927             :          *
    4928             :          * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
    4929             :          * routes that are filtered.  This tanks out Quagga RS pretty badly due
    4930             :          * to
    4931             :          * the iteration over all RS clients.
    4932             :          * Since we need to remove the entry from adj_in anyway, do that first
    4933             :          * and
    4934             :          * if there was no entry, we don't need to do anything more.
    4935             :          */
    4936           0 :         if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
    4937           0 :             && peer != bgp->peer_self)
    4938           0 :                 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
    4939           0 :                         peer->stat_pfx_dup_withdraw++;
    4940             : 
    4941           0 :                         if (bgp_debug_update(peer, p, NULL, 1)) {
    4942           0 :                                 bgp_debug_rdpfxpath2str(
    4943             :                                         afi, safi, prd, p, label, num_labels,
    4944             :                                         addpath_id ? 1 : 0, addpath_id, NULL,
    4945             :                                         pfx_buf, sizeof(pfx_buf));
    4946           0 :                                 zlog_debug(
    4947             :                                         "%s withdrawing route %s not in adj-in",
    4948             :                                         peer->host, pfx_buf);
    4949             :                         }
    4950           0 :                         bgp_dest_unlock_node(dest);
    4951           0 :                         return;
    4952             :                 }
    4953             : 
    4954             :         /* Lookup withdrawn route. */
    4955           0 :         for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
    4956           0 :                 if (pi->peer == peer && pi->type == type
    4957           0 :                     && pi->sub_type == sub_type
    4958           0 :                     && pi->addpath_rx_id == addpath_id)
    4959             :                         break;
    4960             : 
    4961             :         /* Logging. */
    4962           0 :         if (bgp_debug_update(peer, p, NULL, 1)) {
    4963           0 :                 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
    4964             :                                         addpath_id ? 1 : 0, addpath_id, NULL,
    4965             :                                         pfx_buf, sizeof(pfx_buf));
    4966           0 :                 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
    4967             :                            pfx_buf);
    4968             :         }
    4969             : 
    4970             :         /* Withdraw specified route from routing table. */
    4971           0 :         if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
    4972           0 :                 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
    4973           0 :                 if (SAFI_UNICAST == safi
    4974           0 :                     && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
    4975             :                         || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
    4976           0 :                         vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
    4977             :                 }
    4978           0 :                 if ((SAFI_MPLS_VPN == safi)
    4979           0 :                     && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
    4980             : 
    4981           0 :                         vpn_leak_to_vrf_withdraw(pi);
    4982             :                 }
    4983           0 :         } else if (bgp_debug_update(peer, p, NULL, 1)) {
    4984           0 :                 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
    4985             :                                         addpath_id ? 1 : 0, addpath_id, NULL,
    4986             :                                         pfx_buf, sizeof(pfx_buf));
    4987           0 :                 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
    4988             :         }
    4989             : 
    4990             :         /* Unlock bgp_node_get() lock. */
    4991           0 :         bgp_dest_unlock_node(dest);
    4992             : 
    4993           0 :         return;
    4994             : }
    4995             : 
    4996           0 : void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
    4997             :                            int withdraw)
    4998             : {
    4999           0 :         struct update_subgroup *subgrp;
    5000           0 :         subgrp = peer_subgroup(peer, afi, safi);
    5001           0 :         subgroup_default_originate(subgrp, withdraw);
    5002           0 : }
    5003             : 
    5004             : 
    5005             : /*
    5006             :  * bgp_stop_announce_route_timer
    5007             :  */
    5008           7 : void bgp_stop_announce_route_timer(struct peer_af *paf)
    5009             : {
    5010           7 :         if (!paf->t_announce_route)
    5011             :                 return;
    5012             : 
    5013           1 :         THREAD_OFF(paf->t_announce_route);
    5014             : }
    5015             : 
    5016             : /*
    5017             :  * bgp_announce_route_timer_expired
    5018             :  *
    5019             :  * Callback that is invoked when the route announcement timer for a
    5020             :  * peer_af expires.
    5021             :  */
    5022           2 : static void bgp_announce_route_timer_expired(struct thread *t)
    5023             : {
    5024           2 :         struct peer_af *paf;
    5025           2 :         struct peer *peer;
    5026             : 
    5027           2 :         paf = THREAD_ARG(t);
    5028           2 :         peer = paf->peer;
    5029             : 
    5030           2 :         if (!peer_established(peer))
    5031             :                 return;
    5032             : 
    5033           2 :         if (!peer->afc_nego[paf->afi][paf->safi])
    5034             :                 return;
    5035             : 
    5036           2 :         peer_af_announce_route(paf, 1);
    5037             : 
    5038             :         /* Notify BGP conditional advertisement scanner percess */
    5039           2 :         peer->advmap_config_change[paf->afi][paf->safi] = true;
    5040             : }
    5041             : 
    5042             : /*
    5043             :  * bgp_announce_route
    5044             :  *
    5045             :  * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
    5046             :  *
    5047             :  * if force is true we will force an update even if the update
    5048             :  * limiting code is attempted to kick in.
    5049             :  */
    5050           3 : void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
    5051             : {
    5052           3 :         struct peer_af *paf;
    5053           3 :         struct update_subgroup *subgrp;
    5054             : 
    5055           3 :         paf = peer_af_find(peer, afi, safi);
    5056           3 :         if (!paf)
    5057             :                 return;
    5058           3 :         subgrp = PAF_SUBGRP(paf);
    5059             : 
    5060             :         /*
    5061             :          * Ignore if subgroup doesn't exist (implies AF is not negotiated)
    5062             :          * or a refresh has already been triggered.
    5063             :          */
    5064           3 :         if (!subgrp || paf->t_announce_route)
    5065             :                 return;
    5066             : 
    5067           3 :         if (force)
    5068           3 :                 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
    5069             : 
    5070             :         /*
    5071             :          * Start a timer to stagger/delay the announce. This serves
    5072             :          * two purposes - announcement can potentially be combined for
    5073             :          * multiple peers and the announcement doesn't happen in the
    5074             :          * vty context.
    5075             :          */
    5076           4 :         thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
    5077             :                               (subgrp->peer_count == 1)
    5078             :                                       ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
    5079             :                                       : BGP_ANNOUNCE_ROUTE_DELAY_MS,
    5080             :                               &paf->t_announce_route);
    5081             : }
    5082             : 
    5083             : /*
    5084             :  * Announce routes from all AF tables to a peer.
    5085             :  *
    5086             :  * This should ONLY be called when there is a need to refresh the
    5087             :  * routes to the peer based on a policy change for this peer alone
    5088             :  * or a route refresh request received from the peer.
    5089             :  * The operation will result in splitting the peer from its existing
    5090             :  * subgroups and putting it in new subgroups.
    5091             :  */
    5092           0 : void bgp_announce_route_all(struct peer *peer)
    5093             : {
    5094           0 :         afi_t afi;
    5095           0 :         safi_t safi;
    5096             : 
    5097           0 :         FOREACH_AFI_SAFI (afi, safi)
    5098           0 :                 bgp_announce_route(peer, afi, safi, false);
    5099           0 : }
    5100             : 
    5101             : /* Flag or unflag bgp_dest to determine whether it should be treated by
    5102             :  * bgp_soft_reconfig_table_task.
    5103             :  * Flag if flag is true. Unflag if flag is false.
    5104             :  */
    5105           0 : static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
    5106             : {
    5107           0 :         struct bgp_dest *dest;
    5108           0 :         struct bgp_adj_in *ain;
    5109             : 
    5110           0 :         if (!table)
    5111             :                 return;
    5112             : 
    5113           0 :         for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
    5114           0 :                 for (ain = dest->adj_in; ain; ain = ain->next) {
    5115           0 :                         if (ain->peer != NULL)
    5116             :                                 break;
    5117             :                 }
    5118           0 :                 if (flag && ain != NULL && ain->peer != NULL)
    5119           0 :                         SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
    5120             :                 else
    5121           0 :                         UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
    5122             :         }
    5123             : }
    5124             : 
    5125           0 : static void bgp_soft_reconfig_table_update(struct peer *peer,
    5126             :                                            struct bgp_dest *dest,
    5127             :                                            struct bgp_adj_in *ain, afi_t afi,
    5128             :                                            safi_t safi, struct prefix_rd *prd)
    5129             : {
    5130           0 :         struct bgp_path_info *pi;
    5131           0 :         uint32_t num_labels = 0;
    5132           0 :         mpls_label_t *label_pnt = NULL;
    5133           0 :         struct bgp_route_evpn evpn;
    5134             : 
    5135           0 :         for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
    5136           0 :                 if (pi->peer == peer)
    5137             :                         break;
    5138             : 
    5139           0 :         if (pi && pi->extra)
    5140           0 :                 num_labels = pi->extra->num_labels;
    5141           0 :         if (num_labels)
    5142           0 :                 label_pnt = &pi->extra->label[0];
    5143           0 :         if (pi)
    5144           0 :                 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
    5145             :                        sizeof(evpn));
    5146             :         else
    5147           0 :                 memset(&evpn, 0, sizeof(evpn));
    5148             : 
    5149           0 :         bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
    5150             :                    ain->attr, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, prd,
    5151             :                    label_pnt, num_labels, 1, &evpn);
    5152           0 : }
    5153             : 
    5154           0 : static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
    5155             :                                     struct bgp_table *table,
    5156             :                                     struct prefix_rd *prd)
    5157             : {
    5158           0 :         struct bgp_dest *dest;
    5159           0 :         struct bgp_adj_in *ain;
    5160             : 
    5161           0 :         if (!table)
    5162           0 :                 table = peer->bgp->rib[afi][safi];
    5163             : 
    5164           0 :         for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
    5165           0 :                 for (ain = dest->adj_in; ain; ain = ain->next) {
    5166           0 :                         if (ain->peer != peer)
    5167           0 :                                 continue;
    5168             : 
    5169           0 :                         bgp_soft_reconfig_table_update(peer, dest, ain, afi,
    5170             :                                                        safi, prd);
    5171             :                 }
    5172           0 : }
    5173             : 
    5174             : /* Do soft reconfig table per bgp table.
    5175             :  * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
    5176             :  * when BGP_NODE_SOFT_RECONFIG is set,
    5177             :  * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
    5178             :  * Schedule a new thread to continue the job.
    5179             :  * Without splitting the full job into several part,
    5180             :  * vtysh waits for the job to finish before responding to a BGP command
    5181             :  */
    5182           0 : static void bgp_soft_reconfig_table_task(struct thread *thread)
    5183             : {
    5184           0 :         uint32_t iter, max_iter;
    5185           0 :         struct bgp_dest *dest;
    5186           0 :         struct bgp_adj_in *ain;
    5187           0 :         struct peer *peer;
    5188           0 :         struct bgp_table *table;
    5189           0 :         struct prefix_rd *prd;
    5190           0 :         struct listnode *node, *nnode;
    5191             : 
    5192           0 :         table = THREAD_ARG(thread);
    5193           0 :         prd = NULL;
    5194             : 
    5195           0 :         max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
    5196           0 :         if (table->soft_reconfig_init) {
    5197             :                 /* first call of the function with a new srta structure.
    5198             :                  * Don't do any treatment this time on nodes
    5199             :                  * in order vtysh to respond quickly
    5200             :                  */
    5201           0 :                 max_iter = 0;
    5202             :         }
    5203             : 
    5204           0 :         for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
    5205           0 :              dest = bgp_route_next(dest)) {
    5206           0 :                 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
    5207           0 :                         continue;
    5208             : 
    5209           0 :                 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
    5210             : 
    5211           0 :                 for (ain = dest->adj_in; ain; ain = ain->next) {
    5212           0 :                         for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
    5213             :                                                nnode, peer)) {
    5214           0 :                                 if (ain->peer != peer)
    5215           0 :                                         continue;
    5216             : 
    5217           0 :                                 bgp_soft_reconfig_table_update(
    5218             :                                         peer, dest, ain, table->afi,
    5219             :                                         table->safi, prd);
    5220           0 :                                 iter++;
    5221             :                         }
    5222             :                 }
    5223             :         }
    5224             : 
    5225             :         /* we're either starting the initial iteration,
    5226             :          * or we're going to continue an ongoing iteration
    5227             :          */
    5228           0 :         if (dest || table->soft_reconfig_init) {
    5229           0 :                 table->soft_reconfig_init = false;
    5230           0 :                 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
    5231             :                                  table, 0, &table->soft_reconfig_thread);
    5232           0 :                 return;
    5233             :         }
    5234             :         /* we're done, clean up the background iteration context info and
    5235             :         schedule route annoucement
    5236             :         */
    5237           0 :         for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
    5238           0 :                 listnode_delete(table->soft_reconfig_peers, peer);
    5239           0 :                 bgp_announce_route(peer, table->afi, table->safi, false);
    5240             :         }
    5241             : 
    5242           0 :         list_delete(&table->soft_reconfig_peers);
    5243             : }
    5244             : 
    5245             : 
    5246             : /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
    5247             :  * and peer.
    5248             :  * - bgp cannot be NULL
    5249             :  * - if table and peer are NULL, cancel all threads within the bgp instance
    5250             :  * - if table is NULL and peer is not,
    5251             :  * remove peer in all threads within the bgp instance
    5252             :  * - if peer is NULL, cancel all threads matching table within the bgp instance
    5253             :  */
    5254          20 : void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
    5255             :                                          const struct bgp_table *table,
    5256             :                                          const struct peer *peer)
    5257             : {
    5258          20 :         struct peer *npeer;
    5259          20 :         struct listnode *node, *nnode;
    5260          20 :         int afi, safi;
    5261          20 :         struct bgp_table *ntable;
    5262             : 
    5263          20 :         if (!bgp)
    5264             :                 return;
    5265             : 
    5266         500 :         FOREACH_AFI_SAFI (afi, safi) {
    5267         420 :                 ntable = bgp->rib[afi][safi];
    5268         420 :                 if (!ntable)
    5269           0 :                         continue;
    5270         420 :                 if (table && table != ntable)
    5271         140 :                         continue;
    5272             : 
    5273         560 :                 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
    5274             :                                        npeer)) {
    5275           0 :                         if (peer && peer != npeer)
    5276           0 :                                 continue;
    5277           0 :                         listnode_delete(ntable->soft_reconfig_peers, npeer);
    5278             :                 }
    5279             : 
    5280         280 :                 if (!ntable->soft_reconfig_peers
    5281           0 :                     || !list_isempty(ntable->soft_reconfig_peers))
    5282         280 :                         continue;
    5283             : 
    5284           0 :                 list_delete(&ntable->soft_reconfig_peers);
    5285           0 :                 bgp_soft_reconfig_table_flag(ntable, false);
    5286         420 :                 THREAD_OFF(ntable->soft_reconfig_thread);
    5287             :         }
    5288             : }
    5289             : 
    5290             : /*
    5291             :  * Returns false if the peer is not configured for soft reconfig in
    5292             :  */
    5293           0 : bool bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
    5294             : {
    5295           0 :         struct bgp_dest *dest;
    5296           0 :         struct bgp_table *table;
    5297           0 :         struct listnode *node, *nnode;
    5298           0 :         struct peer *npeer;
    5299           0 :         struct peer_af *paf;
    5300             : 
    5301           0 :         if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
    5302             :                 return false;
    5303             : 
    5304           0 :         if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
    5305           0 :             && (safi != SAFI_EVPN)) {
    5306           0 :                 table = peer->bgp->rib[afi][safi];
    5307           0 :                 if (!table)
    5308             :                         return true;
    5309             : 
    5310           0 :                 table->soft_reconfig_init = true;
    5311             : 
    5312           0 :                 if (!table->soft_reconfig_peers)
    5313           0 :                         table->soft_reconfig_peers = list_new();
    5314           0 :                 npeer = NULL;
    5315             :                 /* add peer to the table soft_reconfig_peers if not already
    5316             :                  * there
    5317             :                  */
    5318           0 :                 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
    5319             :                                        npeer)) {
    5320           0 :                         if (peer == npeer)
    5321             :                                 break;
    5322             :                 }
    5323           0 :                 if (peer != npeer)
    5324           0 :                         listnode_add(table->soft_reconfig_peers, peer);
    5325             : 
    5326             :                 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
    5327             :                  * on table would start back at the beginning.
    5328             :                  */
    5329           0 :                 bgp_soft_reconfig_table_flag(table, true);
    5330             : 
    5331           0 :                 if (!table->soft_reconfig_thread)
    5332           0 :                         thread_add_event(bm->master,
    5333             :                                          bgp_soft_reconfig_table_task, table, 0,
    5334             :                                          &table->soft_reconfig_thread);
    5335             :                 /* Cancel bgp_announce_route_timer_expired threads.
    5336             :                  * bgp_announce_route_timer_expired threads have been scheduled
    5337             :                  * to announce routes as soon as the soft_reconfigure process
    5338             :                  * finishes.
    5339             :                  * In this case, soft_reconfigure is also scheduled by using
    5340             :                  * a thread but is planned after the
    5341             :                  * bgp_announce_route_timer_expired threads. It means that,
    5342             :                  * without cancelling the threads, the route announcement task
    5343             :                  * would run before the soft reconfiguration one. That would
    5344             :                  * useless and would block vtysh during several seconds. Route
    5345             :                  * announcements are rescheduled as soon as the soft_reconfigure
    5346             :                  * process finishes.
    5347             :                  */
    5348           0 :                 paf = peer_af_find(peer, afi, safi);
    5349           0 :                 if (paf)
    5350           0 :                         bgp_stop_announce_route_timer(paf);
    5351             :         } else
    5352           0 :                 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
    5353           0 :                      dest = bgp_route_next(dest)) {
    5354           0 :                         table = bgp_dest_get_bgp_table_info(dest);
    5355             : 
    5356           0 :                         if (table == NULL)
    5357           0 :                                 continue;
    5358             : 
    5359           0 :                         const struct prefix *p = bgp_dest_get_prefix(dest);
    5360           0 :                         struct prefix_rd prd;
    5361             : 
    5362           0 :                         prd.family = AF_UNSPEC;
    5363           0 :                         prd.prefixlen = 64;
    5364           0 :                         memcpy(&prd.val, p->u.val, 8);
    5365             : 
    5366           0 :                         bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
    5367             :                 }
    5368             : 
    5369             :         return true;
    5370             : }
    5371             : 
    5372             : 
    5373             : struct bgp_clear_node_queue {
    5374             :         struct bgp_dest *dest;
    5375             : };
    5376             : 
    5377           7 : static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
    5378             : {
    5379           7 :         struct bgp_clear_node_queue *cnq = data;
    5380           7 :         struct bgp_dest *dest = cnq->dest;
    5381           7 :         struct peer *peer = wq->spec.data;
    5382           7 :         struct bgp_path_info *pi;
    5383           7 :         struct bgp *bgp;
    5384           7 :         afi_t afi = bgp_dest_table(dest)->afi;
    5385           7 :         safi_t safi = bgp_dest_table(dest)->safi;
    5386             : 
    5387           7 :         assert(dest && peer);
    5388           7 :         bgp = peer->bgp;
    5389             : 
    5390             :         /* It is possible that we have multiple paths for a prefix from a peer
    5391             :          * if that peer is using AddPath.
    5392             :          */
    5393          20 :         for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
    5394          13 :                 if (pi->peer != peer)
    5395           6 :                         continue;
    5396             : 
    5397             :                 /* graceful restart STALE flag set. */
    5398           7 :                 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
    5399           0 :                       && peer->nsf[afi][safi])
    5400           7 :                      || CHECK_FLAG(peer->af_sflags[afi][safi],
    5401             :                                    PEER_STATUS_ENHANCED_REFRESH))
    5402             :                     && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
    5403           0 :                     && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
    5404          13 :                         bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
    5405             :                 else {
    5406             :                         /* If this is an EVPN route, process for
    5407             :                          * un-import. */
    5408           7 :                         if (safi == SAFI_EVPN)
    5409           0 :                                 bgp_evpn_unimport_route(
    5410             :                                         bgp, afi, safi,
    5411             :                                         bgp_dest_get_prefix(dest), pi);
    5412             :                         /* Handle withdraw for VRF route-leaking and L3VPN */
    5413           7 :                         if (SAFI_UNICAST == safi
    5414           7 :                             && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
    5415             :                                 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
    5416           7 :                                 vpn_leak_from_vrf_withdraw(bgp_get_default(),
    5417             :                                                            bgp, pi);
    5418             :                         }
    5419           7 :                         if (SAFI_MPLS_VPN == safi &&
    5420           0 :                             bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
    5421           0 :                                 vpn_leak_to_vrf_withdraw(pi);
    5422             :                         }
    5423             : 
    5424           7 :                         bgp_rib_remove(dest, pi, peer, afi, safi);
    5425             :                 }
    5426             :         }
    5427           7 :         return WQ_SUCCESS;
    5428             : }
    5429             : 
    5430           7 : static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
    5431             : {
    5432           7 :         struct bgp_clear_node_queue *cnq = data;
    5433           7 :         struct bgp_dest *dest = cnq->dest;
    5434           7 :         struct bgp_table *table = bgp_dest_table(dest);
    5435             : 
    5436           7 :         bgp_dest_unlock_node(dest);
    5437           7 :         bgp_table_unlock(table);
    5438           7 :         XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
    5439           7 : }
    5440             : 
    5441           2 : static void bgp_clear_node_complete(struct work_queue *wq)
    5442             : {
    5443           2 :         struct peer *peer = wq->spec.data;
    5444             : 
    5445             :         /* Tickle FSM to start moving again */
    5446           2 :         BGP_EVENT_ADD(peer, Clearing_Completed);
    5447             : 
    5448           2 :         peer_unlock(peer); /* bgp_clear_route */
    5449           2 : }
    5450             : 
    5451          10 : static void bgp_clear_node_queue_init(struct peer *peer)
    5452             : {
    5453          10 :         char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
    5454             : 
    5455          10 :         snprintf(wname, sizeof(wname), "clear %s", peer->host);
    5456             : #undef CLEAR_QUEUE_NAME_LEN
    5457             : 
    5458          10 :         peer->clear_node_queue = work_queue_new(bm->master, wname);
    5459          10 :         peer->clear_node_queue->spec.hold = 10;
    5460          10 :         peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
    5461          10 :         peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
    5462          10 :         peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
    5463          10 :         peer->clear_node_queue->spec.max_retries = 0;
    5464             : 
    5465             :         /* we only 'lock' this peer reference when the queue is actually active
    5466             :          */
    5467          10 :         peer->clear_node_queue->spec.data = peer;
    5468          10 : }
    5469             : 
    5470         144 : static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
    5471             :                                   struct bgp_table *table)
    5472             : {
    5473         144 :         struct bgp_dest *dest;
    5474         144 :         int force = peer->bgp->process_queue ? 0 : 1;
    5475             : 
    5476         144 :         if (!table)
    5477         144 :                 table = peer->bgp->rib[afi][safi];
    5478             : 
    5479             :         /* If still no table => afi/safi isn't configured at all or smth. */
    5480         144 :         if (!table)
    5481             :                 return;
    5482             : 
    5483         316 :         for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
    5484          28 :                 struct bgp_path_info *pi, *next;
    5485          28 :                 struct bgp_adj_in *ain;
    5486          28 :                 struct bgp_adj_in *ain_next;
    5487             : 
    5488             :                 /* XXX:TODO: This is suboptimal, every non-empty route_node is
    5489             :                  * queued for every clearing peer, regardless of whether it is
    5490             :                  * relevant to the peer at hand.
    5491             :                  *
    5492             :                  * Overview: There are 3 different indices which need to be
    5493             :                  * scrubbed, potentially, when a peer is removed:
    5494             :                  *
    5495             :                  * 1 peer's routes visible via the RIB (ie accepted routes)
    5496             :                  * 2 peer's routes visible by the (optional) peer's adj-in index
    5497             :                  * 3 other routes visible by the peer's adj-out index
    5498             :                  *
    5499             :                  * 3 there is no hurry in scrubbing, once the struct peer is
    5500             :                  * removed from bgp->peer, we could just GC such deleted peer's
    5501             :                  * adj-outs at our leisure.
    5502             :                  *
    5503             :                  * 1 and 2 must be 'scrubbed' in some way, at least made
    5504             :                  * invisible via RIB index before peer session is allowed to be
    5505             :                  * brought back up. So one needs to know when such a 'search' is
    5506             :                  * complete.
    5507             :                  *
    5508             :                  * Ideally:
    5509             :                  *
    5510             :                  * - there'd be a single global queue or a single RIB walker
    5511             :                  * - rather than tracking which route_nodes still need to be
    5512             :                  *   examined on a peer basis, we'd track which peers still
    5513             :                  *   aren't cleared
    5514             :                  *
    5515             :                  * Given that our per-peer prefix-counts now should be reliable,
    5516             :                  * this may actually be achievable. It doesn't seem to be a huge
    5517             :                  * problem at this time,
    5518             :                  *
    5519             :                  * It is possible that we have multiple paths for a prefix from
    5520             :                  * a peer
    5521             :                  * if that peer is using AddPath.
    5522             :                  */
    5523          28 :                 ain = dest->adj_in;
    5524          28 :                 while (ain) {
    5525           0 :                         ain_next = ain->next;
    5526             : 
    5527           0 :                         if (ain->peer == peer)
    5528           0 :                                 bgp_adj_in_remove(dest, ain);
    5529             : 
    5530             :                         ain = ain_next;
    5531             :                 }
    5532             : 
    5533          36 :                 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
    5534          19 :                         next = pi->next;
    5535          19 :                         if (pi->peer != peer)
    5536           8 :                                 continue;
    5537             : 
    5538          11 :                         if (force)
    5539           0 :                                 bgp_path_info_reap(dest, pi);
    5540             :                         else {
    5541          11 :                                 struct bgp_clear_node_queue *cnq;
    5542             : 
    5543             :                                 /* both unlocked in bgp_clear_node_queue_del */
    5544          11 :                                 bgp_table_lock(bgp_dest_table(dest));
    5545          11 :                                 bgp_dest_lock_node(dest);
    5546          11 :                                 cnq = XCALLOC(
    5547             :                                         MTYPE_BGP_CLEAR_NODE_QUEUE,
    5548             :                                         sizeof(struct bgp_clear_node_queue));
    5549          11 :                                 cnq->dest = dest;
    5550          11 :                                 work_queue_add(peer->clear_node_queue, cnq);
    5551          11 :                                 break;
    5552             :                         }
    5553             :                 }
    5554             :         }
    5555             :         return;
    5556             : }
    5557             : 
    5558         252 : void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
    5559             : {
    5560         252 :         struct bgp_dest *dest;
    5561         252 :         struct bgp_table *table;
    5562             : 
    5563         252 :         if (peer->clear_node_queue == NULL)
    5564          10 :                 bgp_clear_node_queue_init(peer);
    5565             : 
    5566             :         /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
    5567             :          * Idle until it receives a Clearing_Completed event. This protects
    5568             :          * against peers which flap faster than we can we clear, which could
    5569             :          * lead to:
    5570             :          *
    5571             :          * a) race with routes from the new session being installed before
    5572             :          *    clear_route_node visits the node (to delete the route of that
    5573             :          *    peer)
    5574             :          * b) resource exhaustion, clear_route_node likely leads to an entry
    5575             :          *    on the process_main queue. Fast-flapping could cause that queue
    5576             :          *    to grow and grow.
    5577             :          */
    5578             : 
    5579             :         /* lock peer in assumption that clear-node-queue will get nodes; if so,
    5580             :          * the unlock will happen upon work-queue completion; other wise, the
    5581             :          * unlock happens at the end of this function.
    5582             :          */
    5583         252 :         if (!peer->clear_node_queue->thread)
    5584         192 :                 peer_lock(peer);
    5585             : 
    5586         252 :         if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
    5587         144 :                 bgp_clear_route_table(peer, afi, safi, NULL);
    5588             :         else
    5589         216 :                 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
    5590           0 :                      dest = bgp_route_next(dest)) {
    5591           0 :                         table = bgp_dest_get_bgp_table_info(dest);
    5592           0 :                         if (!table)
    5593           0 :                                 continue;
    5594             : 
    5595           0 :                         bgp_clear_route_table(peer, afi, safi, table);
    5596             :                 }
    5597             : 
    5598             :         /* unlock if no nodes got added to the clear-node-queue. */
    5599         252 :         if (!peer->clear_node_queue->thread)
    5600         189 :                 peer_unlock(peer);
    5601         252 : }
    5602             : 
    5603          12 : void bgp_clear_route_all(struct peer *peer)
    5604             : {
    5605          12 :         afi_t afi;
    5606          12 :         safi_t safi;
    5607             : 
    5608         300 :         FOREACH_AFI_SAFI (afi, safi)
    5609         252 :                 bgp_clear_route(peer, afi, safi);
    5610             : 
    5611             : #ifdef ENABLE_BGP_VNC
    5612          12 :         rfapiProcessPeerDown(peer);
    5613             : #endif
    5614          12 : }
    5615             : 
    5616           0 : void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
    5617             : {
    5618           0 :         struct bgp_table *table;
    5619           0 :         struct bgp_dest *dest;
    5620           0 :         struct bgp_adj_in *ain;
    5621           0 :         struct bgp_adj_in *ain_next;
    5622             : 
    5623           0 :         table = peer->bgp->rib[afi][safi];
    5624             : 
    5625             :         /* It is possible that we have multiple paths for a prefix from a peer
    5626             :          * if that peer is using AddPath.
    5627             :          */
    5628           0 :         for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
    5629           0 :                 ain = dest->adj_in;
    5630             : 
    5631           0 :                 while (ain) {
    5632           0 :                         ain_next = ain->next;
    5633             : 
    5634           0 :                         if (ain->peer == peer)
    5635           0 :                                 bgp_adj_in_remove(dest, ain);
    5636             : 
    5637             :                         ain = ain_next;
    5638             :                 }
    5639             :         }
    5640           0 : }
    5641             : 
    5642             : /* If any of the routes from the peer have been marked with the NO_LLGR
    5643             :  * community, either as sent by the peer, or as the result of a configured
    5644             :  * policy, they MUST NOT be retained, but MUST be removed as per the normal
    5645             :  * operation of [RFC4271].
    5646             :  */
    5647           0 : void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
    5648             : {
    5649           0 :         struct bgp_dest *dest;
    5650           0 :         struct bgp_path_info *pi;
    5651           0 :         struct bgp_table *table;
    5652             : 
    5653           0 :         if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
    5654           0 :                 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
    5655           0 :                      dest = bgp_route_next(dest)) {
    5656           0 :                         struct bgp_dest *rm;
    5657             : 
    5658             :                         /* look for neighbor in tables */
    5659           0 :                         table = bgp_dest_get_bgp_table_info(dest);
    5660           0 :                         if (!table)
    5661           0 :                                 continue;
    5662             : 
    5663           0 :                         for (rm = bgp_table_top(table); rm;
    5664           0 :                              rm = bgp_route_next(rm))
    5665           0 :                                 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
    5666           0 :                                      pi = pi->next) {
    5667           0 :                                         if (pi->peer != peer)
    5668           0 :                                                 continue;
    5669           0 :                                         if (CHECK_FLAG(
    5670             :                                                     peer->af_sflags[afi][safi],
    5671           0 :                                                     PEER_STATUS_LLGR_WAIT) &&
    5672           0 :                                             bgp_attr_get_community(pi->attr) &&
    5673           0 :                                             !community_include(
    5674             :                                                     bgp_attr_get_community(
    5675           0 :                                                             pi->attr),
    5676             :                                                     COMMUNITY_NO_LLGR))
    5677           0 :                                                 continue;
    5678           0 :                                         if (!CHECK_FLAG(pi->flags,
    5679             :                                                         BGP_PATH_STALE))
    5680           0 :                                                 continue;
    5681             : 
    5682             :                                         /*
    5683             :                                          * If this is VRF leaked route
    5684             :                                          * process for withdraw.
    5685             :                                          */
    5686           0 :                                         if (pi->sub_type ==
    5687           0 :                                                     BGP_ROUTE_IMPORTED &&
    5688           0 :                                             peer->bgp->inst_type ==
    5689             :                                                     BGP_INSTANCE_TYPE_DEFAULT)
    5690           0 :                                                 vpn_leak_to_vrf_withdraw(pi);
    5691             : 
    5692           0 :                                         bgp_rib_remove(rm, pi, peer, afi, safi);
    5693           0 :                                         break;
    5694             :                                 }
    5695             :                 }
    5696             :         } else {
    5697           0 :                 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
    5698           0 :                      dest = bgp_route_next(dest))
    5699           0 :                         for (pi = bgp_dest_get_bgp_path_info(dest); pi;
    5700           0 :                              pi = pi->next) {
    5701           0 :                                 if (pi->peer != peer)
    5702           0 :                                         continue;
    5703           0 :                                 if (CHECK_FLAG(peer->af_sflags[afi][safi],
    5704           0 :                                                PEER_STATUS_LLGR_WAIT) &&
    5705           0 :                                     bgp_attr_get_community(pi->attr) &&
    5706           0 :                                     !community_include(
    5707           0 :                                             bgp_attr_get_community(pi->attr),
    5708             :                                             COMMUNITY_NO_LLGR))
    5709           0 :                                         continue;
    5710           0 :                                 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
    5711           0 :                                         continue;
    5712           0 :                                 if (safi == SAFI_UNICAST &&
    5713           0 :                                     (peer->bgp->inst_type ==
    5714             :                                              BGP_INSTANCE_TYPE_VRF ||
    5715             :                                      peer->bgp->inst_type ==
    5716             :                                              BGP_INSTANCE_TYPE_DEFAULT))
    5717           0 :                                         vpn_leak_from_vrf_withdraw(
    5718             :                                                 bgp_get_default(), peer->bgp,
    5719             :                                                 pi);
    5720             : 
    5721           0 :                                 bgp_rib_remove(dest, pi, peer, afi, safi);
    5722           0 :                                 break;
    5723             :                         }
    5724             :         }
    5725           0 : }
    5726             : 
    5727           1 : void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
    5728             : {
    5729           1 :         struct bgp_dest *dest, *ndest;
    5730           1 :         struct bgp_path_info *pi;
    5731           1 :         struct bgp_table *table;
    5732             : 
    5733           1 :         if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
    5734           0 :                 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
    5735           0 :                      dest = bgp_route_next(dest)) {
    5736           0 :                         table = bgp_dest_get_bgp_table_info(dest);
    5737           0 :                         if (!table)
    5738           0 :                                 continue;
    5739             : 
    5740           0 :                         for (ndest = bgp_table_top(table); ndest;
    5741           0 :                              ndest = bgp_route_next(ndest)) {
    5742           0 :                                 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
    5743           0 :                                      pi = pi->next) {
    5744           0 :                                         if (pi->peer != peer)
    5745           0 :                                                 continue;
    5746             : 
    5747           0 :                                         if ((CHECK_FLAG(
    5748             :                                                     peer->af_sflags[afi][safi],
    5749             :                                                     PEER_STATUS_ENHANCED_REFRESH))
    5750             :                                             && !CHECK_FLAG(pi->flags,
    5751             :                                                            BGP_PATH_STALE)
    5752           0 :                                             && !CHECK_FLAG(
    5753             :                                                        pi->flags,
    5754             :                                                        BGP_PATH_UNUSEABLE)) {
    5755           0 :                                                 if (bgp_debug_neighbor_events(
    5756             :                                                             peer))
    5757           0 :                                                         zlog_debug(
    5758             :                                                                 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
    5759             :                                                                 peer,
    5760             :                                                                 afi2str(afi),
    5761             :                                                                 safi2str(safi),
    5762             :                                                                 bgp_dest_get_prefix(
    5763             :                                                                         ndest));
    5764             : 
    5765           0 :                                                 bgp_path_info_set_flag(
    5766             :                                                         ndest, pi,
    5767             :                                                         BGP_PATH_STALE);
    5768             :                                         }
    5769             :                                 }
    5770             :                         }
    5771             :                 }
    5772             :         } else {
    5773           2 :                 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
    5774           0 :                      dest = bgp_route_next(dest)) {
    5775           0 :                         for (pi = bgp_dest_get_bgp_path_info(dest); pi;
    5776           0 :                              pi = pi->next) {
    5777           0 :                                 if (pi->peer != peer)
    5778           0 :                                         continue;
    5779             : 
    5780           0 :                                 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
    5781             :                                                 PEER_STATUS_ENHANCED_REFRESH))
    5782             :                                     && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
    5783           0 :                                     && !CHECK_FLAG(pi->flags,
    5784             :                                                    BGP_PATH_UNUSEABLE)) {
    5785           0 :                                         if (bgp_debug_neighbor_events(peer))
    5786           0 :                                                 zlog_debug(
    5787             :                                                         "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
    5788             :                                                         peer, afi2str(afi),
    5789             :                                                         safi2str(safi),
    5790             :                                                         bgp_dest_get_prefix(
    5791             :                                                                 dest));
    5792             : 
    5793           0 :                                         bgp_path_info_set_flag(dest, pi,
    5794             :                                                                BGP_PATH_STALE);
    5795             :                                 }
    5796             :                         }
    5797             :                 }
    5798             :         }
    5799           1 : }
    5800             : 
    5801           0 : bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
    5802             : {
    5803           0 :         if (peer->sort == BGP_PEER_IBGP)
    5804             :                 return true;
    5805             : 
    5806           0 :         if (peer->sort == BGP_PEER_EBGP
    5807           0 :             && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
    5808           0 :                 || FILTER_LIST_OUT_NAME(filter)
    5809           0 :                 || DISTRIBUTE_OUT_NAME(filter)))
    5810           0 :                 return true;
    5811             :         return false;
    5812             : }
    5813             : 
    5814           0 : bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
    5815             : {
    5816           0 :         if (peer->sort == BGP_PEER_IBGP)
    5817             :                 return true;
    5818             : 
    5819           0 :         if (peer->sort == BGP_PEER_EBGP
    5820           0 :             && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
    5821           0 :                 || FILTER_LIST_IN_NAME(filter)
    5822           0 :                 || DISTRIBUTE_IN_NAME(filter)))
    5823           0 :                 return true;
    5824             :         return false;
    5825             : }
    5826             : 
    5827           6 : static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
    5828             :                               safi_t safi)
    5829             : {
    5830           6 :         struct bgp_dest *dest;
    5831           6 :         struct bgp_path_info *pi;
    5832           6 :         struct bgp_path_info *next;
    5833             : 
    5834          19 :         for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
    5835          11 :                 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
    5836           4 :                         const struct prefix *p = bgp_dest_get_prefix(dest);
    5837             : 
    5838           4 :                         next = pi->next;
    5839             : 
    5840             :                         /* Unimport EVPN routes from VRFs */
    5841           4 :                         if (safi == SAFI_EVPN)
    5842           0 :                                 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
    5843             :                                                         SAFI_EVPN, p, pi);
    5844             : 
    5845           4 :                         if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
    5846           4 :                             && pi->type == ZEBRA_ROUTE_BGP
    5847           4 :                             && (pi->sub_type == BGP_ROUTE_NORMAL
    5848           4 :                                 || pi->sub_type == BGP_ROUTE_AGGREGATE
    5849           0 :                                 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
    5850             : 
    5851           4 :                                 if (bgp_fibupd_safi(safi))
    5852           4 :                                         bgp_zebra_withdraw(p, pi, bgp, safi);
    5853             :                         }
    5854             : 
    5855           4 :                         bgp_path_info_reap(dest, pi);
    5856             :                 }
    5857           6 : }
    5858             : 
    5859             : /* Delete all kernel routes. */
    5860           3 : void bgp_cleanup_routes(struct bgp *bgp)
    5861             : {
    5862           3 :         afi_t afi;
    5863           3 :         struct bgp_dest *dest;
    5864           3 :         struct bgp_table *table;
    5865             : 
    5866          12 :         for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
    5867           9 :                 if (afi == AFI_L2VPN)
    5868           3 :                         continue;
    5869           6 :                 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
    5870             :                                   SAFI_UNICAST);
    5871             :                 /*
    5872             :                  * VPN and ENCAP and EVPN tables are two-level (RD is top level)
    5873             :                  */
    5874           6 :                 if (afi != AFI_L2VPN) {
    5875           6 :                         safi_t safi;
    5876           6 :                         safi = SAFI_MPLS_VPN;
    5877          12 :                         for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
    5878           0 :                              dest = bgp_route_next(dest)) {
    5879           0 :                                 table = bgp_dest_get_bgp_table_info(dest);
    5880           0 :                                 if (table != NULL) {
    5881           0 :                                         bgp_cleanup_table(bgp, table, safi);
    5882           0 :                                         bgp_table_finish(&table);
    5883           0 :                                         bgp_dest_set_bgp_table_info(dest, NULL);
    5884           0 :                                         bgp_dest_unlock_node(dest);
    5885             :                                 }
    5886             :                         }
    5887           6 :                         safi = SAFI_ENCAP;
    5888          12 :                         for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
    5889           0 :                              dest = bgp_route_next(dest)) {
    5890           0 :                                 table = bgp_dest_get_bgp_table_info(dest);
    5891           0 :                                 if (table != NULL) {
    5892           0 :                                         bgp_cleanup_table(bgp, table, safi);
    5893           0 :                                         bgp_table_finish(&table);
    5894           0 :                                         bgp_dest_set_bgp_table_info(dest, NULL);
    5895           0 :                                         bgp_dest_unlock_node(dest);
    5896             :                                 }
    5897             :                         }
    5898             :                 }
    5899             :         }
    5900           6 :         for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
    5901           0 :              dest = bgp_route_next(dest)) {
    5902           0 :                 table = bgp_dest_get_bgp_table_info(dest);
    5903           0 :                 if (table != NULL) {
    5904           0 :                         bgp_cleanup_table(bgp, table, SAFI_EVPN);
    5905           0 :                         bgp_table_finish(&table);
    5906           0 :                         bgp_dest_set_bgp_table_info(dest, NULL);
    5907           0 :                         bgp_dest_unlock_node(dest);
    5908             :                 }
    5909             :         }
    5910           3 : }
    5911             : 
    5912           0 : void bgp_reset(void)
    5913             : {
    5914           0 :         vty_reset();
    5915           0 :         bgp_zclient_reset();
    5916           0 :         access_list_reset();
    5917           0 :         prefix_list_reset();
    5918           0 : }
    5919             : 
    5920           8 : bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
    5921             : {
    5922           8 :         return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
    5923           8 :                 && CHECK_FLAG(peer->af_cap[afi][safi],
    5924             :                               PEER_CAP_ADDPATH_AF_TX_RCV));
    5925             : }
    5926             : 
    5927             : /* Parse NLRI stream.  Withdraw NLRI is recognized by NULL attr
    5928             :    value. */
    5929           8 : int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
    5930             :                       struct bgp_nlri *packet)
    5931             : {
    5932           8 :         uint8_t *pnt;
    5933           8 :         uint8_t *lim;
    5934           8 :         struct prefix p;
    5935           8 :         int psize;
    5936           8 :         afi_t afi;
    5937           8 :         safi_t safi;
    5938           8 :         bool addpath_capable;
    5939           8 :         uint32_t addpath_id;
    5940             : 
    5941           8 :         pnt = packet->nlri;
    5942           8 :         lim = pnt + packet->length;
    5943           8 :         afi = packet->afi;
    5944           8 :         safi = packet->safi;
    5945           8 :         addpath_id = 0;
    5946           8 :         addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
    5947             : 
    5948             :         /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
    5949             :            syntactic validity.  If the field is syntactically incorrect,
    5950             :            then the Error Subcode is set to Invalid Network Field. */
    5951          28 :         for (; pnt < lim; pnt += psize) {
    5952             :                 /* Clear prefix structure. */
    5953          20 :                 memset(&p, 0, sizeof(p));
    5954             : 
    5955          20 :                 if (addpath_capable) {
    5956             : 
    5957             :                         /* When packet overflow occurs return immediately. */
    5958           0 :                         if (pnt + BGP_ADDPATH_ID_LEN >= lim)
    5959             :                                 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
    5960             : 
    5961           0 :                         memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
    5962           0 :                         addpath_id = ntohl(addpath_id);
    5963           0 :                         pnt += BGP_ADDPATH_ID_LEN;
    5964             :                 }
    5965             : 
    5966             :                 /* Fetch prefix length. */
    5967          20 :                 p.prefixlen = *pnt++;
    5968             :                 /* afi/safi validity already verified by caller,
    5969             :                  * bgp_update_receive */
    5970          20 :                 p.family = afi2family(afi);
    5971             : 
    5972             :                 /* Prefix length check. */
    5973          20 :                 if (p.prefixlen > prefix_blen(&p) * 8) {
    5974           0 :                         flog_err(
    5975             :                                 EC_BGP_UPDATE_RCV,
    5976             :                                 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
    5977             :                                 peer->host, p.prefixlen, packet->afi);
    5978           0 :                         return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
    5979             :                 }
    5980             : 
    5981             :                 /* Packet size overflow check. */
    5982          20 :                 psize = PSIZE(p.prefixlen);
    5983             : 
    5984             :                 /* When packet overflow occur return immediately. */
    5985          20 :                 if (pnt + psize > lim) {
    5986           0 :                         flog_err(
    5987             :                                 EC_BGP_UPDATE_RCV,
    5988             :                                 "%s [Error] Update packet error (prefix length %d overflows packet)",
    5989             :                                 peer->host, p.prefixlen);
    5990           0 :                         return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
    5991             :                 }
    5992             : 
    5993             :                 /* Defensive coding, double-check the psize fits in a struct
    5994             :                  * prefix for the v4 and v6 afi's and unicast/multicast */
    5995          20 :                 if (psize > (ssize_t)sizeof(p.u.val)) {
    5996           0 :                         flog_err(
    5997             :                                 EC_BGP_UPDATE_RCV,
    5998             :                                 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
    5999             :                                 peer->host, p.prefixlen, sizeof(p.u.val));
    6000           0 :                         return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
    6001             :                 }
    6002             : 
    6003             :                 /* Fetch prefix from NLRI packet. */
    6004          20 :                 memcpy(p.u.val, pnt, psize);
    6005             : 
    6006             :                 /* Check address. */
    6007          20 :                 if (afi == AFI_IP && safi == SAFI_UNICAST) {
    6008          20 :                         if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
    6009             :                                 /* From RFC4271 Section 6.3:
    6010             :                                  *
    6011             :                                  * If a prefix in the NLRI field is semantically
    6012             :                                  * incorrect
    6013             :                                  * (e.g., an unexpected multicast IP address),
    6014             :                                  * an error SHOULD
    6015             :                                  * be logged locally, and the prefix SHOULD be
    6016             :                                  * ignored.
    6017             :                                  */
    6018           0 :                                 flog_err(
    6019             :                                         EC_BGP_UPDATE_RCV,
    6020             :                                         "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
    6021             :                                         peer->host, &p.u.prefix4);
    6022           0 :                                 continue;
    6023             :                         }
    6024             :                 }
    6025             : 
    6026             :                 /* Check address. */
    6027          20 :                 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
    6028           0 :                         if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
    6029           0 :                                 flog_err(
    6030             :                                         EC_BGP_UPDATE_RCV,
    6031             :                                         "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
    6032             :                                         peer->host, &p.u.prefix6);
    6033             : 
    6034           0 :                                 continue;
    6035             :                         }
    6036           0 :                         if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
    6037           0 :                                 flog_err(
    6038             :                                         EC_BGP_UPDATE_RCV,
    6039             :                                         "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
    6040             :                                         peer->host, &p.u.prefix6);
    6041             : 
    6042           0 :                                 continue;
    6043             :                         }
    6044             :                 }
    6045             : 
    6046             :                 /* Normal process. */
    6047          20 :                 if (attr)
    6048          20 :                         bgp_update(peer, &p, addpath_id, attr, afi, safi,
    6049             :                                    ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
    6050             :                                    NULL, 0, 0, NULL);
    6051             :                 else
    6052           0 :                         bgp_withdraw(peer, &p, addpath_id, attr, afi, safi,
    6053             :                                      ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
    6054             :                                      NULL, 0, NULL);
    6055             : 
    6056             :                 /* Do not send BGP notification twice when maximum-prefix count
    6057             :                  * overflow. */
    6058          20 :                 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
    6059             :                         return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
    6060             :         }
    6061             : 
    6062             :         /* Packet length consistency check. */
    6063           8 :         if (pnt != lim) {
    6064           0 :                 flog_err(
    6065             :                         EC_BGP_UPDATE_RCV,
    6066             :                         "%s [Error] Update packet error (prefix length mismatch with total length)",
    6067             :                         peer->host);
    6068           0 :                 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
    6069             :         }
    6070             : 
    6071             :         return BGP_NLRI_PARSE_OK;
    6072             : }
    6073             : 
    6074           0 : static struct bgp_static *bgp_static_new(void)
    6075             : {
    6076           0 :         return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
    6077             : }
    6078             : 
    6079           0 : static void bgp_static_free(struct bgp_static *bgp_static)
    6080             : {
    6081           0 :         XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
    6082           0 :         route_map_counter_decrement(bgp_static->rmap.map);
    6083             : 
    6084           0 :         XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
    6085           0 :         XFREE(MTYPE_BGP_STATIC, bgp_static);
    6086           0 : }
    6087             : 
    6088           0 : void bgp_static_update(struct bgp *bgp, const struct prefix *p,
    6089             :                        struct bgp_static *bgp_static, afi_t afi, safi_t safi)
    6090             : {
    6091           0 :         struct bgp_dest *dest;
    6092           0 :         struct bgp_path_info *pi;
    6093           0 :         struct bgp_path_info *new;
    6094           0 :         struct bgp_path_info rmap_path;
    6095           0 :         struct attr attr;
    6096           0 :         struct attr *attr_new;
    6097           0 :         route_map_result_t ret;
    6098             : #ifdef ENABLE_BGP_VNC
    6099           0 :         int vnc_implicit_withdraw = 0;
    6100             : #endif
    6101             : 
    6102           0 :         assert(bgp_static);
    6103             : 
    6104           0 :         dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
    6105             : 
    6106           0 :         bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
    6107             : 
    6108           0 :         attr.nexthop = bgp_static->igpnexthop;
    6109           0 :         attr.med = bgp_static->igpmetric;
    6110           0 :         attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
    6111             : 
    6112           0 :         if (afi == AFI_IP)
    6113           0 :                 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
    6114             : 
    6115           0 :         if (bgp_static->igpmetric)
    6116           0 :                 bgp_attr_set_aigp_metric(&attr, bgp_static->igpmetric);
    6117             : 
    6118           0 :         if (bgp_static->atomic)
    6119           0 :                 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
    6120             : 
    6121             :         /* Store label index, if required. */
    6122           0 :         if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
    6123           0 :                 attr.label_index = bgp_static->label_index;
    6124           0 :                 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
    6125             :         }
    6126             : 
    6127             :         /* Apply route-map. */
    6128           0 :         if (bgp_static->rmap.name) {
    6129           0 :                 struct attr attr_tmp = attr;
    6130             : 
    6131           0 :                 memset(&rmap_path, 0, sizeof(rmap_path));
    6132           0 :                 rmap_path.peer = bgp->peer_self;
    6133           0 :                 rmap_path.attr = &attr_tmp;
    6134             : 
    6135           0 :                 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
    6136             : 
    6137           0 :                 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
    6138             : 
    6139           0 :                 bgp->peer_self->rmap_type = 0;
    6140             : 
    6141           0 :                 if (ret == RMAP_DENYMATCH) {
    6142             :                         /* Free uninterned attribute. */
    6143           0 :                         bgp_attr_flush(&attr_tmp);
    6144             : 
    6145             :                         /* Unintern original. */
    6146           0 :                         aspath_unintern(&attr.aspath);
    6147           0 :                         bgp_static_withdraw(bgp, p, afi, safi);
    6148           0 :                         bgp_dest_unlock_node(dest);
    6149           0 :                         return;
    6150             :                 }
    6151             : 
    6152           0 :                 if (bgp_in_graceful_shutdown(bgp))
    6153           0 :                         bgp_attr_add_gshut_community(&attr_tmp);
    6154             : 
    6155           0 :                 attr_new = bgp_attr_intern(&attr_tmp);
    6156             :         } else {
    6157             : 
    6158           0 :                 if (bgp_in_graceful_shutdown(bgp))
    6159           0 :                         bgp_attr_add_gshut_community(&attr);
    6160             : 
    6161           0 :                 attr_new = bgp_attr_intern(&attr);
    6162             :         }
    6163             : 
    6164           0 :         for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
    6165           0 :                 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
    6166           0 :                     && pi->sub_type == BGP_ROUTE_STATIC)
    6167             :                         break;
    6168             : 
    6169           0 :         if (pi) {
    6170           0 :                 if (attrhash_cmp(pi->attr, attr_new)
    6171           0 :                     && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
    6172           0 :                     && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
    6173           0 :                         bgp_dest_unlock_node(dest);
    6174           0 :                         bgp_attr_unintern(&attr_new);
    6175           0 :                         aspath_unintern(&attr.aspath);
    6176           0 :                         return;
    6177             :                 } else {
    6178             :                         /* The attribute is changed. */
    6179           0 :                         bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
    6180             : 
    6181             :                         /* Rewrite BGP route information. */
    6182           0 :                         if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
    6183           0 :                                 bgp_path_info_restore(dest, pi);
    6184             :                         else
    6185           0 :                                 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
    6186             : #ifdef ENABLE_BGP_VNC
    6187           0 :                         if ((afi == AFI_IP || afi == AFI_IP6)
    6188           0 :                             && (safi == SAFI_UNICAST)) {
    6189           0 :                                 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
    6190             :                                         /*
    6191             :                                          * Implicit withdraw case.
    6192             :                                          * We have to do this before pi is
    6193             :                                          * changed
    6194             :                                          */
    6195           0 :                                         ++vnc_implicit_withdraw;
    6196           0 :                                         vnc_import_bgp_del_route(bgp, p, pi);
    6197           0 :                                         vnc_import_bgp_exterior_del_route(
    6198             :                                                 bgp, p, pi);
    6199             :                                 }
    6200             :                         }
    6201             : #endif
    6202           0 :                         bgp_attr_unintern(&pi->attr);
    6203           0 :                         pi->attr = attr_new;
    6204           0 :                         pi->uptime = monotime(NULL);
    6205             : #ifdef ENABLE_BGP_VNC
    6206           0 :                         if ((afi == AFI_IP || afi == AFI_IP6)
    6207           0 :                             && (safi == SAFI_UNICAST)) {
    6208           0 :                                 if (vnc_implicit_withdraw) {
    6209           0 :                                         vnc_import_bgp_add_route(bgp, p, pi);
    6210           0 :                                         vnc_import_bgp_exterior_add_route(
    6211             :                                                 bgp, p, pi);
    6212             :                                 }
    6213             :                         }
    6214             : #endif
    6215             : 
    6216             :                         /* Nexthop reachability check. */
    6217           0 :                         if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
    6218           0 :                             && (safi == SAFI_UNICAST
    6219           0 :                                 || safi == SAFI_LABELED_UNICAST)) {
    6220             : 
    6221           0 :                                 struct bgp *bgp_nexthop = bgp;
    6222             : 
    6223           0 :                                 if (pi->extra && pi->extra->bgp_orig)
    6224           0 :                                         bgp_nexthop = pi->extra->bgp_orig;
    6225             : 
    6226           0 :                                 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
    6227             :                                                             afi, safi, pi, NULL,
    6228             :                                                             0, p))
    6229           0 :                                         bgp_path_info_set_flag(dest, pi,
    6230             :                                                                BGP_PATH_VALID);
    6231             :                                 else {
    6232           0 :                                         if (BGP_DEBUG(nht, NHT)) {
    6233           0 :                                                 char buf1[INET6_ADDRSTRLEN];
    6234           0 :                                                 inet_ntop(p->family,
    6235           0 :                                                           &p->u.prefix, buf1,
    6236             :                                                           sizeof(buf1));
    6237           0 :                                                 zlog_debug(
    6238             :                                                         "%s(%s): Route not in table, not advertising",
    6239             :                                                         __func__, buf1);
    6240             :                                         }
    6241           0 :                                         bgp_path_info_unset_flag(
    6242             :                                                 dest, pi, BGP_PATH_VALID);
    6243             :                                 }
    6244             :                         } else {
    6245             :                                 /* Delete the NHT structure if any, if we're
    6246             :                                  * toggling between
    6247             :                                  * enabling/disabling import check. We
    6248             :                                  * deregister the route
    6249             :                                  * from NHT to avoid overloading NHT and the
    6250             :                                  * process interaction
    6251             :                                  */
    6252           0 :                                 bgp_unlink_nexthop(pi);
    6253           0 :                                 bgp_path_info_set_flag(dest, pi,
    6254             :                                                        BGP_PATH_VALID);
    6255             :                         }
    6256             :                         /* Process change. */
    6257           0 :                         bgp_aggregate_increment(bgp, p, pi, afi, safi);
    6258           0 :                         bgp_process(bgp, dest, afi, safi);
    6259             : 
    6260           0 :                         if (SAFI_UNICAST == safi
    6261           0 :                             && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
    6262             :                                 || bgp->inst_type
    6263             :                                            == BGP_INSTANCE_TYPE_DEFAULT)) {
    6264           0 :                                 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
    6265             :                                                          pi);
    6266             :                         }
    6267             : 
    6268           0 :                         bgp_dest_unlock_node(dest);
    6269           0 :                         aspath_unintern(&attr.aspath);
    6270           0 :                         return;
    6271             :                 }
    6272             :         }
    6273             : 
    6274             :         /* Make new BGP info. */
    6275           0 :         new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
    6276             :                         attr_new, dest);
    6277             :         /* Nexthop reachability check. */
    6278           0 :         if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
    6279           0 :             && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
    6280           0 :                 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
    6281             :                                             p))
    6282           0 :                         bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
    6283             :                 else {
    6284           0 :                         if (BGP_DEBUG(nht, NHT)) {
    6285           0 :                                 char buf1[INET6_ADDRSTRLEN];
    6286             : 
    6287           0 :                                 inet_ntop(p->family, &p->u.prefix, buf1,
    6288             :                                           sizeof(buf1));
    6289           0 :                                 zlog_debug(
    6290             :                                         "%s(%s): Route not in table, not advertising",
    6291             :                                         __func__, buf1);
    6292             :                         }
    6293           0 :                         bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
    6294             :                 }
    6295             :         } else {
    6296             :                 /* Delete the NHT structure if any, if we're toggling between
    6297             :                  * enabling/disabling import check. We deregister the route
    6298             :                  * from NHT to avoid overloading NHT and the process interaction
    6299             :                  */
    6300           0 :                 bgp_unlink_nexthop(new);
    6301             : 
    6302           0 :                 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
    6303             :         }
    6304             : 
    6305             :         /* Aggregate address increment. */
    6306           0 :         bgp_aggregate_increment(bgp, p, new, afi, safi);
    6307             : 
    6308             :         /* Register new BGP information. */
    6309           0 :         bgp_path_info_add(dest, new);
    6310             : 
    6311             :         /* route_node_get lock */
    6312           0 :         bgp_dest_unlock_node(dest);
    6313             : 
    6314             :         /* Process change. */
    6315           0 :         bgp_process(bgp, dest, afi, safi);
    6316             : 
    6317           0 :         if (SAFI_UNICAST == safi
    6318           0 :             && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
    6319             :                 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
    6320           0 :                 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
    6321             :         }
    6322             : 
    6323             :         /* Unintern original. */
    6324           0 :         aspath_unintern(&attr.aspath);
    6325             : }
    6326             : 
    6327           0 : void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
    6328             :                          safi_t safi)
    6329             : {
    6330           0 :         struct bgp_dest *dest;
    6331           0 :         struct bgp_path_info *pi;
    6332             : 
    6333           0 :         dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
    6334             : 
    6335             :         /* Check selected route and self inserted route. */
    6336           0 :         for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
    6337           0 :                 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
    6338           0 :                     && pi->sub_type == BGP_ROUTE_STATIC)
    6339             :                         break;
    6340             : 
    6341             :         /* Withdraw static BGP route from routing table. */
    6342           0 :         if (pi) {
    6343           0 :                 if (SAFI_UNICAST == safi
    6344           0 :                     && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
    6345             :                         || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
    6346           0 :                         vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
    6347             :                 }
    6348           0 :                 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
    6349           0 :                 bgp_unlink_nexthop(pi);
    6350           0 :                 bgp_path_info_delete(dest, pi);
    6351           0 :                 bgp_process(bgp, dest, afi, safi);
    6352             :         }
    6353             : 
    6354             :         /* Unlock bgp_node_lookup. */
    6355           0 :         bgp_dest_unlock_node(dest);
    6356           0 : }
    6357             : 
    6358             : /*
    6359             :  * Used for SAFI_MPLS_VPN and SAFI_ENCAP
    6360             :  */
    6361           0 : static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
    6362             :                                      afi_t afi, safi_t safi,
    6363             :                                      struct prefix_rd *prd)
    6364             : {
    6365           0 :         struct bgp_dest *dest;
    6366           0 :         struct bgp_path_info *pi;
    6367             : 
    6368           0 :         dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
    6369             : 
    6370             :         /* Check selected route and self inserted route. */
    6371           0 :         for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
    6372           0 :                 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
    6373           0 :                     && pi->sub_type == BGP_ROUTE_STATIC)
    6374             :                         break;
    6375             : 
    6376             :         /* Withdraw static BGP route from routing table. */
    6377           0 :         if (pi) {
    6378             : #ifdef ENABLE_BGP_VNC
    6379           0 :                 rfapiProcessWithdraw(
    6380           0 :                         pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
    6381             :                         1); /* Kill, since it is an administrative change */
    6382             : #endif
    6383           0 :                 if (SAFI_MPLS_VPN == safi
    6384           0 :                     && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
    6385           0 :                         vpn_leak_to_vrf_withdraw(pi);
    6386             :                 }
    6387           0 :                 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
    6388           0 :                 bgp_path_info_delete(dest, pi);
    6389           0 :                 bgp_process(bgp, dest, afi, safi);
    6390             :         }
    6391             : 
    6392             :         /* Unlock bgp_node_lookup. */
    6393           0 :         bgp_dest_unlock_node(dest);
    6394           0 : }
    6395             : 
    6396           0 : static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
    6397             :                                    struct bgp_static *bgp_static, afi_t afi,
    6398             :                                    safi_t safi)
    6399             : {
    6400           0 :         struct bgp_dest *dest;
    6401           0 :         struct bgp_path_info *new;
    6402           0 :         struct attr *attr_new;
    6403           0 :         struct attr attr = {0};
    6404           0 :         struct bgp_path_info *pi;
    6405             : #ifdef ENABLE_BGP_VNC
    6406           0 :         mpls_label_t label = 0;
    6407             : #endif
    6408           0 :         uint32_t num_labels = 0;
    6409             : 
    6410           0 :         assert(bgp_static);
    6411             : 
    6412           0 :         if (bgp_static->label != MPLS_INVALID_LABEL)
    6413           0 :                 num_labels = 1;
    6414           0 :         dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
    6415             :                                 &bgp_static->prd);
    6416             : 
    6417           0 :         bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
    6418             : 
    6419           0 :         attr.nexthop = bgp_static->igpnexthop;
    6420           0 :         attr.med = bgp_static->igpmetric;
    6421           0 :         attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
    6422             : 
    6423           0 :         if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
    6424           0 :             || (safi == SAFI_ENCAP)) {
    6425           0 :                 if (afi == AFI_IP) {
    6426           0 :                         attr.mp_nexthop_global_in = bgp_static->igpnexthop;
    6427           0 :                         attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
    6428             :                 }
    6429             :         }
    6430           0 :         if (afi == AFI_L2VPN) {
    6431           0 :                 if (bgp_static->gatewayIp.family == AF_INET) {
    6432           0 :                         SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
    6433           0 :                         memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
    6434             :                                &bgp_static->gatewayIp.u.prefix4,
    6435             :                                IPV4_MAX_BYTELEN);
    6436           0 :                 } else if (bgp_static->gatewayIp.family == AF_INET6) {
    6437           0 :                         SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
    6438           0 :                         memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
    6439             :                                &bgp_static->gatewayIp.u.prefix6,
    6440             :                                IPV6_MAX_BYTELEN);
    6441             :                 }
    6442           0 :                 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
    6443           0 :                 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
    6444           0 :                         struct bgp_encap_type_vxlan bet;
    6445           0 :                         memset(&bet, 0, sizeof(bet));
    6446           0 :                         bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
    6447           0 :                         bgp_encap_type_vxlan_to_tlv(&bet, &attr);
    6448             :                 }
    6449           0 :                 if (bgp_static->router_mac) {
    6450           0 :                         bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
    6451             :                 }
    6452             :         }
    6453             :         /* Apply route-map. */
    6454           0 :         if (bgp_static->rmap.name) {
    6455           0 :                 struct attr attr_tmp = attr;
    6456           0 :                 struct bgp_path_info rmap_path;
    6457           0 :                 route_map_result_t ret;
    6458             : 
    6459           0 :                 rmap_path.peer = bgp->peer_self;
    6460           0 :                 rmap_path.attr = &attr_tmp;
    6461             : 
    6462           0 :                 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
    6463             : 
    6464           0 :                 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
    6465             : 
    6466           0 :                 bgp->peer_self->rmap_type = 0;
    6467             : 
    6468           0 :                 if (ret == RMAP_DENYMATCH) {
    6469             :                         /* Free uninterned attribute. */
    6470           0 :                         bgp_attr_flush(&attr_tmp);
    6471             : 
    6472             :                         /* Unintern original. */
    6473           0 :                         aspath_unintern(&attr.aspath);
    6474           0 :                         bgp_static_withdraw_safi(bgp, p, afi, safi,
    6475             :                                                  &bgp_static->prd);
    6476           0 :                         bgp_dest_unlock_node(dest);
    6477           0 :                         return;
    6478             :                 }
    6479             : 
    6480           0 :                 attr_new = bgp_attr_intern(&attr_tmp);
    6481             :         } else {
    6482           0 :                 attr_new = bgp_attr_intern(&attr);
    6483             :         }
    6484             : 
    6485           0 :         for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
    6486           0 :                 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
    6487           0 :                     && pi->sub_type == BGP_ROUTE_STATIC)
    6488             :                         break;
    6489             : 
    6490           0 :         if (pi) {
    6491           0 :                 if (attrhash_cmp(pi->attr, attr_new)
    6492           0 :                     && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
    6493           0 :                         bgp_dest_unlock_node(dest);
    6494           0 :                         bgp_attr_unintern(&attr_new);
    6495           0 :                         aspath_unintern(&attr.aspath);
    6496           0 :                         return;
    6497             :                 } else {
    6498             :                         /* The attribute is changed. */
    6499           0 :                         bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
    6500             : 
    6501             :                         /* Rewrite BGP route information. */
    6502           0 :                         if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
    6503           0 :                                 bgp_path_info_restore(dest, pi);
    6504             :                         else
    6505           0 :                                 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
    6506           0 :                         bgp_attr_unintern(&pi->attr);
    6507           0 :                         pi->attr = attr_new;
    6508           0 :                         pi->uptime = monotime(NULL);
    6509             : #ifdef ENABLE_BGP_VNC
    6510           0 :                         if (pi->extra)
    6511           0 :                                 label = decode_label(&pi->extra->label[0]);
    6512             : #endif
    6513             : 
    6514             :                         /* Process change. */
    6515           0 :                         bgp_aggregate_increment(bgp, p, pi, afi, safi);
    6516           0 :                         bgp_process(bgp, dest, afi, safi);
    6517             : 
    6518           0 :                         if (SAFI_MPLS_VPN == safi
    6519           0 :                             && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
    6520           0 :                                 vpn_leak_to_vrf_update(bgp, pi,
    6521             :                                                        &bgp_static->prd);
    6522             :                         }
    6523             : #ifdef ENABLE_BGP_VNC
    6524           0 :                         rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
    6525           0 :                                            pi->attr, afi, safi, pi->type,
    6526           0 :                                            pi->sub_type, &label);
    6527             : #endif
    6528           0 :                         bgp_dest_unlock_node(dest);
    6529           0 :                         aspath_unintern(&attr.aspath);
    6530           0 :                         return;
    6531             :                 }
    6532             :         }
    6533             : 
    6534             : 
    6535             :         /* Make new BGP info. */
    6536           0 :         new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
    6537             :                         attr_new, dest);
    6538           0 :         SET_FLAG(new->flags, BGP_PATH_VALID);
    6539           0 :         bgp_path_info_extra_get(new);
    6540           0 :         if (num_labels) {
    6541           0 :                 new->extra->label[0] = bgp_static->label;
    6542           0 :                 new->extra->num_labels = num_labels;
    6543             :         }
    6544             : #ifdef ENABLE_BGP_VNC
    6545           0 :         label = decode_label(&bgp_static->label);
    6546             : #endif
    6547             : 
    6548             :         /* Aggregate address increment. */
    6549           0 :         bgp_aggregate_increment(bgp, p, new, afi, safi);
    6550             : 
    6551             :         /* Register new BGP information. */
    6552           0 :         bgp_path_info_add(dest, new);
    6553             :         /* route_node_get lock */
    6554           0 :         bgp_dest_unlock_node(dest);
    6555             : 
    6556             :         /* Process change. */
    6557           0 :         bgp_process(bgp, dest, afi, safi);
    6558             : 
    6559           0 :         if (SAFI_MPLS_VPN == safi
    6560           0 :             && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
    6561           0 :                 vpn_leak_to_vrf_update(bgp, new, &bgp_static->prd);
    6562             :         }
    6563             : #ifdef ENABLE_BGP_VNC
    6564           0 :         rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
    6565           0 :                            safi, new->type, new->sub_type, &label);
    6566             : #endif
    6567             : 
    6568             :         /* Unintern original. */
    6569           0 :         aspath_unintern(&attr.aspath);
    6570             : }
    6571             : 
    6572             : /* Configure static BGP network.  When user don't run zebra, static
    6573             :    route should be installed as valid.  */
    6574           0 : static int bgp_static_set(struct vty *vty, const char *negate,
    6575             :                           const char *ip_str, afi_t afi, safi_t safi,
    6576             :                           const char *rmap, int backdoor, uint32_t label_index)
    6577             : {
    6578           0 :         VTY_DECLVAR_CONTEXT(bgp, bgp);
    6579           0 :         int ret;
    6580           0 :         struct prefix p;
    6581           0 :         struct bgp_static *bgp_static;
    6582           0 :         struct bgp_dest *dest;
    6583           0 :         uint8_t need_update = 0;
    6584             : 
    6585             :         /* Convert IP prefix string to struct prefix. */
    6586           0 :         ret = str2prefix(ip_str, &p);
    6587           0 :         if (!ret) {
    6588           0 :                 vty_out(vty, "%% Malformed prefix\n");
    6589           0 :                 return CMD_WARNING_CONFIG_FAILED;
    6590             :         }
    6591           0 :         if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
    6592           0 :                 vty_out(vty, "%% Malformed prefix (link-local address)\n");
    6593           0 :                 return CMD_WARNING_CONFIG_FAILED;
    6594             :         }
    6595             : 
    6596           0 :         apply_mask(&p);
    6597             : 
    6598           0 :         if (negate) {
    6599             : 
    6600             :                 /* Set BGP static route configuration. */
    6601           0 :                 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
    6602             : 
    6603           0 :                 if (!dest) {
    6604           0 :                         vty_out(vty, "%% Can't find static route specified\n");
    6605           0 :                         return CMD_WARNING_CONFIG_FAILED;
    6606             :                 }
    6607             : 
    6608           0 :                 bgp_static = bgp_dest_get_bgp_static_info(dest);
    6609             : 
    6610           0 :                 if ((label_index != BGP_INVALID_LABEL_INDEX)
    6611           0 :                     && (label_index != bgp_static->label_index)) {
    6612           0 :                         vty_out(vty,
    6613             :                                 "%% label-index doesn't match static route\n");
    6614           0 :                         bgp_dest_unlock_node(dest);
    6615           0 :                         return CMD_WARNING_CONFIG_FAILED;
    6616             :                 }
    6617             : 
    6618           0 :                 if ((rmap && bgp_static->rmap.name)
    6619           0 :                     && strcmp(rmap, bgp_static->rmap.name)) {
    6620           0 :                         vty_out(vty,
    6621             :                                 "%% route-map name doesn't match static route\n");
    6622           0 :                         bgp_dest_unlock_node(dest);
    6623           0 :                         return CMD_WARNING_CONFIG_FAILED;
    6624             :                 }
    6625             : 
    6626             :                 /* Update BGP RIB. */
    6627           0 :                 if (!bgp_static->backdoor)
    6628           0 :                         bgp_static_withdraw(bgp, &p, afi, safi);
    6629             : 
    6630             :                 /* Clear configuration. */
    6631           0 :                 bgp_static_free(bgp_static);
    6632           0 :                 bgp_dest_set_bgp_static_info(dest, NULL);
    6633           0 :                 bgp_dest_unlock_node(dest);
    6634           0 :                 bgp_dest_unlock_node(dest);
    6635             :         } else {
    6636             : 
    6637             :                 /* Set BGP static route configuration. */
    6638           0 :                 dest = bgp_node_get(bgp->route[afi][safi], &p);
    6639           0 :                 bgp_static = bgp_dest_get_bgp_static_info(dest);
    6640           0 :                 if (bgp_static) {
    6641             :                         /* Configuration change. */
    6642             :                         /* Label index cannot be changed. */
    6643           0 :                         if (bgp_static->label_index != label_index) {
    6644           0 :                                 vty_out(vty, "%% cannot change label-index\n");
    6645           0 :                                 bgp_dest_unlock_node(dest);
    6646           0 :                                 return CMD_WARNING_CONFIG_FAILED;
    6647             :                         }
    6648             : 
    6649             :                         /* Check previous routes are installed into BGP.  */
    6650           0 :                         if (bgp_static->valid
    6651           0 :                             && bgp_static->backdoor != backdoor)
    6652           0 :                                 need_update = 1;
    6653             : 
    6654           0 :                         bgp_static->backdoor = backdoor;
    6655             : 
    6656           0 :                         if (rmap) {
    6657           0 :                                 XFREE(MTYPE_ROUTE_MAP_NAME,
    6658             :                                       bgp_static->rmap.name);
    6659           0 :                                 route_map_counter_decrement(
    6660             :                                         bgp_static->rmap.map);
    6661           0 :                                 bgp_static->rmap.name =
    6662           0 :                                         XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
    6663           0 :                                 bgp_static->rmap.map =
    6664           0 :                                         route_map_lookup_by_name(rmap);
    6665           0 :                                 route_map_counter_increment(
    6666             :                                         bgp_static->rmap.map);
    6667             :                         } else {
    6668           0 :                                 XFREE(MTYPE_ROUTE_MAP_NAME,
    6669             :                                       bgp_static->rmap.name);
    6670           0 :                                 route_map_counter_decrement(
    6671             :                                         bgp_static->rmap.map);
    6672           0 :                                 bgp_static->rmap.map = NULL;
    6673           0 :                                 bgp_static->valid = 0;
    6674             :                         }
    6675           0 :                         bgp_dest_unlock_node(dest);
    6676             :                 } else {
    6677             :                         /* New configuration. */
    6678           0 :                         bgp_static = bgp_static_new();
    6679           0 :                         bgp_static->backdoor = backdoor;
    6680           0 :                         bgp_static->valid = 0;
    6681           0 :                         bgp_static->igpmetric = 0;
    6682           0 :                         bgp_static->igpnexthop.s_addr = INADDR_ANY;
    6683           0 :                         bgp_static->label_index = label_index;
    6684             : 
    6685           0 :                         if (rmap) {
    6686           0 :                                 XFREE(MTYPE_ROUTE_MAP_NAME,
    6687             :                                       bgp_static->rmap.name);
    6688           0 :                                 route_map_counter_decrement(
    6689             :                                         bgp_static->rmap.map);
    6690           0 :                                 bgp_static->rmap.name =
    6691           0 :                                         XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
    6692           0 :                                 bgp_static->rmap.map =
    6693           0 :                                         route_map_lookup_by_name(rmap);
    6694           0 :                                 route_map_counter_increment(
    6695             :                                         bgp_static->rmap.map);
    6696             :                         }
    6697           0 :                         bgp_dest_set_bgp_static_info(dest, bgp_static);
    6698             :                 }
    6699             : 
    6700           0 :                 bgp_static->valid = 1;
    6701           0 :                 if (need_update)
    6702           0 :                         bgp_static_withdraw(bgp, &p, afi, safi);
    6703             : 
    6704           0 :                 if (!bgp_static->backdoor)
    6705           0 :                         bgp_static_update(bgp, &p, bgp_static, afi, safi);
    6706             :         }
    6707             : 
    6708             :         return CMD_SUCCESS;
    6709             : }
    6710             : 
    6711           0 : void bgp_static_add(struct bgp *bgp)
    6712             : {
    6713           0 :         afi_t afi;
    6714           0 :         safi_t safi;
    6715           0 :         struct bgp_dest *dest;
    6716           0 :         struct bgp_dest *rm;
    6717           0 :         struct bgp_table *table;
    6718           0 :         struct bgp_static *bgp_static;
    6719             : 
    6720           0 :         SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
    6721           0 :         FOREACH_AFI_SAFI (afi, safi)
    6722           0 :                 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
    6723           0 :                      dest = bgp_route_next(dest)) {
    6724           0 :                         if (!bgp_dest_has_bgp_path_info_data(dest))
    6725           0 :                                 continue;
    6726             : 
    6727           0 :                         if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
    6728           0 :                             || (safi == SAFI_EVPN)) {
    6729           0 :                                 table = bgp_dest_get_bgp_table_info(dest);
    6730             : 
    6731           0 :                                 for (rm = bgp_table_top(table); rm;
    6732           0 :                                      rm = bgp_route_next(rm)) {
    6733           0 :                                         bgp_static =
    6734           0 :                                                 bgp_dest_get_bgp_static_info(
    6735             :                                                         rm);
    6736           0 :                                         bgp_static_update_safi(
    6737             :                                                 bgp, bgp_dest_get_prefix(rm),
    6738             :                                                 bgp_static, afi, safi);
    6739             :                                 }
    6740             :                         } else {
    6741           0 :                                 bgp_static_update(
    6742             :                                         bgp, bgp_dest_get_prefix(dest),
    6743             :                                         bgp_dest_get_bgp_static_info(dest), afi,
    6744             :                                         safi);
    6745             :                         }
    6746             :                 }
    6747           0 :         UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
    6748           0 : }
    6749             : 
    6750             : /* Called from bgp_delete().  Delete all static routes from the BGP
    6751             :    instance. */
    6752           3 : void bgp_static_delete(struct bgp *bgp)
    6753             : {
    6754           3 :         afi_t afi;
    6755           3 :         safi_t safi;
    6756           3 :         struct bgp_dest *dest;
    6757           3 :         struct bgp_dest *rm;
    6758           3 :         struct bgp_table *table;
    6759           3 :         struct bgp_static *bgp_static;
    6760             : 
    6761          75 :         FOREACH_AFI_SAFI (afi, safi)
    6762         126 :                 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
    6763           0 :                      dest = bgp_route_next(dest)) {
    6764           0 :                         if (!bgp_dest_has_bgp_path_info_data(dest))
    6765           0 :                                 continue;
    6766             : 
    6767           0 :                         if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
    6768           0 :                             || (safi == SAFI_EVPN)) {
    6769           0 :                                 table = bgp_dest_get_bgp_table_info(dest);
    6770             : 
    6771           0 :                                 for (rm = bgp_table_top(table); rm;
    6772           0 :                                      rm = bgp_route_next(rm)) {
    6773           0 :                                         bgp_static =
    6774           0 :                                                 bgp_dest_get_bgp_static_info(
    6775             :                                                         rm);
    6776           0 :                                         if (!bgp_static)
    6777           0 :                                                 continue;
    6778             : 
    6779           0 :                                         bgp_static_withdraw_safi(
    6780             :                                                 bgp, bgp_dest_get_prefix(rm),
    6781             :                                                 AFI_IP, safi,
    6782             :                                                 (struct prefix_rd *)
    6783           0 :                                                         bgp_dest_get_prefix(
    6784             :                                                                 dest));
    6785           0 :                                         bgp_static_free(bgp_static);
    6786           0 :                                         bgp_dest_set_bgp_static_info(rm,
    6787             :                                                                      NULL);
    6788           0 :                                         bgp_dest_unlock_node(rm);
    6789             :                                 }
    6790             :                         } else {
    6791           0 :                                 bgp_static = bgp_dest_get_bgp_static_info(dest);
    6792           0 :                                 bgp_static_withdraw(bgp,
    6793             :                                                     bgp_dest_get_prefix(dest),
    6794             :                                                     afi, safi);
    6795           0 :                                 bgp_static_free(bgp_static);
    6796           0 :                                 bgp_dest_set_bgp_static_info(dest, NULL);
    6797           0 :                                 bgp_dest_unlock_node(dest);
    6798             :                         }
    6799             :                 }
    6800           3 : }
    6801             : 
    6802           0 : void bgp_static_redo_import_check(struct bgp *bgp)
    6803             : {
    6804           0 :         afi_t afi;
    6805           0 :         safi_t safi;
    6806           0 :         struct bgp_dest *dest;
    6807           0 :         struct bgp_dest *rm;
    6808           0 :         struct bgp_table *table;
    6809           0 :         struct bgp_static *bgp_static;
    6810             : 
    6811             :         /* Use this flag to force reprocessing of the route */
    6812           0 :         SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
    6813           0 :         FOREACH_AFI_SAFI (afi, safi) {
    6814           0 :                 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
    6815           0 :                      dest = bgp_route_next(dest)) {
    6816           0 :                         if (!bgp_dest_has_bgp_path_info_data(dest))
    6817           0 :                                 continue;
    6818             : 
    6819           0 :                         if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
    6820           0 :                             || (safi == SAFI_EVPN)) {
    6821           0 :                                 table = bgp_dest_get_bgp_table_info(dest);
    6822             : 
    6823           0 :                                 for (rm = bgp_table_top(table); rm;
    6824           0 :                                      rm = bgp_route_next(rm)) {
    6825           0 :                                         bgp_static =
    6826           0 :                                                 bgp_dest_get_bgp_static_info(
    6827             :                                                         rm);
    6828           0 :                                         bgp_static_update_safi(
    6829             :                                                 bgp, bgp_dest_get_prefix(rm),
    6830             :                                                 bgp_static, afi, safi);
    6831             :                                 }
    6832             :                         } else {
    6833           0 :                                 bgp_static = bgp_dest_get_bgp_static_info(dest);
    6834           0 :                                 bgp_static_update(bgp,
    6835             :                                                   bgp_dest_get_prefix(dest),
    6836             :                                                   bgp_static, afi, safi);
    6837             :                         }
    6838             :                 }
    6839             :         }
    6840           0 :         UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
    6841           0 : }
    6842             : 
    6843           0 : static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
    6844             :                                               safi_t safi)
    6845             : {
    6846           0 :         struct bgp_table *table;
    6847           0 :         struct bgp_dest *dest;
    6848           0 :         struct bgp_path_info *pi;
    6849             : 
    6850             :         /* Do not install the aggregate route if BGP is in the
    6851             :          * process of termination.
    6852             :          */
    6853           0 :         if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
    6854           0 :             || (bgp->peer_self == NULL))
    6855             :                 return;
    6856             : 
    6857           0 :         table = bgp->rib[afi][safi];
    6858           0 :         for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
    6859           0 :                 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
    6860           0 :                         if (pi->peer == bgp->peer_self
    6861           0 :                             && ((pi->type == ZEBRA_ROUTE_BGP
    6862           0 :                                  && pi->sub_type == BGP_ROUTE_STATIC)
    6863           0 :                                 || (pi->type != ZEBRA_ROUTE_BGP
    6864           0 :                                     && pi->sub_type
    6865             :                                                == BGP_ROUTE_REDISTRIBUTE))) {
    6866           0 :                                 bgp_aggregate_decrement(
    6867             :                                         bgp, bgp_dest_get_prefix(dest), pi, afi,
    6868             :                                         safi);
    6869           0 :                                 bgp_unlink_nexthop(pi);
    6870           0 :                                 bgp_path_info_delete(dest, pi);
    6871           0 :                                 bgp_process(bgp, dest, afi, safi);
    6872             :                         }
    6873             :                 }
    6874             :         }
    6875             : }
    6876             : 
    6877             : /*
    6878             :  * Purge all networks and redistributed routes from routing table.
    6879             :  * Invoked upon the instance going down.
    6880             :  */
    6881           0 : void bgp_purge_static_redist_routes(struct bgp *bgp)
    6882             : {
    6883           0 :         afi_t afi;
    6884           0 :         safi_t safi;
    6885             : 
    6886           0 :         FOREACH_AFI_SAFI (afi, safi)
    6887           0 :                 bgp_purge_af_static_redist_routes(bgp, afi, safi);
    6888           0 : }
    6889             : 
    6890             : /*
    6891             :  * gpz 110624
    6892             :  * Currently this is used to set static routes for VPN and ENCAP.
    6893             :  * I think it can probably be factored with bgp_static_set.
    6894             :  */
    6895           0 : int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
    6896             :                         const char *ip_str, const char *rd_str,
    6897             :                         const char *label_str, const char *rmap_str,
    6898             :                         int evpn_type, const char *esi, const char *gwip,
    6899             :                         const char *ethtag, const char *routermac)
    6900             : {
    6901           0 :         VTY_DECLVAR_CONTEXT(bgp, bgp);
    6902           0 :         int ret;
    6903           0 :         struct prefix p;
    6904           0 :         struct prefix_rd prd;
    6905           0 :         struct bgp_dest *pdest;
    6906           0 :         struct bgp_dest *dest;
    6907           0 :         struct bgp_table *table;
    6908           0 :         struct bgp_static *bgp_static;
    6909           0 :         mpls_label_t label = MPLS_INVALID_LABEL;
    6910           0 :         struct prefix gw_ip;
    6911             : 
    6912             :         /* validate ip prefix */
    6913           0 :         ret = str2prefix(ip_str, &p);
    6914           0 :         if (!ret) {
    6915           0 :                 vty_out(vty, "%% Malformed prefix\n");
    6916           0 :                 return CMD_WARNING_CONFIG_FAILED;
    6917             :         }
    6918           0 :         apply_mask(&p);
    6919           0 :         if ((afi == AFI_L2VPN)
    6920           0 :             && (bgp_build_evpn_prefix(evpn_type,
    6921           0 :                                       ethtag != NULL ? atol(ethtag) : 0, &p))) {
    6922           0 :                 vty_out(vty, "%% L2VPN prefix could not be forged\n");
    6923           0 :                 return CMD_WARNING_CONFIG_FAILED;
    6924             :         }
    6925             : 
    6926           0 :         ret = str2prefix_rd(rd_str, &prd);
    6927           0 :         if (!ret) {
    6928           0 :                 vty_out(vty, "%% Malformed rd\n");
    6929           0 :                 return CMD_WARNING_CONFIG_FAILED;
    6930             :         }
    6931             : 
    6932           0 :         if (label_str) {
    6933           0 :                 unsigned long label_val;
    6934           0 :                 label_val = strtoul(label_str, NULL, 10);
    6935           0 :                 encode_label(label_val, &label);
    6936             :         }
    6937             : 
    6938           0 :         if (safi == SAFI_EVPN) {
    6939           0 :                 if (esi && str2esi(esi, NULL) == 0) {
    6940           0 :                         vty_out(vty, "%% Malformed ESI\n");
    6941           0 :                         return CMD_WARNING_CONFIG_FAILED;
    6942             :                 }
    6943           0 :                 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
    6944           0 :                         vty_out(vty, "%% Malformed Router MAC\n");
    6945           0 :                         return CMD_WARNING_CONFIG_FAILED;
    6946             :                 }
    6947           0 :                 if (gwip) {
    6948           0 :                         memset(&gw_ip, 0, sizeof(gw_ip));
    6949           0 :                         ret = str2prefix(gwip, &gw_ip);
    6950           0 :                         if (!ret) {
    6951           0 :                                 vty_out(vty, "%% Malformed GatewayIp\n");
    6952           0 :                                 return CMD_WARNING_CONFIG_FAILED;
    6953             :                         }
    6954           0 :                         if ((gw_ip.family == AF_INET
    6955           0 :                              && is_evpn_prefix_ipaddr_v6(
    6956             :                                         (struct prefix_evpn *)&p))
    6957           0 :                             || (gw_ip.family == AF_INET6
    6958           0 :                                 && is_evpn_prefix_ipaddr_v4(
    6959             :                                            (struct prefix_evpn *)&p))) {
    6960           0 :                                 vty_out(vty,
    6961             :                                         "%% GatewayIp family differs with IP prefix\n");
    6962           0 :                                 return CMD_WARNING_CONFIG_FAILED;
    6963             :                         }
    6964             :                 }
    6965             :         }
    6966           0 :         pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
    6967           0 :         if (!bgp_dest_has_bgp_path_info_data(pdest))
    6968           0 :                 bgp_dest_set_bgp_table_info(pdest,
    6969             :                                             bgp_table_init(bgp, afi, safi));
    6970           0 :         table = bgp_dest_get_bgp_table_info(pdest);
    6971             : 
    6972           0 :         dest = bgp_node_get(table, &p);
    6973             : 
    6974           0 :         if (bgp_dest_has_bgp_path_info_data(dest)) {
    6975           0 :                 vty_out(vty, "%% Same network configuration exists\n");
    6976           0 :                 bgp_dest_unlock_node(dest);
    6977             :         } else {
    6978             :                 /* New configuration. */
    6979           0 :                 bgp_static = bgp_static_new();
    6980           0 :                 bgp_static->backdoor = 0;
    6981           0 :                 bgp_static->valid = 0;
    6982           0 :                 bgp_static->igpmetric = 0;
    6983           0 :                 bgp_static->igpnexthop.s_addr = INADDR_ANY;
    6984           0 :                 bgp_static->label = label;
    6985           0 :                 bgp_static->prd = prd;
    6986             : 
    6987           0 :                 if (rmap_str) {
    6988           0 :                         XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
    6989           0 :                         route_map_counter_decrement(bgp_static->rmap.map);
    6990           0 :                         bgp_static->rmap.name =
    6991           0 :                                 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
    6992           0 :                         bgp_static->rmap.map =
    6993           0 :                                 route_map_lookup_by_name(rmap_str);
    6994           0 :                         route_map_counter_increment(bgp_static->rmap.map);
    6995             :                 }
    6996             : 
    6997           0 :                 if (safi == SAFI_EVPN) {
    6998           0 :                         if (esi) {
    6999           0 :                                 bgp_static->eth_s_id =
    7000           0 :                                         XCALLOC(MTYPE_ATTR,
    7001             :                                                 sizeof(esi_t));
    7002           0 :                                 str2esi(esi, bgp_static->eth_s_id);
    7003             :                         }
    7004           0 :                         if (routermac) {
    7005           0 :                                 bgp_static->router_mac =
    7006           0 :                                         XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
    7007           0 :                                 (void)prefix_str2mac(routermac,
    7008             :                                                      bgp_static->router_mac);
    7009             :                         }
    7010           0 :                         if (gwip)
    7011           0 :                                 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
    7012             :                 }
    7013           0 :                 bgp_dest_set_bgp_static_info(dest, bgp_static);
    7014             : 
    7015           0 :                 bgp_static->valid = 1;
    7016           0 :                 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
    7017             :         }
    7018             : 
    7019             :         return CMD_SUCCESS;
    7020             : }
    7021             : 
    7022             : /* Configure static BGP network. */
    7023           0 : int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
    7024             :                           const char *ip_str, const char *rd_str,
    7025             :                           const char *label_str, int evpn_type, const char *esi,
    7026             :                           const char *gwip, const char *ethtag)
    7027             : {
    7028           0 :         VTY_DECLVAR_CONTEXT(bgp, bgp);
    7029           0 :         int ret;
    7030           0 :         struct prefix p;
    7031           0 :         struct prefix_rd prd;
    7032           0 :         struct bgp_dest *pdest;
    7033           0 :         struct bgp_dest *dest;
    7034           0 :         struct bgp_table *table;
    7035           0 :         struct bgp_static *bgp_static;
    7036           0 :         mpls_label_t label = MPLS_INVALID_LABEL;
    7037             : 
    7038             :         /* Convert IP prefix string to struct prefix. */
    7039           0 :         ret = str2prefix(ip_str, &p);
    7040           0 :         if (!ret) {
    7041           0 :                 vty_out(vty, "%% Malformed prefix\n");
    7042           0 :                 return CMD_WARNING_CONFIG_FAILED;
    7043             :         }
    7044           0 :         apply_mask(&p);
    7045           0 :         if ((afi == AFI_L2VPN)
    7046           0 :             && (bgp_build_evpn_prefix(evpn_type,
    7047           0 :                                       ethtag != NULL ? atol(ethtag) : 0, &p))) {
    7048           0 :                 vty_out(vty, "%% L2VPN prefix could not be forged\n");
    7049           0 :                 return CMD_WARNING_CONFIG_FAILED;
    7050             :         }
    7051           0 :         ret = str2prefix_rd(rd_str, &prd);
    7052           0 :         if (!ret) {
    7053           0 :                 vty_out(vty, "%% Malformed rd\n");
    7054           0 :                 return CMD_WARNING_CONFIG_FAILED;
    7055             :         }
    7056             : 
    7057           0 :         if (label_str) {
    7058           0 :                 unsigned long label_val;
    7059           0 :                 label_val = strtoul(label_str, NULL, 10);
    7060           0 :                 encode_label(label_val, &label);
    7061             :         }
    7062             : 
    7063           0 :         pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
    7064           0 :         if (!bgp_dest_has_bgp_path_info_data(pdest))
    7065           0 :                 bgp_dest_set_bgp_table_info(pdest,
    7066             :                                             bgp_table_init(bgp, afi, safi));
    7067             :         else
    7068           0 :                 bgp_dest_unlock_node(pdest);
    7069           0 :         table = bgp_dest_get_bgp_table_info(pdest);
    7070             : 
    7071           0 :         dest = bgp_node_lookup(table, &p);
    7072             : 
    7073           0 :         if (dest) {
    7074           0 :                 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
    7075             : 
    7076           0 :                 bgp_static = bgp_dest_get_bgp_static_info(dest);
    7077           0 :                 bgp_static_free(bgp_static);
    7078           0 :                 bgp_dest_set_bgp_static_info(dest, NULL);
    7079           0 :                 bgp_dest_unlock_node(dest);
    7080           0 :                 bgp_dest_unlock_node(dest);
    7081             :         } else
    7082           0 :                 vty_out(vty, "%% Can't find the route\n");
    7083             : 
    7084             :         return CMD_SUCCESS;
    7085             : }
    7086             : 
    7087           0 : static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
    7088             :                              const char *rmap_name)
    7089             : {
    7090           0 :         VTY_DECLVAR_CONTEXT(bgp, bgp);
    7091           0 :         struct bgp_rmap *rmap;
    7092             : 
    7093           0 :         rmap = &bgp->table_map[afi][safi];
    7094           0 :         if (rmap_name) {
    7095           0 :                 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
    7096           0 :                 route_map_counter_decrement(rmap->map);
    7097           0 :                 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
    7098           0 :                 rmap->map = route_map_lookup_by_name(rmap_name);
    7099           0 :                 route_map_counter_increment(rmap->map);
    7100             :         } else {
    7101           0 :                 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
    7102           0 :                 route_map_counter_decrement(rmap->map);
    7103           0 :                 rmap->map = NULL;
    7104             :         }
    7105             : 
    7106           0 :         if (bgp_fibupd_safi(safi))
    7107           0 :                 bgp_zebra_announce_table(bgp, afi, safi);
    7108             : 
    7109             :         return CMD_SUCCESS;
    7110             : }
    7111             : 
    7112           0 : static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
    7113             :                                const char *rmap_name)
    7114             : {
    7115           0 :         VTY_DECLVAR_CONTEXT(bgp, bgp);
    7116           0 :         struct bgp_rmap *rmap;
    7117             : 
    7118           0 :         rmap = &bgp->table_map[afi][safi];
    7119           0 :         XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
    7120           0 :         route_map_counter_decrement(rmap->map);
    7121           0 :         rmap->map = NULL;
    7122             : 
    7123           0 :         if (bgp_fibupd_safi(safi))
    7124           0 :                 bgp_zebra_announce_table(bgp, afi, safi);
    7125             : 
    7126             :         return CMD_SUCCESS;
    7127             : }
    7128             : 
    7129           0 : void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
    7130             :                                 safi_t safi)
    7131             : {
    7132           0 :         if (bgp->table_map[afi][safi].name) {
    7133           0 :                 vty_out(vty, "  table-map %s\n",
    7134             :                         bgp->table_map[afi][safi].name);
    7135             :         }
    7136           0 : }
    7137             : 
    7138           0 : DEFUN (bgp_table_map,
    7139             :        bgp_table_map_cmd,
    7140             :        "table-map WORD",
    7141             :        "BGP table to RIB route download filter\n"
    7142             :        "Name of the route map\n")
    7143             : {
    7144           0 :         int idx_word = 1;
    7145           0 :         return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
    7146           0 :                                  argv[idx_word]->arg);
    7147             : }
    7148           0 : DEFUN (no_bgp_table_map,
    7149             :        no_bgp_table_map_cmd,
    7150             :        "no table-map WORD",
    7151             :        NO_STR
    7152             :        "BGP table to RIB route download filter\n"
    7153             :        "Name of the route map\n")
    7154             : {
    7155           0 :         int idx_word = 2;
    7156           0 :         return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
    7157           0 :                                    argv[idx_word]->arg);
    7158             : }
    7159             : 
    7160           0 : DEFPY(bgp_network,
    7161             :         bgp_network_cmd,
    7162             :         "[no] network \
    7163             :         <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
    7164             :         [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
    7165             :         backdoor$backdoor}]",
    7166             :         NO_STR
    7167             :         "Specify a network to announce via BGP\n"
    7168             :         "IPv4 prefix\n"
    7169             :         "Network number\n"
    7170             :         "Network mask\n"
    7171             :         "Network mask\n"
    7172             :         "Route-map to modify the attributes\n"
    7173             :         "Name of the route map\n"
    7174             :         "Label index to associate with the prefix\n"
    7175             :         "Label index value\n"
    7176             :         "Specify a BGP backdoor route\n")
    7177             : {
    7178           0 :         char addr_prefix_str[BUFSIZ];
    7179             : 
    7180           0 :         if (address_str) {
    7181           0 :                 int ret;
    7182             : 
    7183           0 :                 ret = netmask_str2prefix_str(address_str, netmask_str,
    7184             :                                              addr_prefix_str,
    7185             :                                              sizeof(addr_prefix_str));
    7186           0 :                 if (!ret) {
    7187           0 :                         vty_out(vty, "%% Inconsistent address and mask\n");
    7188           0 :                         return CMD_WARNING_CONFIG_FAILED;
    7189             :                 }
    7190             :         }
    7191             : 
    7192           0 :         return bgp_static_set(
    7193             :                 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
    7194             :                 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
    7195             :                 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
    7196             : }
    7197             : 
    7198           0 : DEFPY(ipv6_bgp_network,
    7199             :         ipv6_bgp_network_cmd,
    7200             :         "[no] network X:X::X:X/M$prefix \
    7201             :         [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
    7202             :         NO_STR
    7203             :         "Specify a network to announce via BGP\n"
    7204             :         "IPv6 prefix\n"
    7205             :         "Route-map to modify the attributes\n"
    7206             :         "Name of the route map\n"
    7207             :         "Label index to associate with the prefix\n"
    7208             :         "Label index value\n")
    7209             : {
    7210           0 :         return bgp_static_set(
    7211             :                 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
    7212             :                 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
    7213             : }
    7214             : 
    7215           0 : static struct bgp_aggregate *bgp_aggregate_new(void)
    7216             : {
    7217           0 :         return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
    7218             : }
    7219             : 
    7220           0 : static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
    7221             : {
    7222           0 :         XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
    7223           0 :         route_map_counter_decrement(aggregate->suppress_map);
    7224           0 :         XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
    7225           0 :         route_map_counter_decrement(aggregate->rmap.map);
    7226           0 :         XFREE(MTYPE_BGP_AGGREGATE, aggregate);
    7227           0 : }
    7228             : 
    7229             : /**
    7230             :  * Helper function to avoid repeated code: prepare variables for a
    7231             :  * `route_map_apply` call.
    7232             :  *
    7233             :  * \returns `true` on route map match, otherwise `false`.
    7234             :  */
    7235           0 : static bool aggr_suppress_map_test(struct bgp *bgp,
    7236             :                                    struct bgp_aggregate *aggregate,
    7237             :                                    struct bgp_path_info *pi)
    7238             : {
    7239           0 :         const struct prefix *p = bgp_dest_get_prefix(pi->net);
    7240           0 :         route_map_result_t rmr = RMAP_DENYMATCH;
    7241           0 :         struct bgp_path_info rmap_path = {};
    7242           0 :         struct attr attr = {};
    7243             : 
    7244             :         /* No route map entries created, just don't match. */
    7245           0 :         if (aggregate->suppress_map == NULL)
    7246             :                 return false;
    7247             : 
    7248             :         /* Call route map matching and return result. */
    7249           0 :         attr.aspath = aspath_empty();
    7250           0 :         rmap_path.peer = bgp->peer_self;
    7251           0 :         rmap_path.attr = &attr;
    7252             : 
    7253           0 :         SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
    7254           0 :         rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
    7255           0 :         bgp->peer_self->rmap_type = 0;
    7256             : 
    7257           0 :         bgp_attr_flush(&attr);
    7258           0 :         aspath_unintern(&attr.aspath);
    7259             : 
    7260           0 :         return rmr == RMAP_PERMITMATCH;
    7261             : }
    7262             : 
    7263             : /** Test whether the aggregation has suppressed this path or not. */
    7264           0 : static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
    7265             :                                  struct bgp_path_info *pi)
    7266             : {
    7267           0 :         if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
    7268             :                 return false;
    7269             : 
    7270           0 :         return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
    7271             : }
    7272             : 
    7273             : /**
    7274             :  * Suppress this path and keep the reference.
    7275             :  *
    7276             :  * \returns `true` if needs processing otherwise `false`.
    7277             :  */
    7278           0 : static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
    7279             :                                struct bgp_path_info *pi)
    7280             : {
    7281           0 :         struct bgp_path_info_extra *pie;
    7282             : 
    7283             :         /* Path is already suppressed by this aggregation. */
    7284           0 :         if (aggr_suppress_exists(aggregate, pi))
    7285             :                 return false;
    7286             : 
    7287           0 :         pie = bgp_path_info_extra_get(pi);
    7288             : 
    7289             :         /* This is the first suppression, allocate memory and list it. */
    7290           0 :         if (pie->aggr_suppressors == NULL)
    7291           0 :                 pie->aggr_suppressors = list_new();
    7292             : 
    7293           0 :         listnode_add(pie->aggr_suppressors, aggregate);
    7294             : 
    7295             :         /* Only mark for processing if suppressed. */
    7296           0 :         if (listcount(pie->aggr_suppressors) == 1) {
    7297           0 :                 if (BGP_DEBUG(update, UPDATE_OUT))
    7298           0 :                         zlog_debug("aggregate-address suppressing: %pFX",
    7299             :                                    bgp_dest_get_prefix(pi->net));
    7300             : 
    7301           0 :                 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
    7302           0 :                 return true;
    7303             :         }
    7304             : 
    7305             :         return false;
    7306             : }
    7307             : 
    7308             : /**
    7309             :  * Unsuppress this path and remove the reference.
    7310             :  *
    7311             :  * \returns `true` if needs processing otherwise `false`.
    7312             :  */
    7313           0 : static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
    7314             :                                  struct bgp_path_info *pi)
    7315             : {
    7316             :         /* Path wasn't suppressed. */
    7317           0 :         if (!aggr_suppress_exists(aggregate, pi))
    7318             :                 return false;
    7319             : 
    7320           0 :         listnode_delete(pi->extra->aggr_suppressors, aggregate);
    7321             : 
    7322             :         /* Unsuppress and free extra memory if last item. */
    7323           0 :         if (listcount(pi->extra->aggr_suppressors) == 0) {
    7324           0 :                 if (BGP_DEBUG(update, UPDATE_OUT))
    7325           0 :                         zlog_debug("aggregate-address unsuppressing: %pFX",
    7326             :                                    bgp_dest_get_prefix(pi->net));
    7327             : 
    7328           0 :                 list_delete(&pi->extra->aggr_suppressors);
    7329           0 :                 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
    7330           0 :                 return true;
    7331             :         }
    7332             : 
    7333             :         return false;
    7334             : }
    7335             : 
    7336           0 : static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
    7337             :                                     struct aspath *aspath,
    7338             :                                     struct community *comm,
    7339             :                                     struct ecommunity *ecomm,
    7340             :                                     struct lcommunity *lcomm)
    7341             : {
    7342           0 :         static struct aspath *ae = NULL;
    7343             : 
    7344           0 :         if (!ae)
    7345           0 :                 ae = aspath_empty();
    7346             : 
    7347           0 :         if (!pi)
    7348             :                 return false;
    7349             : 
    7350           0 :         if (origin != pi->attr->origin)
    7351             :                 return false;
    7352             : 
    7353           0 :         if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
    7354             :                 return false;
    7355             : 
    7356           0 :         if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
    7357             :                 return false;
    7358             : 
    7359           0 :         if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
    7360             :                 return false;
    7361             : 
    7362           0 :         if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
    7363             :                 return false;
    7364             : 
    7365           0 :         if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
    7366             :                 return false;
    7367             : 
    7368             :         return true;
    7369             : }
    7370             : 
    7371           0 : static void bgp_aggregate_install(
    7372             :         struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
    7373             :         uint8_t origin, struct aspath *aspath, struct community *community,
    7374             :         struct ecommunity *ecommunity, struct lcommunity *lcommunity,
    7375             :         uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
    7376             : {
    7377           0 :         struct bgp_dest *dest;
    7378           0 :         struct bgp_table *table;
    7379           0 :         struct bgp_path_info *pi, *orig, *new;
    7380           0 :         struct attr *attr;
    7381             : 
    7382           0 :         table = bgp->rib[afi][safi];
    7383             : 
    7384           0 :         dest = bgp_node_get(table, p);
    7385             : 
    7386           0 :         for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
    7387           0 :                 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
    7388           0 :                     && pi->sub_type == BGP_ROUTE_AGGREGATE)
    7389             :                         break;
    7390             : 
    7391             :         /*
    7392             :          * If we have paths with different MEDs, then don't install
    7393             :          * (or uninstall) the aggregate route.
    7394             :          */
    7395           0 :         if (aggregate->match_med && aggregate->med_mismatched)
    7396           0 :                 goto uninstall_aggregate_route;
    7397             : 
    7398           0 :         if (aggregate->count > 0) {
    7399             :                 /*
    7400             :                  * If the aggregate information has not changed
    7401             :                  * no need to re-install it again.
    7402             :                  */
    7403           0 :                 if (bgp_aggregate_info_same(orig, origin, aspath, community,
    7404             :                                             ecommunity, lcommunity)) {
    7405           0 :                         bgp_dest_unlock_node(dest);
    7406             : 
    7407           0 :                         if (aspath)
    7408           0 :                                 aspath_free(aspath);
    7409           0 :                         if (community)
    7410           0 :                                 community_free(&community);
    7411           0 :                         if (ecommunity)
    7412           0 :                                 ecommunity_free(&ecommunity);
    7413           0 :                         if (lcommunity)
    7414           0 :                                 lcommunity_free(&lcommunity);
    7415             : 
    7416           0 :                         return;
    7417             :                 }
    7418             : 
    7419             :                 /*
    7420             :                  * Mark the old as unusable
    7421             :                  */
    7422           0 :                 if (pi)
    7423           0 :                         bgp_path_info_delete(dest, pi);
    7424             : 
    7425           0 :                 attr = bgp_attr_aggregate_intern(
    7426             :                         bgp, origin, aspath, community, ecommunity, lcommunity,
    7427             :                         aggregate, atomic_aggregate, p);
    7428             : 
    7429           0 :                 if (!attr) {
    7430           0 :                         bgp_dest_unlock_node(dest);
    7431           0 :                         bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
    7432           0 :                         if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
    7433           0 :                                 zlog_debug("%s: %pFX null attribute", __func__,
    7434             :                                            p);
    7435           0 :                         return;
    7436             :                 }
    7437             : 
    7438           0 :                 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
    7439             :                                 bgp->peer_self, attr, dest);
    7440             : 
    7441           0 :                 SET_FLAG(new->flags, BGP_PATH_VALID);
    7442             : 
    7443           0 :                 bgp_path_info_add(dest, new);
    7444           0 :                 bgp_process(bgp, dest, afi, safi);
    7445             :         } else {
    7446           0 :         uninstall_aggregate_route:
    7447           0 :                 for (pi = orig; pi; pi = pi->next)
    7448           0 :                         if (pi->peer == bgp->peer_self
    7449             :                             && pi->type == ZEBRA_ROUTE_BGP
    7450           0 :                             && pi->sub_type == BGP_ROUTE_AGGREGATE)
    7451             :                                 break;
    7452             : 
    7453             :                 /* Withdraw static BGP route from routing table. */
    7454           0 :                 if (pi) {
    7455           0 :                         bgp_path_info_delete(dest, pi);
    7456           0 :                         bgp_process(bgp, dest, afi, safi);
    7457             :                 }
    7458             :         }
    7459             : 
    7460           0 :         bgp_dest_unlock_node(dest);
    7461             : }
    7462             : 
    7463             : /**
    7464             :  * Check if the current path has different MED than other known paths.
    7465             :  *
    7466             :  * \returns `true` if the MED matched the others else `false`.
    7467             :  */
    7468           0 : static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
    7469             :                                     struct bgp *bgp, struct bgp_path_info *pi)
    7470             : {
    7471           0 :         uint32_t cur_med = bgp_med_value(pi->attr, bgp);
    7472             : 
    7473             :         /* This is the first route being analyzed. */
    7474           0 :         if (!aggregate->med_initialized) {
    7475           0 :                 aggregate->med_initialized = true;
    7476           0 :                 aggregate->med_mismatched = false;
    7477           0 :                 aggregate->med_matched_value = cur_med;
    7478             :         } else {
    7479             :                 /* Check if routes with different MED showed up. */
    7480           0 :                 if (cur_med != aggregate->med_matched_value)
    7481           0 :                         aggregate->med_mismatched = true;
    7482             :         }
    7483             : 
    7484           0 :         return !aggregate->med_mismatched;
    7485             : }
    7486             : 
    7487             : /**
    7488             :  * Initializes and tests all routes in the aggregate address path for MED
    7489             :  * values.
    7490             :  *
    7491             :  * \returns `true` if all MEDs are the same otherwise `false`.
    7492             :  */
    7493           0 : static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
    7494             :                                        struct bgp *bgp, const struct prefix *p,
    7495             :                                        afi_t afi, safi_t safi)
    7496             : {
    7497           0 :         struct bgp_table *table = bgp->rib[afi][safi];
    7498           0 :         const struct prefix *dest_p;
    7499           0 :         struct bgp_dest *dest, *top;
    7500           0 :         struct bgp_path_info *pi;
    7501           0 :         bool med_matched = true;
    7502             : 
    7503           0 :         aggregate->med_initialized = false;
    7504             : 
    7505           0 :         top = bgp_node_get(table, p);
    7506           0 :         for (dest = bgp_node_get(table, p); dest;
    7507           0 :              dest = bgp_route_next_until(dest, top)) {
    7508           0 :                 dest_p = bgp_dest_get_prefix(dest);
    7509           0 :                 if (dest_p->prefixlen <= p->prefixlen)
    7510           0 :                         continue;
    7511             : 
    7512           0 :                 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
    7513           0 :                         if (BGP_PATH_HOLDDOWN(pi))
    7514           0 :                                 continue;
    7515           0 :                         if (pi->sub_type == BGP_ROUTE_AGGREGATE)
    7516           0 :                                 continue;
    7517           0 :                         if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
    7518             :                                 med_matched = false;
    7519             :                                 break;
    7520             :                         }
    7521             :                 }
    7522           0 :                 if (!med_matched)
    7523             :                         break;
    7524             :         }
    7525           0 :         bgp_dest_unlock_node(top);
    7526             : 
    7527           0 :         return med_matched;
    7528             : }
    7529             : 
    7530             : /**
    7531             :  * Toggles the route suppression status for this aggregate address
    7532             :  * configuration.
    7533             :  */
    7534           0 : void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
    7535             :                                      struct bgp *bgp, const struct prefix *p,
    7536             :                                      afi_t afi, safi_t safi, bool suppress)
    7537             : {
    7538           0 :         struct bgp_table *table = bgp->rib[afi][safi];
    7539           0 :         const struct prefix *dest_p;
    7540           0 :         struct bgp_dest *dest, *top;
    7541           0 :         struct bgp_path_info *pi;
    7542           0 :         bool toggle_suppression;
    7543             : 
    7544             :         /* We've found a different MED we must revert any suppressed routes. */
    7545           0 :         top = bgp_node_get(table, p);
    7546           0 :         for (dest = bgp_node_get(table, p); dest;
    7547           0 :              dest = bgp_route_next_until(dest, top)) {
    7548           0 :                 dest_p = bgp_dest_get_prefix(dest);
    7549           0 :                 if (dest_p->prefixlen <= p->prefixlen)
    7550           0 :                         continue;
    7551             : 
    7552           0 :                 toggle_suppression = false;
    7553           0 :                 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
    7554           0 :                         if (BGP_PATH_HOLDDOWN(pi))
    7555           0 :                                 continue;
    7556           0 :                         if (pi->sub_type == BGP_ROUTE_AGGREGATE)
    7557           0 :                                 continue;
    7558             : 
    7559             :                         /* We are toggling suppression back. */
    7560           0 :                         if (suppress) {
    7561             :                                 /* Suppress route if not suppressed already. */
    7562           0 :                                 if (aggr_suppress_path(aggregate, pi))
    7563           0 :                                         toggle_suppression = true;
    7564           0 :                                 continue;
    7565             :                         }
    7566             : 
    7567             :                         /* Install route if there is no more suppression. */
    7568           0 :                         if (aggr_unsuppress_path(aggregate, pi))
    7569           0 :                                 toggle_suppression = true;
    7570             :                 }
    7571             : 
    7572           0 :                 if (toggle_suppression)
    7573           0 :                         bgp_process(bgp, dest, afi, safi);
    7574             :         }
    7575           0 :         bgp_dest_unlock_node(top);
    7576           0 : }
    7577             : 
    7578             : /**
    7579             :  * Aggregate address MED matching incremental test: this function is called
    7580             :  * when the initial aggregation occurred and we are only testing a single
    7581             :  * new path.
    7582             :  *
    7583             :  * In addition to testing and setting the MED validity it also installs back
    7584             :  * suppressed routes (if summary is configured).
    7585             :  *
    7586             :  * Must not be called in `bgp_aggregate_route`.
    7587             :  */
    7588           0 : static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
    7589             :                                      struct bgp *bgp, const struct prefix *p,
    7590             :                                      afi_t afi, safi_t safi,
    7591             :                                      struct bgp_path_info *pi)
    7592             : {
    7593             :         /* MED matching disabled. */
    7594           0 :         if (!aggregate->match_med)
    7595             :                 return;
    7596             : 
    7597             :         /* Aggregation with different MED, recheck if we have got equal MEDs
    7598             :          * now.
    7599             :          */
    7600           0 :         if (aggregate->med_mismatched &&
    7601           0 :             bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi) &&
    7602           0 :             aggregate->summary_only)
    7603           0 :                 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi,
    7604             :                                                 true);
    7605             :         else
    7606           0 :                 bgp_aggregate_med_match(aggregate, bgp, pi);
    7607             : 
    7608             :         /* No mismatches, just quit. */
    7609           0 :         if (!aggregate->med_mismatched)
    7610             :                 return;
    7611             : 
    7612             :         /* Route summarization is disabled. */
    7613           0 :         if (!aggregate->summary_only)
    7614             :                 return;
    7615             : 
    7616           0 :         bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
    7617             : }
    7618             : 
    7619             : /* Update an aggregate as routes are added/removed from the BGP table */
    7620           0 : void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
    7621             :                          safi_t safi, struct bgp_aggregate *aggregate)
    7622             : {
    7623           0 :         struct bgp_table *table;
    7624           0 :         struct bgp_dest *top;
    7625           0 :         struct bgp_dest *dest;
    7626           0 :         uint8_t origin;
    7627           0 :         struct aspath *aspath = NULL;
    7628           0 :         struct community *community = NULL;
    7629           0 :         struct ecommunity *ecommunity = NULL;
    7630           0 :         struct lcommunity *lcommunity = NULL;
    7631           0 :         struct bgp_path_info *pi;
    7632           0 :         unsigned long match = 0;
    7633           0 :         uint8_t atomic_aggregate = 0;
    7634             : 
    7635             :         /* If the bgp instance is being deleted or self peer is deleted
    7636             :          * then do not create aggregate route
    7637             :          */
    7638           0 :         if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
    7639           0 :             || (bgp->peer_self == NULL))
    7640             :                 return;
    7641             : 
    7642             :         /* Initialize and test routes for MED difference. */
    7643           0 :         if (aggregate->match_med)
    7644           0 :                 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
    7645             : 
    7646             :         /*
    7647             :          * Reset aggregate count: we might've been called from route map
    7648             :          * update so in that case we must retest all more specific routes.
    7649             :          *
    7650             :          * \see `bgp_route_map_process_update`.
    7651             :          */
    7652           0 :         aggregate->count = 0;
    7653           0 :         aggregate->incomplete_origin_count = 0;
    7654           0 :         aggregate->incomplete_origin_count = 0;
    7655           0 :         aggregate->egp_origin_count = 0;
    7656             : 
    7657             :         /* ORIGIN attribute: If at least one route among routes that are
    7658             :            aggregated has ORIGIN with the value INCOMPLETE, then the
    7659             :            aggregated route must have the ORIGIN attribute with the value
    7660             :            INCOMPLETE. Otherwise, if at least one route among routes that
    7661             :            are aggregated has ORIGIN with the value EGP, then the aggregated
    7662             :            route must have the origin attribute with the value EGP. In all
    7663             :            other case the value of the ORIGIN attribute of the aggregated
    7664             :            route is INTERNAL. */
    7665           0 :         origin = BGP_ORIGIN_IGP;
    7666             : 
    7667           0 :         table = bgp->rib[afi][safi];
    7668             : 
    7669           0 :         top = bgp_node_get(table, p);
    7670           0 :         for (dest = bgp_node_get(table, p); dest;
    7671           0 :              dest = bgp_route_next_until(dest, top)) {
    7672           0 :                 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
    7673             : 
    7674           0 :                 if (dest_p->prefixlen <= p->prefixlen)
    7675           0 :                         continue;
    7676             : 
    7677             :                 /* If suppress fib is enabled and route not installed
    7678             :                  * in FIB, skip the route
    7679             :                  */
    7680           0 :                 if (!bgp_check_advertise(bgp, dest))
    7681           0 :                         continue;
    7682             : 
    7683           0 :                 match = 0;
    7684             : 
    7685           0 :                 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
    7686           0 :                         if (BGP_PATH_HOLDDOWN(pi))
    7687           0 :                                 continue;
    7688             : 
    7689           0 :                         if (pi->attr->flag
    7690           0 :                             & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
    7691           0 :                                 atomic_aggregate = 1;
    7692             : 
    7693           0 :                         if (pi->sub_type == BGP_ROUTE_AGGREGATE)
    7694           0 :                                 continue;
    7695             : 
    7696             :                         /*
    7697             :                          * summary-only aggregate route suppress
    7698             :                          * aggregated route announcements.
    7699             :                          *
    7700             :                          * MED matching:
    7701             :                          * Don't create summaries if MED didn't match
    7702             :                          * otherwise neither the specific routes and the
    7703             :                          * aggregation will be announced.
    7704             :                          */
    7705           0 :                         if (aggregate->summary_only
    7706           0 :                             && AGGREGATE_MED_VALID(aggregate)) {
    7707           0 :                                 if (aggr_suppress_path(aggregate, pi))
    7708           0 :                                         match++;
    7709             :                         }
    7710             : 
    7711             :                         /*
    7712             :                          * Suppress more specific routes that match the route
    7713             :                          * map results.
    7714             :                          *
    7715             :                          * MED matching:
    7716             :                          * Don't suppress routes if MED matching is enabled and
    7717             :                          * it mismatched otherwise we might end up with no
    7718             :                          * routes for this path.
    7719             :                          */
    7720           0 :                         if (aggregate->suppress_map_name
    7721           0 :                             && AGGREGATE_MED_VALID(aggregate)
    7722           0 :                             && aggr_suppress_map_test(bgp, aggregate, pi)) {
    7723           0 :                                 if (aggr_suppress_path(aggregate, pi))
    7724           0 :                                         match++;
    7725             :                         }
    7726             : 
    7727           0 :                         aggregate->count++;
    7728             : 
    7729             :                         /*
    7730             :                         * If at least one route among routes that are
    7731             :                         * aggregated has ORIGIN with the value INCOMPLETE,
    7732             :                         * then the aggregated route MUST have the ORIGIN
    7733             :                         * attribute with the value INCOMPLETE.  Otherwise, if
    7734             :                         * at least one route among routes that are aggregated
    7735             :                         * has ORIGIN with the value EGP, then the aggregated
    7736             :                         * route MUST have the ORIGIN attribute with the value
    7737             :                         * EGP.
    7738             :                         */
    7739           0 :                         switch (pi->attr->origin) {
    7740           0 :                         case BGP_ORIGIN_INCOMPLETE:
    7741           0 :                                 aggregate->incomplete_origin_count++;
    7742           0 :                         break;
    7743           0 :                         case BGP_ORIGIN_EGP:
    7744           0 :                                 aggregate->egp_origin_count++;
    7745           0 :                         break;
    7746             :                         default:
    7747             :                                 /*Do nothing.
    7748             :                                  */
    7749             :                         break;
    7750             :                         }
    7751             : 
    7752           0 :                         if (!aggregate->as_set)
    7753           0 :                                 continue;
    7754             : 
    7755             :                         /*
    7756             :                          * as-set aggregate route generate origin, as path,
    7757             :                          * and community aggregation.
    7758             :                          */
    7759             :                         /* Compute aggregate route's as-path.
    7760             :                          */
    7761           0 :                         bgp_compute_aggregate_aspath_hash(aggregate,
    7762             :                                                           pi->attr->aspath);
    7763             : 
    7764             :                         /* Compute aggregate route's community.
    7765             :                          */
    7766           0 :                         if (bgp_attr_get_community(pi->attr))
    7767           0 :                                 bgp_compute_aggregate_community_hash(
    7768             :                                         aggregate,
    7769           0 :                                         bgp_attr_get_community(pi->attr));
    7770             : 
    7771             :                         /* Compute aggregate route's extended community.
    7772             :                          */
    7773           0 :                         if (bgp_attr_get_ecommunity(pi->attr))
    7774           0 :                                 bgp_compute_aggregate_ecommunity_hash(
    7775             :                                         aggregate,
    7776           0 :                                         bgp_attr_get_ecommunity(pi->attr));
    7777             : 
    7778             :                         /* Compute aggregate route's large community.
    7779             :                          */
    7780           0 :                         if (bgp_attr_get_lcommunity(pi->attr))
    7781           0 :                                 bgp_compute_aggregate_lcommunity_hash(
    7782             :                                         aggregate,
    7783           0 :                                         bgp_attr_get_lcommunity(pi->attr));
    7784             :                 }
    7785           0 :                 if (match)
    7786           0 :                         bgp_process(bgp, dest, afi, safi);
    7787             :         }
    7788           0 :         if (aggregate->as_set) {
    7789           0 :                 bgp_compute_aggregate_aspath_val(aggregate);
    7790           0 :                 bgp_compute_aggregate_community_val(aggregate);
    7791           0 :                 bgp_compute_aggregate_ecommunity_val(aggregate);
    7792           0 :                 bgp_compute_aggregate_lcommunity_val(aggregate);
    7793             :         }
    7794             : 
    7795             : 
    7796           0 :         bgp_dest_unlock_node(top);
    7797             : 
    7798             : 
    7799           0 :         if (aggregate->incomplete_origin_count > 0)
    7800             :                 origin = BGP_ORIGIN_INCOMPLETE;
    7801           0 :         else if (aggregate->egp_origin_count > 0)
    7802           0 :                 origin = BGP_ORIGIN_EGP;
    7803             : 
    7804           0 :         if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
    7805           0 :                 origin = aggregate->origin;
    7806             : 
    7807           0 :         if (aggregate->as_set) {
    7808           0 :                 if (aggregate->aspath)
    7809             :                         /* Retrieve aggregate route's as-path.
    7810             :                          */
    7811           0 :                         aspath = aspath_dup(aggregate->aspath);
    7812             : 
    7813           0 :                 if (aggregate->community)
    7814             :                         /* Retrieve aggregate route's community.
    7815             :                          */
    7816           0 :                         community = community_dup(aggregate->community);
    7817             : 
    7818           0 :                 if (aggregate->ecommunity)
    7819             :                         /* Retrieve aggregate route's ecommunity.
    7820             :                          */
    7821           0 :                         ecommunity = ecommunity_dup(aggregate->ecommunity);
    7822             : 
    7823           0 :                 if (aggregate->lcommunity)
    7824             :                         /* Retrieve aggregate route's lcommunity.
    7825             :                          */
    7826           0 :                         lcommunity = lcommunity_dup(aggregate->lcommunity);
    7827             :         }
    7828             : 
    7829           0 :         bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
    7830             :                               ecommunity, lcommunity, atomic_aggregate,
    7831             :                               aggregate);
    7832             : }
    7833             : 
    7834           0 : void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
    7835             :                           safi_t safi, struct bgp_aggregate *aggregate)
    7836             : {
    7837           0 :         struct bgp_table *table;
    7838           0 :         struct bgp_dest *top;
    7839           0 :         struct bgp_dest *dest;
    7840           0 :         struct bgp_path_info *pi;
    7841           0 :         unsigned long match;
    7842             : 
    7843           0 :         table = bgp->rib[afi][safi];
    7844             : 
    7845             :         /* If routes exists below this node, generate aggregate routes. */
    7846           0 :         top = bgp_node_get(table, p);
    7847           0 :         for (dest = bgp_node_get(table, p); dest;
    7848           0 :              dest = bgp_route_next_until(dest, top)) {
    7849           0 :                 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
    7850             : 
    7851           0 :                 if (dest_p->prefixlen <= p->prefixlen)
    7852           0 :                         continue;
    7853           0 :                 match = 0;
    7854             : 
    7855           0 :                 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
    7856           0 :                         if (BGP_PATH_HOLDDOWN(pi))
    7857           0 :                                 continue;
    7858             : 
    7859           0 :                         if (pi->sub_type == BGP_ROUTE_AGGREGATE)
    7860           0 :                                 continue;
    7861             : 
    7862             :                         /*
    7863             :                          * This route is suppressed: attempt to unsuppress it.
    7864             :                          *
    7865             :                          * `aggr_unsuppress_path` will fail if this particular
    7866             :                          * aggregate route was not the suppressor.
    7867             :                          */
    7868           0 :                         if (pi->extra && pi->extra->aggr_suppressors &&
    7869           0 :                             listcount(pi->extra->aggr_suppressors)) {
    7870           0 :                                 if (aggr_unsuppress_path(aggregate, pi))
    7871           0 :                                         match++;
    7872             :                         }
    7873             : 
    7874           0 :                         aggregate->count--;
    7875             : 
    7876           0 :                         if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
    7877           0 :                                 aggregate->incomplete_origin_count--;
    7878           0 :                         else if (pi->attr->origin == BGP_ORIGIN_EGP)
    7879           0 :                                 aggregate->egp_origin_count--;
    7880             : 
    7881           0 :                         if (aggregate->as_set) {
    7882             :                                 /* Remove as-path from aggregate.
    7883             :                                  */
    7884           0 :                                 bgp_remove_aspath_from_aggregate_hash(
    7885             :                                                         aggregate,
    7886             :                                                         pi->attr->aspath);
    7887             : 
    7888           0 :                                 if (bgp_attr_get_community(pi->attr))
    7889             :                                         /* Remove community from aggregate.
    7890             :                                          */
    7891           0 :                                         bgp_remove_comm_from_aggregate_hash(
    7892             :                                                 aggregate,
    7893             :                                                 bgp_attr_get_community(
    7894           0 :                                                         pi->attr));
    7895             : 
    7896           0 :                                 if (bgp_attr_get_ecommunity(pi->attr))
    7897             :                                         /* Remove ecommunity from aggregate.
    7898             :                                          */
    7899           0 :                                         bgp_remove_ecomm_from_aggregate_hash(
    7900             :                                                 aggregate,
    7901             :                                                 bgp_attr_get_ecommunity(
    7902           0 :                                                         pi->attr));
    7903             : 
    7904           0 :                                 if (bgp_attr_get_lcommunity(pi->attr))
    7905             :                                         /* Remove lcommunity from aggregate.
    7906             :                                          */
    7907           0 :                                         bgp_remove_lcomm_from_aggregate_hash(
    7908             :                                                 aggregate,
    7909             :                                                 bgp_attr_get_lcommunity(
    7910           0 :                                                         pi->attr));
    7911             :                         }
    7912             :                 }
    7913             : 
    7914             :                 /* If this node was suppressed, process the change. */
    7915           0 :                 if (match)
    7916           0 :                         bgp_process(bgp, dest, afi, safi);
    7917             :         }
    7918           0 :         if (aggregate->as_set) {
    7919           0 :                 aspath_free(aggregate->aspath);
    7920           0 :                 aggregate->aspath = NULL;
    7921           0 :                 if (aggregate->community)
    7922           0 :                         community_free(&aggregate->community);
    7923           0 :                 if (aggregate->ecommunity)
    7924           0 :                         ecommunity_free(&aggregate->ecommunity);
    7925           0 :                 if (aggregate->lcommunity)
    7926           0 :                         lcommunity_free(&aggregate->lcommunity);
    7927             :         }
    7928             : 
    7929           0 :         bgp_dest_unlock_node(top);
    7930           0 : }
    7931             : 
    7932           0 : static void bgp_add_route_to_aggregate(struct bgp *bgp,
    7933             :                                        const struct prefix *aggr_p,
    7934             :                                        struct bgp_path_info *pinew, afi_t afi,
    7935             :                                        safi_t safi,
    7936             :                                        struct bgp_aggregate *aggregate)
    7937             : {
    7938           0 :         uint8_t origin;
    7939           0 :         struct aspath *aspath = NULL;
    7940           0 :         uint8_t atomic_aggregate = 0;
    7941           0 :         struct community *community = NULL;
    7942           0 :         struct ecommunity *ecommunity = NULL;
    7943           0 :         struct lcommunity *lcommunity = NULL;
    7944             : 
    7945             :         /* If the bgp instance is being deleted or self peer is deleted
    7946             :          * then do not create aggregate route
    7947             :          */
    7948           0 :         if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
    7949           0 :             || (bgp->peer_self == NULL))
    7950             :                 return;
    7951             : 
    7952             :         /* ORIGIN attribute: If at least one route among routes that are
    7953             :          * aggregated has ORIGIN with the value INCOMPLETE, then the
    7954             :          * aggregated route must have the ORIGIN attribute with the value
    7955             :          * INCOMPLETE. Otherwise, if at least one route among routes that
    7956             :          * are aggregated has ORIGIN with the value EGP, then the aggregated
    7957             :          * route must have the origin attribute with the value EGP. In all
    7958             :          * other case the value of the ORIGIN attribute of the aggregated
    7959             :          * route is INTERNAL.
    7960             :          */
    7961           0 :         origin = BGP_ORIGIN_IGP;
    7962             : 
    7963           0 :         aggregate->count++;
    7964             : 
    7965             :         /*
    7966             :          * This must be called before `summary` check to avoid
    7967             :          * "suppressing" twice.
    7968             :          */
    7969           0 :         if (aggregate->match_med)
    7970           0 :                 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
    7971             :                                          pinew);
    7972             : 
    7973           0 :         if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
    7974           0 :                 aggr_suppress_path(aggregate, pinew);
    7975             : 
    7976           0 :         if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
    7977           0 :             && aggr_suppress_map_test(bgp, aggregate, pinew))
    7978           0 :                 aggr_suppress_path(aggregate, pinew);
    7979             : 
    7980           0 :         switch (pinew->attr->origin) {
    7981           0 :         case BGP_ORIGIN_INCOMPLETE:
    7982           0 :                 aggregate->incomplete_origin_count++;
    7983           0 :         break;
    7984           0 :         case BGP_ORIGIN_EGP:
    7985           0 :                 aggregate->egp_origin_count++;
    7986           0 :         break;
    7987             :         default:
    7988             :                 /* Do nothing.
    7989             :                  */
    7990             :         break;
    7991             :         }
    7992             : 
    7993           0 :         if (aggregate->incomplete_origin_count > 0)
    7994             :                 origin = BGP_ORIGIN_INCOMPLETE;
    7995           0 :         else if (aggregate->egp_origin_count > 0)
    7996           0 :                 origin = BGP_ORIGIN_EGP;
    7997             : 
    7998           0 :         if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
    7999           0 :                 origin = aggregate->origin;
    8000             : 
    8001           0 :         if (aggregate->as_set) {
    8002             :                 /* Compute aggregate route's as-path.
    8003             :                  */
    8004           0 :                 bgp_compute_aggregate_aspath(aggregate,
    8005             :                                              pinew->attr->aspath);
    8006             : 
    8007             :                 /* Compute aggregate route's community.
    8008             :                  */
    8009           0 :                 if (bgp_attr_get_community(pinew->attr))
    8010           0 :                         bgp_compute_aggregate_community(
    8011           0 :                                 aggregate, bgp_attr_get_community(pinew->attr));
    8012             : 
    8013             :                 /* Compute aggregate route's extended community.
    8014             :                  */
    8015           0 :                 if (bgp_attr_get_ecommunity(pinew->attr))
    8016           0 :                         bgp_compute_aggregate_ecommunity(
    8017             :                                 aggregate,
    8018           0 :                                 bgp_attr_get_ecommunity(pinew->attr));
    8019             : 
    8020             :                 /* Compute aggregate route's large community.
    8021             :                  */
    8022           0 :                 if (bgp_attr_get_lcommunity(pinew->attr))
    8023           0 :                         bgp_compute_aggregate_lcommunity(
    8024             :                                 aggregate,
    8025           0 :                                 bgp_attr_get_lcommunity(pinew->attr));
    8026             : 
    8027             :                 /* Retrieve aggregate route's as-path.
    8028             :                  */
    8029           0 :                 if (aggregate->aspath)
    8030           0 :                         aspath = aspath_dup(aggregate->aspath);
    8031             : 
    8032             :                 /* Retrieve aggregate route's community.
    8033             :                  */
    8034           0 :                 if (aggregate->community)
    8035           0 :                         community = community_dup(aggregate->community);
    8036             : 
    8037             :                 /* Retrieve aggregate route's ecommunity.
    8038             :                  */
    8039           0 :                 if (aggregate->ecommunity)
    8040           0 :                         ecommunity = ecommunity_dup(aggregate->ecommunity);
    8041             : 
    8042             :                 /* Retrieve aggregate route's lcommunity.
    8043             :                  */
    8044           0 :                 if (aggregate->lcommunity)
    8045           0 :                         lcommunity = lcommunity_dup(aggregate->lcommunity);
    8046             :         }
    8047             : 
    8048           0 :         bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
    8049             :                               aspath, community, ecommunity,
    8050             :                               lcommunity, atomic_aggregate, aggregate);
    8051             : }
    8052             : 
    8053           0 : static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
    8054             :                                             safi_t safi,
    8055             :                                             struct bgp_path_info *pi,
    8056             :                                             struct bgp_aggregate *aggregate,
    8057             :                                             const struct prefix *aggr_p)
    8058             : {
    8059           0 :         uint8_t origin;
    8060           0 :         struct aspath *aspath = NULL;
    8061           0 :         uint8_t atomic_aggregate = 0;
    8062           0 :         struct community *community = NULL;
    8063           0 :         struct ecommunity *ecommunity = NULL;
    8064           0 :         struct lcommunity *lcommunity = NULL;
    8065           0 :         unsigned long match = 0;
    8066             : 
    8067             :         /* If the bgp instance is being deleted or self peer is deleted
    8068             :          * then do not create aggregate route
    8069             :          */
    8070           0 :         if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
    8071           0 :             || (bgp->peer_self == NULL))
    8072             :                 return;
    8073             : 
    8074           0 :         if (BGP_PATH_HOLDDOWN(pi))
    8075             :                 return;
    8076             : 
    8077           0 :         if (pi->sub_type == BGP_ROUTE_AGGREGATE)
    8078             :                 return;
    8079             : 
    8080           0 :         if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
    8081           0 :                 if (aggr_unsuppress_path(aggregate, pi))
    8082           0 :                         match++;
    8083             : 
    8084           0 :         if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
    8085           0 :             && aggr_suppress_map_test(bgp, aggregate, pi))
    8086           0 :                 if (aggr_unsuppress_path(aggregate, pi))
    8087           0 :                         match++;
    8088             : 
    8089             :         /*
    8090             :          * This must be called after `summary`, `suppress-map` check to avoid
    8091             :          * "unsuppressing" twice.
    8092             :          */
    8093           0 :         if (aggregate->match_med)
    8094           0 :                 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi);
    8095             : 
    8096           0 :         if (aggregate->count > 0)
    8097           0 :                 aggregate->count--;
    8098             : 
    8099           0 :         if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
    8100           0 :                 aggregate->incomplete_origin_count--;
    8101           0 :         else if (pi->attr->origin == BGP_ORIGIN_EGP)
    8102           0 :                 aggregate->egp_origin_count--;
    8103             : 
    8104           0 :         if (aggregate->as_set) {
    8105             :                 /* Remove as-path from aggregate.
    8106             :                  */
    8107           0 :                 bgp_remove_aspath_from_aggregate(aggregate,
    8108             :                                                  pi->attr->aspath);
    8109             : 
    8110           0 :                 if (bgp_attr_get_community(pi->attr))
    8111             :                         /* Remove community from aggregate.
    8112             :                          */
    8113           0 :                         bgp_remove_community_from_aggregate(
    8114           0 :                                 aggregate, bgp_attr_get_community(pi->attr));
    8115             : 
    8116           0 :                 if (bgp_attr_get_ecommunity(pi->attr))
    8117             :                         /* Remove ecommunity from aggregate.
    8118             :                          */
    8119           0 :                         bgp_remove_ecommunity_from_aggregate(
    8120           0 :                                 aggregate, bgp_attr_get_ecommunity(pi->attr));
    8121             : 
    8122           0 :                 if (bgp_attr_get_lcommunity(pi->attr))
    8123             :                         /* Remove lcommunity from aggregate.
    8124             :                          */
    8125           0 :                         bgp_remove_lcommunity_from_aggregate(
    8126           0 :                                 aggregate, bgp_attr_get_lcommunity(pi->attr));
    8127             :         }
    8128             : 
    8129             :         /* If this node was suppressed, process the change. */
    8130           0 :         if (match)
    8131           0 :                 bgp_process(bgp, pi->net, afi, safi);
    8132             : 
    8133           0 :         origin = BGP_ORIGIN_IGP;
    8134           0 :         if (aggregate->incomplete_origin_count > 0)
    8135             :                 origin = BGP_ORIGIN_INCOMPLETE;
    8136           0 :         else if (aggregate->egp_origin_count > 0)
    8137           0 :                 origin = BGP_ORIGIN_EGP;
    8138             : 
    8139           0 :         if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
    8140           0 :                 origin = aggregate->origin;
    8141             : 
    8142           0 :         if (aggregate->as_set) {
    8143             :                 /* Retrieve aggregate route's as-path.
    8144             :                  */
    8145           0 :                 if (aggregate->aspath)
    8146           0 :                         aspath = aspath_dup(aggregate->aspath);
    8147             : 
    8148             :                 /* Retrieve aggregate route's community.
    8149             :                  */
    8150           0 :                 if (aggregate->community)
    8151           0 :                         community = community_dup(aggregate->community);
    8152             : 
    8153             :                 /* Retrieve aggregate route's ecommunity.
    8154             :                  */
    8155           0 :                 if (aggregate->ecommunity)
    8156           0 :                         ecommunity = ecommunity_dup(aggregate->ecommunity);
    8157             : 
    8158             :                 /* Retrieve aggregate route's lcommunity.
    8159             :                  */
    8160           0 :                 if (aggregate->lcommunity)
    8161           0 :                         lcommunity = lcommunity_dup(aggregate->lcommunity);
    8162             :         }
    8163             : 
    8164           0 :         bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
    8165             :                               aspath, community, ecommunity,
    8166             :                               lcommunity, atomic_aggregate, aggregate);
    8167             : }
    8168             : 
    8169          17 : void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
    8170             :                              struct bgp_path_info *pi, afi_t afi, safi_t safi)
    8171             : {
    8172          17 :         struct bgp_dest *child;
    8173          17 :         struct bgp_dest *dest;
    8174          17 :         struct bgp_aggregate *aggregate;
    8175          17 :         struct bgp_table *table;
    8176             : 
    8177          17 :         table = bgp->aggregate[afi][safi];
    8178             : 
    8179             :         /* No aggregates configured. */
    8180          17 :         if (bgp_table_top_nolock(table) == NULL)
    8181             :                 return;
    8182             : 
    8183           0 :         if (p->prefixlen == 0)
    8184             :                 return;
    8185             : 
    8186           0 :         if (BGP_PATH_HOLDDOWN(pi))
    8187             :                 return;
    8188             : 
    8189             :         /* If suppress fib is enabled and route not installed
    8190             :          * in FIB, do not update the aggregate route
    8191             :          */
    8192           0 :         if (!bgp_check_advertise(bgp, pi->net))
    8193             :                 return;
    8194             : 
    8195           0 :         child = bgp_node_get(table, p);
    8196             : 
    8197             :         /* Aggregate address configuration check. */
    8198           0 :         for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
    8199           0 :                 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
    8200             : 
    8201           0 :                 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
    8202           0 :                 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
    8203           0 :                         bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
    8204             :                                                    aggregate);
    8205             :                 }
    8206             :         }
    8207           0 :         bgp_dest_unlock_node(child);
    8208             : }
    8209             : 
    8210          15 : void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
    8211             :                              struct bgp_path_info *del, afi_t afi, safi_t safi)
    8212             : {
    8213          15 :         struct bgp_dest *child;
    8214          15 :         struct bgp_dest *dest;
    8215          15 :         struct bgp_aggregate *aggregate;
    8216          15 :         struct bgp_table *table;
    8217             : 
    8218          15 :         table = bgp->aggregate[afi][safi];
    8219             : 
    8220             :         /* No aggregates configured. */
    8221          15 :         if (bgp_table_top_nolock(table) == NULL)
    8222             :                 return;
    8223             : 
    8224           0 :         if (p->prefixlen == 0)
    8225             :                 return;
    8226             : 
    8227           0 :         child = bgp_node_get(table, p);
    8228             : 
    8229             :         /* Aggregate address configuration check. */
    8230           0 :         for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
    8231           0 :                 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
    8232             : 
    8233           0 :                 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
    8234           0 :                 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
    8235           0 :                         bgp_remove_route_from_aggregate(bgp, afi, safi, del,
    8236             :                                                         aggregate, dest_p);
    8237             :                 }
    8238             :         }
    8239           0 :         bgp_dest_unlock_node(child);
    8240             : }
    8241             : 
    8242             : /* Aggregate route attribute. */
    8243             : #define AGGREGATE_SUMMARY_ONLY 1
    8244             : #define AGGREGATE_AS_SET       1
    8245             : #define AGGREGATE_AS_UNSET     0
    8246             : 
    8247           0 : static const char *bgp_origin2str(uint8_t origin)
    8248             : {
    8249           0 :         switch (origin) {
    8250             :         case BGP_ORIGIN_IGP:
    8251             :                 return "igp";
    8252           0 :         case BGP_ORIGIN_EGP:
    8253           0 :                 return "egp";
    8254           0 :         case BGP_ORIGIN_INCOMPLETE:
    8255           0 :                 return "incomplete";
    8256             :         }
    8257           0 :         return "n/a";
    8258             : }
    8259             : 
    8260           0 : static const char *bgp_rpki_validation2str(enum rpki_states v_state)
    8261             : {
    8262           0 :         switch (v_state) {
    8263             :         case RPKI_NOT_BEING_USED:
    8264             :                 return "not used";
    8265           0 :         case RPKI_VALID:
    8266           0 :                 return "valid";
    8267           0 :         case RPKI_NOTFOUND:
    8268           0 :                 return "not found";
    8269           0 :         case RPKI_INVALID:
    8270           0 :                 return "invalid";
    8271             :         }
    8272             : 
    8273           0 :         assert(!"We should never get here this is a dev escape");
    8274             :         return "ERROR";
    8275             : }
    8276             : 
    8277           0 : static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
    8278             :                                afi_t afi, safi_t safi)
    8279             : {
    8280           0 :         VTY_DECLVAR_CONTEXT(bgp, bgp);
    8281           0 :         int ret;
    8282           0 :         struct prefix p;
    8283           0 :         struct bgp_dest *dest;
    8284           0 :         struct bgp_aggregate *aggregate;
    8285             : 
    8286             :         /* Convert string to prefix structure. */
    8287           0 :         ret = str2prefix(prefix_str, &p);
    8288           0 :         if (!ret) {
    8289           0 :                 vty_out(vty, "Malformed prefix\n");
    8290           0 :                 return CMD_WARNING_CONFIG_FAILED;
    8291             :         }
    8292           0 :         apply_mask(&p);
    8293             : 
    8294             :         /* Old configuration check. */
    8295           0 :         dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
    8296           0 :         if (!dest) {
    8297           0 :                 vty_out(vty,
    8298             :                         "%% There is no aggregate-address configuration.\n");
    8299           0 :                 return CMD_WARNING_CONFIG_FAILED;
    8300             :         }
    8301             : 
    8302           0 :         aggregate = bgp_dest_get_bgp_aggregate_info(dest);
    8303           0 :         bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
    8304           0 :         bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
    8305             :                               NULL, NULL,  0, aggregate);
    8306             : 
    8307             :         /* Unlock aggregate address configuration. */
    8308           0 :         bgp_dest_set_bgp_aggregate_info(dest, NULL);
    8309             : 
    8310           0 :         if (aggregate->community)
    8311           0 :                 community_free(&aggregate->community);
    8312             : 
    8313           0 :         if (aggregate->community_hash) {
    8314             :                 /* Delete all communities in the hash.
    8315             :                  */
    8316           0 :                 hash_clean(aggregate->community_hash,
    8317             :                            bgp_aggr_community_remove);
    8318             :                 /* Free up the community_hash.
    8319             :                  */
    8320           0 :                 hash_free(aggregate->community_hash);
    8321             :         }
    8322             : 
    8323           0 :         if (aggregate->ecommunity)
    8324           0 :                 ecommunity_free(&aggregate->ecommunity);
    8325             : 
    8326           0 :         if (aggregate->ecommunity_hash) {
    8327             :                 /* Delete all ecommunities in the hash.
    8328             :                  */
    8329           0 :                 hash_clean(aggregate->ecommunity_hash,
    8330             :                            bgp_aggr_ecommunity_remove);
    8331             :                 /* Free up the ecommunity_hash.
    8332             :                  */
    8333           0 :                 hash_free(aggregate->ecommunity_hash);
    8334             :         }
    8335             : 
    8336           0 :         if (aggregate->lcommunity)
    8337           0 :                 lcommunity_free(&aggregate->lcommunity);
    8338             : 
    8339           0 :         if (aggregate->lcommunity_hash) {
    8340             :                 /* Delete all lcommunities in the hash.
    8341             :                  */
    8342           0 :                 hash_clean(aggregate->lcommunity_hash,
    8343             :                            bgp_aggr_lcommunity_remove);
    8344             :                 /* Free up the lcommunity_hash.
    8345             :                  */
    8346           0 :                 hash_free(aggregate->lcommunity_hash);
    8347             :         }
    8348             : 
    8349           0 :         if (aggregate->aspath)
    8350           0 :                 aspath_free(aggregate->aspath);
    8351             : 
    8352           0 :         if (aggregate->aspath_hash) {
    8353             :                 /* Delete all as-paths in the hash.
    8354             :                  */
    8355           0 :                 hash_clean(aggregate->aspath_hash,
    8356             :                            bgp_aggr_aspath_remove);
    8357             :                 /* Free up the aspath_hash.
    8358             :                  */
    8359           0 :                 hash_free(aggregate->aspath_hash);
    8360             :         }
    8361             : 
    8362           0 :         bgp_aggregate_free(aggregate);
    8363           0 :         bgp_dest_unlock_node(dest);
    8364           0 :         bgp_dest_unlock_node(dest);
    8365             : 
    8366           0 :         return CMD_SUCCESS;
    8367             : }
    8368             : 
    8369           0 : static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
    8370             :                              safi_t safi, const char *rmap,
    8371             :                              uint8_t summary_only, uint8_t as_set,
    8372             :                              uint8_t origin, bool match_med,
    8373             :                              const char *suppress_map)
    8374             : {
    8375           0 :         VTY_DECLVAR_CONTEXT(bgp, bgp);
    8376           0 :         int ret;
    8377           0 :         struct prefix p;
    8378           0 :         struct bgp_dest *dest;
    8379           0 :         struct bgp_aggregate *aggregate;
    8380           0 :         uint8_t as_set_new = as_set;
    8381             : 
    8382           0 :         if (suppress_map && summary_only) {
    8383           0 :                 vty_out(vty,
    8384             :                         "'summary-only' and 'suppress-map' can't be used at the same time\n");
    8385           0 :                 return CMD_WARNING_CONFIG_FAILED;
    8386             :         }
    8387             : 
    8388             :         /* Convert string to prefix structure. */
    8389           0 :         ret = str2prefix(prefix_str, &p);
    8390           0 :         if (!ret) {
    8391           0 :                 vty_out(vty, "Malformed prefix\n");
    8392           0 :                 return CMD_WARNING_CONFIG_FAILED;
    8393             :         }
    8394           0 :         apply_mask(&p);
    8395             : 
    8396           0 :         if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
    8397           0 :             (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
    8398           0 :                 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
    8399             :                         prefix_str);
    8400           0 :                 return CMD_WARNING_CONFIG_FAILED;
    8401             :         }
    8402             : 
    8403             :         /* Old configuration check. */
    8404           0 :         dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
    8405           0 :         aggregate = bgp_dest_get_bgp_aggregate_info(dest);
    8406             : 
    8407           0 :         if (aggregate) {
    8408           0 :                 vty_out(vty, "There is already same aggregate network.\n");
    8409             :                 /* try to remove the old entry */
    8410           0 :                 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
    8411           0 :                 if (ret) {
    8412           0 :                         vty_out(vty, "Error deleting aggregate.\n");
    8413           0 :                         bgp_dest_unlock_node(dest);
    8414           0 :                         return CMD_WARNING_CONFIG_FAILED;
    8415             :                 }
    8416             :         }
    8417             : 
    8418             :         /* Make aggregate address structure. */
    8419           0 :         aggregate = bgp_aggregate_new();
    8420           0 :         aggregate->summary_only = summary_only;
    8421           0 :         aggregate->match_med = match_med;
    8422             : 
    8423             :         /* Network operators MUST NOT locally generate any new
    8424             :          * announcements containing AS_SET or AS_CONFED_SET. If they have
    8425             :          * announced routes with AS_SET or AS_CONFED_SET in them, then they
    8426             :          * SHOULD withdraw those routes and re-announce routes for the
    8427             :          * aggregate or component prefixes (i.e., the more-specific routes
    8428             :          * subsumed by the previously aggregated route) without AS_SET
    8429             :          * or AS_CONFED_SET in the updates.
    8430             :          */
    8431           0 :         if (bgp->reject_as_sets) {
    8432           0 :                 if (as_set == AGGREGATE_AS_SET) {
    8433           0 :                         as_set_new = AGGREGATE_AS_UNSET;
    8434           0 :                         zlog_warn(
    8435             :                                 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
    8436             :                                 __func__);
    8437           0 :                         vty_out(vty,
    8438             :                                 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
    8439             :                 }
    8440             :         }
    8441             : 
    8442           0 :         aggregate->as_set = as_set_new;
    8443           0 :         aggregate->safi = safi;
    8444             :         /* Override ORIGIN attribute if defined.
    8445             :          * E.g.: Cisco and Juniper set ORIGIN for aggregated address
    8446             :          * to IGP which is not what rfc4271 says.
    8447             :          * This enables the same behavior, optionally.
    8448             :          */
    8449           0 :         aggregate->origin = origin;
    8450             : 
    8451           0 :         if (rmap) {
    8452           0 :                 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
    8453           0 :                 route_map_counter_decrement(aggregate->rmap.map);
    8454           0 :                 aggregate->rmap.name =
    8455           0 :                         XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
    8456           0 :                 aggregate->rmap.map = route_map_lookup_by_name(rmap);
    8457           0 :                 route_map_counter_increment(aggregate->rmap.map);
    8458             :         }
    8459             : 
    8460           0 :         if (suppress_map) {
    8461           0 :                 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
    8462           0 :                 route_map_counter_decrement(aggregate->suppress_map);
    8463             : 
    8464           0 :                 aggregate->suppress_map_name =
    8465           0 :                         XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
    8466           0 :                 aggregate->suppress_map =
    8467           0 :                         route_map_lookup_by_name(aggregate->suppress_map_name);
    8468           0 :                 route_map_counter_increment(aggregate->suppress_map);
    8469             :         }
    8470             : 
    8471           0 :         bgp_dest_set_bgp_aggregate_info(dest, aggregate);
    8472             : 
    8473             :         /* Aggregate address insert into BGP routing table. */
    8474           0 :         bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
    8475             : 
    8476           0 :         return CMD_SUCCESS;
    8477             : }
    8478             : 
    8479           0 : DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
    8480             :       "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
    8481             :       "as-set$as_set_s"
    8482             :       "|summary-only$summary_only"
    8483             :       "|route-map RMAP_NAME$rmap_name"
    8484             :       "|origin <egp|igp|incomplete>$origin_s"
    8485             :       "|matching-MED-only$match_med"
    8486             :       "|suppress-map RMAP_NAME$suppress_map"
    8487             :       "}]",
    8488             :       NO_STR
    8489             :       "Configure BGP aggregate entries\n"
    8490             :       "Aggregate prefix\n"
    8491             :       "Aggregate address\n"
    8492             :       "Aggregate mask\n"
    8493             :       "Generate AS set path information\n"
    8494             :       "Filter more specific routes from updates\n"
    8495             :       "Apply route map to aggregate network\n"
    8496             :       "Route map name\n"
    8497             :       "BGP origin code\n"
    8498             :       "Remote EGP\n"
    8499             :       "Local IGP\n"
    8500             :       "Unknown heritage\n"
    8501             :       "Only aggregate routes with matching MED\n"
    8502             :       "Suppress the selected more specific routes\n"
    8503             :       "Route map with the route selectors\n")
    8504             : {
    8505           0 :         const char *prefix_s = NULL;
    8506           0 :         safi_t safi = bgp_node_safi(vty);
    8507           0 :         uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
    8508           0 :         int as_set = AGGREGATE_AS_UNSET;
    8509           0 :         char prefix_buf[PREFIX2STR_BUFFER];
    8510             : 
    8511           0 :         if (addr_str) {
    8512           0 :                 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
    8513             :                                            sizeof(prefix_buf))
    8514             :                     == 0) {
    8515           0 :                         vty_out(vty, "%% Inconsistent address and mask\n");
    8516           0 :                         return CMD_WARNING_CONFIG_FAILED;
    8517             :                 }
    8518             :                 prefix_s = prefix_buf;
    8519             :         } else
    8520             :                 prefix_s = prefix_str;
    8521             : 
    8522           0 :         if (origin_s) {
    8523           0 :                 if (strcmp(origin_s, "egp") == 0)
    8524             :                         origin = BGP_ORIGIN_EGP;
    8525           0 :                 else if (strcmp(origin_s, "igp") == 0)
    8526             :                         origin = BGP_ORIGIN_IGP;
    8527           0 :                 else if (strcmp(origin_s, "incomplete") == 0)
    8528           0 :                         origin = BGP_ORIGIN_INCOMPLETE;
    8529             :         }
    8530             : 
    8531           0 :         if (as_set_s)
    8532           0 :                 as_set = AGGREGATE_AS_SET;
    8533             : 
    8534             :         /* Handle configuration removal, otherwise installation. */
    8535           0 :         if (no)
    8536           0 :                 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
    8537             : 
    8538           0 :         return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
    8539             :                                  summary_only != NULL, as_set, origin,
    8540             :                                  match_med != NULL, suppress_map);
    8541             : }
    8542             : 
    8543           0 : DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
    8544             :       "[no] aggregate-address X:X::X:X/M$prefix [{"
    8545             :       "as-set$as_set_s"
    8546             :       "|summary-only$summary_only"
    8547             :       "|route-map RMAP_NAME$rmap_name"
    8548             :       "|origin <egp|igp|incomplete>$origin_s"
    8549             :       "|matching-MED-only$match_med"
    8550             :       "|suppress-map RMAP_NAME$suppress_map"
    8551             :       "}]",
    8552             :       NO_STR
    8553             :       "Configure BGP aggregate entries\n"
    8554             :       "Aggregate prefix\n"
    8555             :       "Generate AS set path information\n"
    8556             :       "Filter more specific routes from updates\n"
    8557             :       "Apply route map to aggregate network\n"
    8558             :       "Route map name\n"
    8559             :       "BGP origin code\n"
    8560             :       "Remote EGP\n"
    8561             :       "Local IGP\n"
    8562             :       "Unknown heritage\n"
    8563             :       "Only aggregate routes with matching MED\n"
    8564             :       "Suppress the selected more specific routes\n"
    8565             :       "Route map with the route selectors\n")
    8566             : {
    8567           0 :         uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
    8568           0 :         int as_set = AGGREGATE_AS_UNSET;
    8569             : 
    8570           0 :         if (origin_s) {
    8571           0 :                 if (strcmp(origin_s, "egp") == 0)
    8572             :                         origin = BGP_ORIGIN_EGP;
    8573           0 :                 else if (strcmp(origin_s, "igp") == 0)
    8574             :                         origin = BGP_ORIGIN_IGP;
    8575           0 :                 else if (strcmp(origin_s, "incomplete") == 0)
    8576           0 :                         origin = BGP_ORIGIN_INCOMPLETE;
    8577             :         }
    8578             : 
    8579           0 :         if (as_set_s)
    8580           0 :                 as_set = AGGREGATE_AS_SET;
    8581             : 
    8582             :         /* Handle configuration removal, otherwise installation. */
    8583           0 :         if (no)
    8584           0 :                 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
    8585             :                                            SAFI_UNICAST);
    8586             : 
    8587           0 :         return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
    8588             :                                  rmap_name, summary_only != NULL, as_set,
    8589             :                                  origin, match_med != NULL, suppress_map);
    8590             : }
    8591             : 
    8592             : /* Redistribute route treatment. */
    8593           6 : void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
    8594             :                           const union g_addr *nexthop, ifindex_t ifindex,
    8595             :                           enum nexthop_types_t nhtype, uint8_t distance,
    8596             :                           enum blackhole_type bhtype, uint32_t metric,
    8597             :                           uint8_t type, unsigned short instance,
    8598             :                           route_tag_t tag)
    8599             : {
    8600           6 :         struct bgp_path_info *new;
    8601           6 :         struct bgp_path_info *bpi;
    8602           6 :         struct bgp_path_info rmap_path;
    8603           6 :         struct bgp_dest *bn;
    8604           6 :         struct attr attr;
    8605           6 :         struct attr *new_attr;
    8606           6 :         afi_t afi;
    8607           6 :         route_map_result_t ret;
    8608           6 :         struct bgp_redist *red;
    8609             : 
    8610             :         /* Make default attribute. */
    8611           6 :         bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
    8612             :         /*
    8613             :          * This must not be NULL to satisfy Coverity SA
    8614             :          */
    8615           6 :         assert(attr.aspath);
    8616             : 
    8617           6 :         switch (nhtype) {
    8618           6 :         case NEXTHOP_TYPE_IFINDEX:
    8619           6 :                 switch (p->family) {
    8620           6 :                 case AF_INET:
    8621           6 :                         attr.nexthop.s_addr = INADDR_ANY;
    8622           6 :                         attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
    8623           6 :                         break;
    8624           0 :                 case AF_INET6:
    8625           0 :                         memset(&attr.mp_nexthop_global, 0,
    8626             :                                sizeof(attr.mp_nexthop_global));
    8627           0 :                         attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
    8628           0 :                         break;
    8629             :                 }
    8630             :                 break;
    8631           0 :         case NEXTHOP_TYPE_IPV4:
    8632             :         case NEXTHOP_TYPE_IPV4_IFINDEX:
    8633           0 :                 attr.nexthop = nexthop->ipv4;
    8634           0 :                 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
    8635           0 :                 break;
    8636           0 :         case NEXTHOP_TYPE_IPV6:
    8637             :         case NEXTHOP_TYPE_IPV6_IFINDEX:
    8638           0 :                 attr.mp_nexthop_global = nexthop->ipv6;
    8639           0 :                 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
    8640           0 :                 break;
    8641           0 :         case NEXTHOP_TYPE_BLACKHOLE:
    8642           0 :                 switch (p->family) {
    8643           0 :                 case AF_INET:
    8644           0 :                         attr.nexthop.s_addr = INADDR_ANY;
    8645           0 :                         attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
    8646           0 :                         break;
    8647           0 :                 case AF_INET6:
    8648           0 :                         memset(&attr.mp_nexthop_global, 0,
    8649             :                                sizeof(attr.mp_nexthop_global));
    8650           0 :                         attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
    8651           0 :                         break;
    8652             :                 }
    8653           0 :                 attr.bh_type = bhtype;
    8654           0 :                 break;
    8655             :         }
    8656           6 :         attr.nh_type = nhtype;
    8657           6 :         attr.nh_ifindex = ifindex;
    8658             : 
    8659           6 :         attr.med = metric;
    8660           6 :         attr.distance = distance;
    8661           6 :         attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
    8662           6 :         attr.tag = tag;
    8663             : 
    8664           6 :         if (metric)
    8665           0 :                 bgp_attr_set_aigp_metric(&attr, metric);
    8666             : 
    8667           6 :         afi = family2afi(p->family);
    8668             : 
    8669           6 :         red = bgp_redist_lookup(bgp, afi, type, instance);
    8670           6 :         if (red) {
    8671           6 :                 struct attr attr_new;
    8672             : 
    8673             :                 /* Copy attribute for modification. */
    8674           6 :                 attr_new = attr;
    8675             : 
    8676           6 :                 if (red->redist_metric_flag) {
    8677           0 :                         attr_new.med = red->redist_metric;
    8678           0 :                         bgp_attr_set_aigp_metric(&attr_new, red->redist_metric);
    8679             :                 }
    8680             : 
    8681             :                 /* Apply route-map. */
    8682           6 :                 if (red->rmap.name) {
    8683           0 :                         memset(&rmap_path, 0, sizeof(rmap_path));
    8684           0 :                         rmap_path.peer = bgp->peer_self;
    8685           0 :                         rmap_path.attr = &attr_new;
    8686             : 
    8687           0 :                         SET_FLAG(bgp->peer_self->rmap_type,
    8688             :                                  PEER_RMAP_TYPE_REDISTRIBUTE);
    8689             : 
    8690           0 :                         ret = route_map_apply(red->rmap.map, p, &rmap_path);
    8691             : 
    8692           0 :                         bgp->peer_self->rmap_type = 0;
    8693             : 
    8694           0 :                         if (ret == RMAP_DENYMATCH) {
    8695             :                                 /* Free uninterned attribute. */
    8696           0 :                                 bgp_attr_flush(&attr_new);
    8697             : 
    8698             :                                 /* Unintern original. */
    8699           0 :                                 aspath_unintern(&attr.aspath);
    8700           0 :                                 bgp_redistribute_delete(bgp, p, type, instance);
    8701           0 :                                 return;
    8702             :                         }
    8703             :                 }
    8704             : 
    8705           6 :                 if (bgp_in_graceful_shutdown(bgp))
    8706           0 :                         bgp_attr_add_gshut_community(&attr_new);
    8707             : 
    8708           6 :                 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
    8709             :                                       SAFI_UNICAST, p, NULL);
    8710             : 
    8711           6 :                 new_attr = bgp_attr_intern(&attr_new);
    8712             : 
    8713          12 :                 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
    8714           0 :                         if (bpi->peer == bgp->peer_self
    8715           0 :                             && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
    8716             :                                 break;
    8717             : 
    8718           6 :                 if (bpi) {
    8719             :                         /* Ensure the (source route) type is updated. */
    8720           0 :                         bpi->type = type;
    8721           0 :                         if (attrhash_cmp(bpi->attr, new_attr)
    8722           0 :                             && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
    8723           0 :                                 bgp_attr_unintern(&new_attr);
    8724           0 :                                 aspath_unintern(&attr.aspath);
    8725           0 :                                 bgp_dest_unlock_node(bn);
    8726           0 :                                 return;
    8727             :                         } else {
    8728             :                                 /* The attribute is changed. */
    8729           0 :                                 bgp_path_info_set_flag(bn, bpi,
    8730             :                                                        BGP_PATH_ATTR_CHANGED);
    8731             : 
    8732             :                                 /* Rewrite BGP route information. */
    8733           0 :                                 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
    8734           0 :                                         bgp_path_info_restore(bn, bpi);
    8735             :                                 else
    8736           0 :                                         bgp_aggregate_decrement(
    8737             :                                                 bgp, p, bpi, afi, SAFI_UNICAST);
    8738           0 :                                 bgp_attr_unintern(&bpi->attr);
    8739           0 :                                 bpi->attr = new_attr;
    8740           0 :                                 bpi->uptime = monotime(NULL);
    8741             : 
    8742             :                                 /* Process change. */
    8743           0 :                                 bgp_aggregate_increment(bgp, p, bpi, afi,
    8744             :                                                         SAFI_UNICAST);
    8745           0 :                                 bgp_process(bgp, bn, afi, SAFI_UNICAST);
    8746           0 :                                 bgp_dest_unlock_node(bn);
    8747           0 :                                 aspath_unintern(&attr.aspath);
    8748             : 
    8749           0 :                                 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
    8750             :                                     || (bgp->inst_type
    8751             :                                         == BGP_INSTANCE_TYPE_DEFAULT)) {
    8752             : 
    8753           0 :                                         vpn_leak_from_vrf_update(
    8754             :                                                 bgp_get_default(), bgp, bpi);
    8755             :                                 }
    8756           0 :                                 return;
    8757             :                         }
    8758             :                 }
    8759             : 
    8760           6 :                 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
    8761             :                                 bgp->peer_self, new_attr, bn);
    8762           6 :                 SET_FLAG(new->flags, BGP_PATH_VALID);
    8763             : 
    8764           6 :                 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
    8765           6 :                 bgp_path_info_add(bn, new);
    8766           6 :                 bgp_dest_unlock_node(bn);
    8767           6 :                 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
    8768           6 :                 bgp_process(bgp, bn, afi, SAFI_UNICAST);
    8769             : 
    8770           6 :                 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
    8771             :                     || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
    8772             : 
    8773           6 :                         vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
    8774             :                 }
    8775             :         }
    8776             : 
    8777             :         /* Unintern original. */
    8778           6 :         aspath_unintern(&attr.aspath);
    8779             : }
    8780             : 
    8781         184 : void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
    8782             :                              unsigned short instance)
    8783             : {
    8784         184 :         afi_t afi;
    8785         184 :         struct bgp_dest *dest;
    8786         184 :         struct bgp_path_info *pi;
    8787         184 :         struct bgp_redist *red;
    8788             : 
    8789         184 :         afi = family2afi(p->family);
    8790             : 
    8791         184 :         red = bgp_redist_lookup(bgp, afi, type, instance);
    8792         184 :         if (red) {
    8793           4 :                 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
    8794             :                                         SAFI_UNICAST, p, NULL);
    8795             : 
    8796           8 :                 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
    8797           4 :                         if (pi->peer == bgp->peer_self && pi->type == type)
    8798             :                                 break;
    8799             : 
    8800           4 :                 if (pi) {
    8801           4 :                         if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
    8802             :                             || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
    8803             : 
    8804           4 :                                 vpn_leak_from_vrf_withdraw(bgp_get_default(),
    8805             :                                                            bgp, pi);
    8806             :                         }
    8807           4 :                         bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
    8808           4 :                         bgp_path_info_delete(dest, pi);
    8809           4 :                         bgp_process(bgp, dest, afi, SAFI_UNICAST);
    8810             :                 }
    8811           4 :                 bgp_dest_unlock_node(dest);
    8812             :         }
    8813         184 : }
    8814             : 
    8815             : /* Withdraw specified route type's route. */
    8816           1 : void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
    8817             :                                unsigned short instance)
    8818             : {
    8819           1 :         struct bgp_dest *dest;
    8820           1 :         struct bgp_path_info *pi;
    8821           1 :         struct bgp_table *table;
    8822             : 
    8823           1 :         table = bgp->rib[afi][SAFI_UNICAST];
    8824             : 
    8825           9 :         for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
    8826           7 :                 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
    8827           4 :                         if (pi->peer == bgp->peer_self && pi->type == type
    8828           4 :                             && pi->instance == instance)
    8829             :                                 break;
    8830             : 
    8831           7 :                 if (pi) {
    8832           4 :                         if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
    8833             :                             || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
    8834             : 
    8835           4 :                                 vpn_leak_from_vrf_withdraw(bgp_get_default(),
    8836             :                                                            bgp, pi);
    8837             :                         }
    8838           4 :                         bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
    8839             :                                                 pi, afi, SAFI_UNICAST);
    8840           4 :                         bgp_path_info_delete(dest, pi);
    8841           4 :                         if (!CHECK_FLAG(bgp->flags,
    8842             :                                         BGP_FLAG_DELETE_IN_PROGRESS))
    8843           0 :                                 bgp_process(bgp, dest, afi, SAFI_UNICAST);
    8844             :                         else
    8845           4 :                                 bgp_path_info_reap(dest, pi);
    8846             :                 }
    8847             :         }
    8848           1 : }
    8849             : 
    8850             : /* Static function to display route. */
    8851           4 : static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
    8852             :                                 struct vty *vty, json_object *json, bool wide)
    8853             : {
    8854           4 :         int len = 0;
    8855           4 :         char buf[INET6_ADDRSTRLEN];
    8856             : 
    8857           4 :         if (p->family == AF_INET) {
    8858           4 :                 if (!json) {
    8859           0 :                         len = vty_out(vty, "%pFX", p);
    8860             :                 } else {
    8861           4 :                         json_object_string_add(json, "prefix",
    8862             :                                                inet_ntop(p->family,
    8863           4 :                                                          &p->u.prefix, buf,
    8864             :                                                          sizeof(buf)));
    8865           4 :                         json_object_int_add(json, "prefixLen", p->prefixlen);
    8866           4 :                         json_object_string_addf(json, "network", "%pFX", p);
    8867           4 :                         json_object_int_add(json, "version", dest->version);
    8868             :                 }
    8869           0 :         } else if (p->family == AF_ETHERNET) {
    8870           0 :                 len = vty_out(vty, "%pFX", p);
    8871           0 :         } else if (p->family == AF_EVPN) {
    8872           0 :                 if (!json)
    8873           0 :                         len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
    8874             :                 else
    8875           0 :                         bgp_evpn_route2json((struct prefix_evpn *)p, json);
    8876           0 :         } else if (p->family == AF_FLOWSPEC) {
    8877           0 :                 route_vty_out_flowspec(vty, p, NULL,
    8878             :                                json ?
    8879             :                                NLRI_STRING_FORMAT_JSON_SIMPLE :
    8880             :                                NLRI_STRING_FORMAT_MIN, json);
    8881             :         } else {
    8882           0 :                 if (!json)
    8883           0 :                         len = vty_out(vty, "%pFX", p);
    8884             :                 else {
    8885           0 :                         json_object_string_add(json, "prefix",
    8886             :                                                inet_ntop(p->family,
    8887           0 :                                                          &p->u.prefix, buf,
    8888             :                                                          sizeof(buf)));
    8889           0 :                         json_object_int_add(json, "prefixLen", p->prefixlen);
    8890           0 :                         json_object_string_addf(json, "network", "%pFX", p);
    8891           0 :                         json_object_int_add(json, "version", dest->version);
    8892             :                 }
    8893             :         }
    8894             : 
    8895           4 :         if (!json) {
    8896           0 :                 len = wide ? (45 - len) : (17 - len);
    8897           0 :                 if (len < 1)
    8898           0 :                         vty_out(vty, "\n%*s", 20, " ");
    8899             :                 else
    8900           0 :                         vty_out(vty, "%*s", len, " ");
    8901             :         }
    8902           4 : }
    8903             : 
    8904             : enum bgp_display_type {
    8905             :         normal_list,
    8906             : };
    8907             : 
    8908           4 : const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
    8909             : {
    8910           4 :         switch (reason) {
    8911             :         case bgp_path_selection_none:
    8912             :                 return "Nothing to Select";
    8913           4 :         case bgp_path_selection_first:
    8914           4 :                 return "First path received";
    8915           0 :         case bgp_path_selection_evpn_sticky_mac:
    8916           0 :                 return "EVPN Sticky Mac";
    8917           0 :         case bgp_path_selection_evpn_seq:
    8918           0 :                 return "EVPN sequence number";
    8919           0 :         case bgp_path_selection_evpn_lower_ip:
    8920           0 :                 return "EVPN lower IP";
    8921           0 :         case bgp_path_selection_evpn_local_path:
    8922           0 :                 return "EVPN local ES path";
    8923           0 :         case bgp_path_selection_evpn_non_proxy:
    8924           0 :                 return "EVPN non proxy";
    8925           0 :         case bgp_path_selection_weight:
    8926           0 :                 return "Weight";
    8927           0 :         case bgp_path_selection_local_pref:
    8928           0 :                 return "Local Pref";
    8929           0 :         case bgp_path_selection_accept_own:
    8930           0 :                 return "Accept Own";
    8931           0 :         case bgp_path_selection_local_route:
    8932           0 :                 return "Local Route";
    8933           0 :         case bgp_path_selection_aigp:
    8934           0 :                 return "AIGP";
    8935           0 :         case bgp_path_selection_confed_as_path:
    8936           0 :                 return "Confederation based AS Path";
    8937           0 :         case bgp_path_selection_as_path:
    8938           0 :                 return "AS Path";
    8939           0 :         case bgp_path_selection_origin:
    8940           0 :                 return "Origin";
    8941           0 :         case bgp_path_selection_med:
    8942           0 :                 return "MED";
    8943           0 :         case bgp_path_selection_peer:
    8944           0 :                 return "Peer Type";
    8945           0 :         case bgp_path_selection_confed:
    8946           0 :                 return "Confed Peer Type";
    8947           0 :         case bgp_path_selection_igp_metric:
    8948           0 :                 return "IGP Metric";
    8949           0 :         case bgp_path_selection_older:
    8950           0 :                 return "Older Path";
    8951           0 :         case bgp_path_selection_router_id:
    8952           0 :                 return "Router ID";
    8953           0 :         case bgp_path_selection_cluster_length:
    8954           0 :                 return "Cluster length";
    8955           0 :         case bgp_path_selection_stale:
    8956           0 :                 return "Path Staleness";
    8957           0 :         case bgp_path_selection_local_configured:
    8958           0 :                 return "Locally configured route";
    8959           0 :         case bgp_path_selection_neighbor_ip:
    8960           0 :                 return "Neighbor IP";
    8961           0 :         case bgp_path_selection_default:
    8962           0 :                 return "Nothing left to compare";
    8963             :         }
    8964           0 :         return "Invalid (internal error)";
    8965             : }
    8966             : 
    8967             : /* Print the short form route status for a bgp_path_info */
    8968           4 : static void route_vty_short_status_out(struct vty *vty,
    8969             :                                        struct bgp_path_info *path,
    8970             :                                        const struct prefix *p,
    8971             :                                        json_object *json_path)
    8972             : {
    8973           4 :         enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
    8974             : 
    8975           4 :         if (json_path) {
    8976             : 
    8977             :                 /* Route status display. */
    8978           4 :                 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
    8979           0 :                         json_object_boolean_true_add(json_path, "removed");
    8980             : 
    8981           4 :                 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
    8982           0 :                         json_object_boolean_true_add(json_path, "stale");
    8983             : 
    8984           4 :                 if (path->extra && bgp_path_suppressed(path))
    8985           0 :                         json_object_boolean_true_add(json_path, "suppressed");
    8986             : 
    8987           4 :                 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
    8988           4 :                     && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
    8989           4 :                         json_object_boolean_true_add(json_path, "valid");
    8990             : 
    8991             :                 /* Selected */
    8992           4 :                 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
    8993           0 :                         json_object_boolean_true_add(json_path, "history");
    8994             : 
    8995           4 :                 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
    8996           0 :                         json_object_boolean_true_add(json_path, "damped");
    8997             : 
    8998           4 :                 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
    8999           4 :                         json_object_boolean_true_add(json_path, "bestpath");
    9000           4 :                         json_object_string_add(json_path, "selectionReason",
    9001             :                                                bgp_path_selection_reason2str(
    9002           4 :                                                        path->net->reason));
    9003             :                 }
    9004             : 
    9005           4 :                 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
    9006           0 :                         json_object_boolean_true_add(json_path, "multipath");
    9007             : 
    9008             :                 /* Internal route. */
    9009           4 :                 if ((path->peer->as)
    9010           4 :                     && (path->peer->as == path->peer->local_as))
    9011           0 :                         json_object_string_add(json_path, "pathFrom",
    9012             :                                                "internal");
    9013             :                 else
    9014           4 :                         json_object_string_add(json_path, "pathFrom",
    9015             :                                                "external");
    9016             : 
    9017           4 :                 return;
    9018             :         }
    9019             : 
    9020             :         /* RPKI validation state */
    9021           0 :         rpki_state =
    9022           0 :                 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
    9023             : 
    9024           0 :         if (rpki_state == RPKI_VALID)
    9025           0 :                 vty_out(vty, "V");
    9026           0 :         else if (rpki_state == RPKI_INVALID)
    9027           0 :                 vty_out(vty, "I");
    9028           0 :         else if (rpki_state == RPKI_NOTFOUND)
    9029           0 :                 vty_out(vty, "N");
    9030             :         else
    9031           0 :                 vty_out(vty, " ");
    9032             : 
    9033             :         /* Route status display. */
    9034           0 :         if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
    9035           0 :                 vty_out(vty, "R");
    9036           0 :         else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
    9037           0 :                 vty_out(vty, "S");
    9038           0 :         else if (bgp_path_suppressed(path))
    9039           0 :                 vty_out(vty, "s");
    9040           0 :         else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
    9041           0 :                  && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
    9042           0 :                 vty_out(vty, "*");
    9043             :         else
    9044           0 :                 vty_out(vty, " ");
    9045             : 
    9046             :         /* Selected */
    9047           0 :         if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
    9048           0 :                 vty_out(vty, "h");
    9049           0 :         else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
    9050           0 :                 vty_out(vty, "d");
    9051           0 :         else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
    9052           0 :                 vty_out(vty, ">");
    9053           0 :         else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
    9054           0 :                 vty_out(vty, "=");
    9055             :         else
    9056           0 :                 vty_out(vty, " ");
    9057             : 
    9058             :         /* Internal route. */
    9059           0 :         if (path->peer && (path->peer->as)
    9060           0 :             && (path->peer->as == path->peer->local_as))
    9061           0 :                 vty_out(vty, "i");
    9062             :         else
    9063           0 :                 vty_out(vty, " ");
    9064             : }
    9065             : 
    9066           4 : static char *bgp_nexthop_hostname(struct peer *peer,
    9067             :                                   struct bgp_nexthop_cache *bnc)
    9068             : {
    9069           4 :         if (peer->hostname
    9070           4 :             && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
    9071             :                 return peer->hostname;
    9072             :         return NULL;
    9073             : }
    9074             : 
    9075             : /* called from terminal list command */
    9076           4 : void route_vty_out(struct vty *vty, const struct prefix *p,
    9077             :                    struct bgp_path_info *path, int display, safi_t safi,
    9078             :                    json_object *json_paths, bool wide)
    9079             : {
    9080           4 :         int len;
    9081           4 :         struct attr *attr = path->attr;
    9082           4 :         json_object *json_path = NULL;
    9083           4 :         json_object *json_nexthops = NULL;
    9084           4 :         json_object *json_nexthop_global = NULL;
    9085           4 :         json_object *json_nexthop_ll = NULL;
    9086           4 :         json_object *json_ext_community = NULL;
    9087           4 :         char vrf_id_str[VRF_NAMSIZ] = {0};
    9088           4 :         bool nexthop_self =
    9089           4 :                 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
    9090           4 :         bool nexthop_othervrf = false;
    9091           4 :         vrf_id_t nexthop_vrfid = VRF_DEFAULT;
    9092           4 :         const char *nexthop_vrfname = VRF_DEFAULT_NAME;
    9093           4 :         char *nexthop_hostname =
    9094           4 :                 bgp_nexthop_hostname(path->peer, path->nexthop);
    9095           4 :         char esi_buf[ESI_STR_LEN];
    9096             : 
    9097           4 :         if (json_paths)
    9098           4 :                 json_path = json_object_new_object();
    9099             : 
    9100             :         /* short status lead text */
    9101           4 :         route_vty_short_status_out(vty, path, p, json_path);
    9102             : 
    9103           4 :         if (!json_paths) {
    9104             :                 /* print prefix and mask */
    9105           0 :                 if (!display)
    9106           0 :                         route_vty_out_route(path->net, p, vty, json_path, wide);
    9107             :                 else
    9108           0 :                         vty_out(vty, "%*s", (wide ? 45 : 17), " ");
    9109             :         } else {
    9110           4 :                 route_vty_out_route(path->net, p, vty, json_path, wide);
    9111             :         }
    9112             : 
    9113             :         /*
    9114             :          * If vrf id of nexthop is different from that of prefix,
    9115             :          * set up printable string to append
    9116             :          */
    9117           4 :         if (path->extra && path->extra->bgp_orig) {
    9118           0 :                 const char *self = "";
    9119             : 
    9120           0 :                 if (nexthop_self)
    9121           0 :                         self = "<";
    9122             : 
    9123           0 :                 nexthop_othervrf = true;
    9124           0 :                 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
    9125             : 
    9126           0 :                 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
    9127           0 :                         snprintf(vrf_id_str, sizeof(vrf_id_str),
    9128             :                                 "@%s%s", VRFID_NONE_STR, self);
    9129             :                 else
    9130           0 :                         snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
    9131             :                                  path->extra->bgp_orig->vrf_id, self);
    9132             : 
    9133           0 :                 if (path->extra->bgp_orig->inst_type
    9134             :                     != BGP_INSTANCE_TYPE_DEFAULT)
    9135             : 
    9136           0 :                         nexthop_vrfname = path->extra->bgp_orig->name;
    9137             :         } else {
    9138           4 :                 const char *self = "";
    9139             : 
    9140           4 :                 if (nexthop_self)
    9141           0 :                         self = "<";
    9142             : 
    9143           4 :                 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
    9144             :         }
    9145             : 
    9146             :         /*
    9147             :          * For ENCAP and EVPN routes, nexthop address family is not
    9148             :          * neccessarily the same as the prefix address family.
    9149             :          * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
    9150             :          * EVPN routes are also exchanged with a MP nexthop. Currently,
    9151             :          * this
    9152             :          * is only IPv4, the value will be present in either
    9153             :          * attr->nexthop or
    9154             :          * attr->mp_nexthop_global_in
    9155             :          */
    9156           4 :         if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
    9157           0 :                 char nexthop[128];
    9158           0 :                 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
    9159             : 
    9160           0 :                 switch (af) {
    9161             :                 case AF_INET:
    9162           0 :                         snprintfrr(nexthop, sizeof(nexthop), "%pI4",
    9163             :                                    &attr->mp_nexthop_global_in);
    9164           0 :                         break;
    9165           0 :                 case AF_INET6:
    9166           0 :                         snprintfrr(nexthop, sizeof(nexthop), "%pI6",
    9167             :                                    &attr->mp_nexthop_global);
    9168           0 :                         break;
    9169             :                 default:
    9170           0 :                         snprintf(nexthop, sizeof(nexthop), "?");
    9171           0 :                         break;
    9172             :                 }
    9173             : 
    9174           0 :                 if (json_paths) {
    9175           0 :                         json_nexthop_global = json_object_new_object();
    9176             : 
    9177           0 :                         json_object_string_add(json_nexthop_global, "ip",
    9178             :                                                nexthop);
    9179             : 
    9180           0 :                         if (path->peer->hostname)
    9181           0 :                                 json_object_string_add(json_nexthop_global,
    9182             :                                                        "hostname",
    9183             :                                                        path->peer->hostname);
    9184             : 
    9185           0 :                         json_object_string_add(json_nexthop_global, "afi",
    9186             :                                                (af == AF_INET) ? "ipv4"
    9187             :                                                                : "ipv6");
    9188           0 :                         json_object_boolean_true_add(json_nexthop_global,
    9189             :                                                      "used");
    9190             :                 } else {
    9191           0 :                         if (nexthop_hostname)
    9192           0 :                                 len = vty_out(vty, "%s(%s)%s", nexthop,
    9193             :                                               nexthop_hostname, vrf_id_str);
    9194             :                         else
    9195           0 :                                 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
    9196             : 
    9197           0 :                         len = wide ? (41 - len) : (16 - len);
    9198           0 :                         if (len < 1)
    9199           0 :                                 vty_out(vty, "\n%*s", 36, " ");
    9200             :                         else
    9201           0 :                                 vty_out(vty, "%*s", len, " ");
    9202             :                 }
    9203           4 :         } else if (safi == SAFI_EVPN) {
    9204           0 :                 if (json_paths) {
    9205           0 :                         json_nexthop_global = json_object_new_object();
    9206             : 
    9207           0 :                         json_object_string_addf(json_nexthop_global, "ip",
    9208             :                                                 "%pI4",
    9209             :                                                 &attr->mp_nexthop_global_in);
    9210             : 
    9211           0 :                         if (path->peer->hostname)
    9212           0 :                                 json_object_string_add(json_nexthop_global,
    9213             :                                                        "hostname",
    9214             :                                                        path->peer->hostname);
    9215             : 
    9216           0 :                         json_object_string_add(json_nexthop_global, "afi",
    9217             :                                                "ipv4");
    9218           0 :                         json_object_boolean_true_add(json_nexthop_global,
    9219             :                                                      "used");
    9220             :                 } else {
    9221           0 :                         if (nexthop_hostname)
    9222           0 :                                 len = vty_out(vty, "%pI4(%s)%s",
    9223             :                                               &attr->mp_nexthop_global_in,
    9224             :                                               nexthop_hostname, vrf_id_str);
    9225             :                         else
    9226           0 :                                 len = vty_out(vty, "%pI4%s",
    9227             :                                               &attr->mp_nexthop_global_in,
    9228             :                                               vrf_id_str);
    9229             : 
    9230           0 :                         len = wide ? (41 - len) : (16 - len);
    9231           0 :                         if (len < 1)
    9232           0 :                                 vty_out(vty, "\n%*s", 36, " ");
    9233             :                         else
    9234           0 :                                 vty_out(vty, "%*s", len, " ");
    9235             :                 }
    9236           4 :         } else if (safi == SAFI_FLOWSPEC) {
    9237           0 :                 if (attr->nexthop.s_addr != INADDR_ANY) {
    9238           0 :                         if (json_paths) {
    9239           0 :                                 json_nexthop_global = json_object_new_object();
    9240             : 
    9241           0 :                                 json_object_string_add(json_nexthop_global,
    9242             :                                                        "afi", "ipv4");
    9243           0 :                                 json_object_string_addf(json_nexthop_global,
    9244             :                                                         "ip", "%pI4",
    9245             :                                                         &attr->nexthop);
    9246             : 
    9247           0 :                                 if (path->peer->hostname)
    9248           0 :                                         json_object_string_add(
    9249             :                                                 json_nexthop_global, "hostname",
    9250             :                                                 path->peer->hostname);
    9251             : 
    9252           0 :                                 json_object_boolean_true_add(
    9253             :                                                         json_nexthop_global,
    9254             :                                                              "used");
    9255             :                         } else {
    9256           0 :                                 if (nexthop_hostname)
    9257           0 :                                         len = vty_out(vty, "%pI4(%s)%s",
    9258             :                                                       &attr->nexthop,
    9259             :                                                       nexthop_hostname,
    9260             :                                                       vrf_id_str);
    9261             :                                 else
    9262           0 :                                         len = vty_out(vty, "%pI4%s",
    9263             :                                                       &attr->nexthop,
    9264             :                                                       vrf_id_str);
    9265             : 
    9266           0 :                                 len = wide ? (41 - len) : (16 - len);
    9267           0 :                                 if (len < 1)
    9268           0 :                                         vty_out(vty, "\n%*s", 36, " ");
    9269             :                                 else
    9270           0 :                                         vty_out(vty, "%*s", len, " ");
    9271             :                         }
    9272             :                 }
    9273           4 :         } else if (p->family == AF_INET && !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
    9274           4 :                 if (json_paths) {
    9275           4 :                         json_nexthop_global = json_object_new_object();
    9276             : 
    9277           4 :                         json_object_string_addf(json_nexthop_global, "ip",
    9278             :                                                 "%pI4", &attr->nexthop);
    9279             : 
    9280           4 :                         if (path->peer->hostname)
    9281           4 :                                 json_object_string_add(json_nexthop_global,
    9282             :                                                        "hostname",
    9283             :                                                        path->peer->hostname);
    9284             : 
    9285           4 :                         json_object_string_add(json_nexthop_global, "afi",
    9286             :                                                "ipv4");
    9287           4 :                         json_object_boolean_true_add(json_nexthop_global,
    9288             :                                                      "used");
    9289             :                 } else {
    9290           0 :                         if (nexthop_hostname)
    9291           0 :                                 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
    9292             :                                               nexthop_hostname, vrf_id_str);
    9293             :                         else
    9294           0 :                                 len = vty_out(vty, "%pI4%s", &attr->nexthop,
    9295             :                                               vrf_id_str);
    9296             : 
    9297           0 :                         len = wide ? (41 - len) : (16 - len);
    9298           0 :                         if (len < 1)
    9299           0 :                                 vty_out(vty, "\n%*s", 36, " ");
    9300             :                         else
    9301           0 :                                 vty_out(vty, "%*s", len, " ");
    9302             :                 }
    9303             :         }
    9304             : 
    9305             :         /* IPv6 Next Hop */
    9306           0 :         else if (p->family == AF_INET6 || BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
    9307           0 :                 if (json_paths) {
    9308           0 :                         json_nexthop_global = json_object_new_object();
    9309           0 :                         json_object_string_addf(json_nexthop_global, "ip",
    9310             :                                                 "%pI6",
    9311             :                                                 &attr->mp_nexthop_global);
    9312             : 
    9313           0 :                         if (path->peer->hostname)
    9314           0 :                                 json_object_string_add(json_nexthop_global,
    9315             :                                                        "hostname",
    9316             :                                                        path->peer->hostname);
    9317             : 
    9318           0 :                         json_object_string_add(json_nexthop_global, "afi",
    9319             :                                                "ipv6");
    9320           0 :                         json_object_string_add(json_nexthop_global, "scope",
    9321             :                                                "global");
    9322             : 
    9323             :                         /* We display both LL & GL if both have been
    9324             :                          * received */
    9325           0 :                         if ((attr->mp_nexthop_len
    9326             :                              == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
    9327           0 :                             || (path->peer->conf_if)) {
    9328           0 :                                 json_nexthop_ll = json_object_new_object();
    9329           0 :                                 json_object_string_addf(
    9330             :                                         json_nexthop_ll, "ip", "%pI6",
    9331             :                                         &attr->mp_nexthop_local);
    9332             : 
    9333           0 :                                 if (path->peer->hostname)
    9334           0 :                                         json_object_string_add(
    9335             :                                                 json_nexthop_ll, "hostname",
    9336             :                                                 path->peer->hostname);
    9337             : 
    9338           0 :                                 json_object_string_add(json_nexthop_ll, "afi",
    9339             :                                                        "ipv6");
    9340           0 :                                 json_object_string_add(json_nexthop_ll, "scope",
    9341             :                                                        "link-local");
    9342             : 
    9343           0 :                                 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
    9344             :                                                    &attr->mp_nexthop_local)
    9345             :                                      != 0)
    9346           0 :                                     && !attr->mp_nexthop_prefer_global)
    9347           0 :                                         json_object_boolean_true_add(
    9348             :                                                 json_nexthop_ll, "used");
    9349             :                                 else
    9350           0 :                                         json_object_boolean_true_add(
    9351             :                                                 json_nexthop_global, "used");
    9352             :                         } else
    9353           0 :                                 json_object_boolean_true_add(
    9354             :                                         json_nexthop_global, "used");
    9355             :                 } else {
    9356             :                         /* Display LL if LL/Global both in table unless
    9357             :                          * prefer-global is set */
    9358           0 :                         if (((attr->mp_nexthop_len
    9359             :                               == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
    9360           0 :                              && !attr->mp_nexthop_prefer_global)
    9361           0 :                             || (path->peer->conf_if)) {
    9362           0 :                                 if (path->peer->conf_if) {
    9363           0 :                                         len = vty_out(vty, "%s",
    9364             :                                                       path->peer->conf_if);
    9365             :                                         /* len of IPv6 addr + max len of def
    9366             :                                          * ifname */
    9367           0 :                                         len = wide ? (41 - len) : (16 - len);
    9368             : 
    9369           0 :                                         if (len < 1)
    9370           0 :                                                 vty_out(vty, "\n%*s", 36, " ");
    9371             :                                         else
    9372           0 :                                                 vty_out(vty, "%*s", len, " ");
    9373             :                                 } else {
    9374           0 :                                         if (nexthop_hostname)
    9375           0 :                                                 len = vty_out(
    9376             :                                                         vty, "%pI6(%s)%s",
    9377             :                                                         &attr->mp_nexthop_local,
    9378             :                                                         nexthop_hostname,
    9379             :                                                         vrf_id_str);
    9380             :                                         else
    9381           0 :                                                 len = vty_out(
    9382             :                                                         vty, "%pI6%s",
    9383             :                                                         &attr->mp_nexthop_local,
    9384             :                                                         vrf_id_str);
    9385             : 
    9386           0 :                                         len = wide ? (41 - len) : (16 - len);
    9387             : 
    9388           0 :                                         if (len < 1)
    9389           0 :                                                 vty_out(vty, "\n%*s", 36, " ");
    9390             :                                         else
    9391           0 :                                                 vty_out(vty, "%*s", len, " ");
    9392             :                                 }
    9393             :                         } else {
    9394           0 :                                 if (nexthop_hostname)
    9395           0 :                                         len = vty_out(vty, "%pI6(%s)%s",
    9396             :                                                       &attr->mp_nexthop_global,
    9397             :                                                       nexthop_hostname,
    9398             :                                                       vrf_id_str);
    9399             :                                 else
    9400           0 :                                         len = vty_out(vty, "%pI6%s",
    9401             :                                                       &attr->mp_nexthop_global,
    9402             :                                                       vrf_id_str);
    9403             : 
    9404           0 :                                 len = wide ? (41 - len) : (16 - len);
    9405             : 
    9406           0 :                                 if (len < 1)
    9407           0 :                                         vty_out(vty, "\n%*s", 36, " ");
    9408             :                                 else
    9409           0 :                                         vty_out(vty, "%*s", len, " ");
    9410             :                         }
    9411             :                 }
    9412             :         }
    9413             : 
    9414             :         /* MED/Metric */
    9415           4 :         if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
    9416           0 :                 if (json_paths)
    9417           0 :                         json_object_int_add(json_path, "metric", attr->med);
    9418           0 :                 else if (wide)
    9419           0 :                         vty_out(vty, "%7u", attr->med);
    9420             :                 else
    9421           0 :                         vty_out(vty, "%10u", attr->med);
    9422           4 :         else if (!json_paths) {
    9423           0 :                 if (wide)
    9424           0 :                         vty_out(vty, "%*s", 7, " ");
    9425             :                 else
    9426           0 :                         vty_out(vty, "%*s", 10, " ");
    9427             :         }
    9428             : 
    9429             :         /* Local Pref */
    9430           4 :         if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
    9431           0 :                 if (json_paths)
    9432           0 :                         json_object_int_add(json_path, "locPrf",
    9433           0 :                                             attr->local_pref);
    9434             :                 else
    9435           0 :                         vty_out(vty, "%7u", attr->local_pref);
    9436           4 :         else if (!json_paths)
    9437           0 :                 vty_out(vty, "       ");
    9438             : 
    9439           0 :         if (json_paths)
    9440           4 :                 json_object_int_add(json_path, "weight", attr->weight);
    9441             :         else
    9442           0 :                 vty_out(vty, "%7u ", attr->weight);
    9443             : 
    9444           4 :         if (json_paths)
    9445           4 :                 json_object_string_addf(json_path, "peerId", "%pSU",
    9446           4 :                                         &path->peer->su);
    9447             : 
    9448             :         /* Print aspath */
    9449           4 :         if (attr->aspath) {
    9450           4 :                 if (json_paths)
    9451           4 :                         json_object_string_add(json_path, "path",
    9452           4 :                                                attr->aspath->str);
    9453             :                 else
    9454           0 :                         aspath_print_vty(vty, attr->aspath);
    9455             :         }
    9456             : 
    9457             :         /* Print origin */
    9458           4 :         if (json_paths)
    9459           4 :                 json_object_string_add(json_path, "origin",
    9460           4 :                                        bgp_origin_long_str[attr->origin]);
    9461             :         else
    9462           0 :                 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
    9463             : 
    9464           4 :         if (json_paths) {
    9465           4 :                 if (bgp_evpn_is_esi_valid(&attr->esi)) {
    9466           0 :                         json_object_string_add(json_path, "esi",
    9467           0 :                                         esi_to_str(&attr->esi,
    9468             :                                         esi_buf, sizeof(esi_buf)));
    9469             :                 }
    9470           4 :                 if (safi == SAFI_EVPN &&
    9471           0 :                     attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
    9472           0 :                         json_ext_community = json_object_new_object();
    9473           0 :                         json_object_string_add(
    9474             :                                 json_ext_community, "string",
    9475           0 :                                 bgp_attr_get_ecommunity(attr)->str);
    9476           0 :                         json_object_object_add(json_path,
    9477             :                                                "extendedCommunity",
    9478             :                                                json_ext_community);
    9479             :                 }
    9480             : 
    9481           4 :                 if (nexthop_self)
    9482           0 :                         json_object_boolean_true_add(json_path,
    9483             :                                 "announceNexthopSelf");
    9484           4 :                 if (nexthop_othervrf) {
    9485           0 :                         json_object_string_add(json_path, "nhVrfName",
    9486             :                                 nexthop_vrfname);
    9487             : 
    9488           0 :                         json_object_int_add(json_path, "nhVrfId",
    9489             :                                 ((nexthop_vrfid == VRF_UNKNOWN)
    9490             :                                         ? -1
    9491           0 :                                         : (int)nexthop_vrfid));
    9492             :                 }
    9493             :         }
    9494             : 
    9495           4 :         if (json_paths) {
    9496           4 :                 if (json_nexthop_global || json_nexthop_ll) {
    9497           4 :                         json_nexthops = json_object_new_array();
    9498             : 
    9499           4 :                         if (json_nexthop_global)
    9500           4 :                                 json_object_array_add(json_nexthops,
    9501             :                                                       json_nexthop_global);
    9502             : 
    9503           4 :                         if (json_nexthop_ll)
    9504           0 :                                 json_object_array_add(json_nexthops,
    9505             :                                                       json_nexthop_ll);
    9506             : 
    9507           4 :                         json_object_object_add(json_path, "nexthops",
    9508             :                                                json_nexthops);
    9509             :                 }
    9510             : 
    9511           4 :                 json_object_array_add(json_paths, json_path);
    9512             :         } else {
    9513           0 :                 vty_out(vty, "\n");
    9514             : 
    9515           0 :                 if (safi == SAFI_EVPN) {
    9516           0 :                         if (bgp_evpn_is_esi_valid(&attr->esi)) {
    9517             :                                 /* XXX - add these params to the json out */
    9518           0 :                                 vty_out(vty, "%*s", 20, " ");
    9519           0 :                                 vty_out(vty, "ESI:%s",
    9520             :                                         esi_to_str(&attr->esi, esi_buf,
    9521             :                                                    sizeof(esi_buf)));
    9522             : 
    9523           0 :                                 vty_out(vty, "\n");
    9524             :                         }
    9525           0 :                         if (attr->flag &
    9526             :                                 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
    9527           0 :                                 vty_out(vty, "%*s", 20, " ");
    9528           0 :                                 vty_out(vty, "%s\n",
    9529           0 :                                         bgp_attr_get_ecommunity(attr)->str);
    9530             :                         }
    9531             :                 }
    9532             : 
    9533             : #ifdef ENABLE_BGP_VNC
    9534             :                 /* prints an additional line, indented, with VNC info, if
    9535             :                  * present */
    9536           0 :                 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
    9537           0 :                         rfapi_vty_out_vncinfo(vty, p, path, safi);
    9538             : #endif
    9539             :         }
    9540           4 : }
    9541             : 
    9542             : /* called from terminal list command */
    9543           0 : void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
    9544             :                        const struct prefix *p, struct attr *attr, safi_t safi,
    9545             :                        bool use_json, json_object *json_ar, bool wide)
    9546             : {
    9547           0 :         json_object *json_status = NULL;
    9548           0 :         json_object *json_net = NULL;
    9549           0 :         int len;
    9550           0 :         char buff[BUFSIZ];
    9551             : 
    9552             :         /* Route status display. */
    9553           0 :         if (use_json) {
    9554           0 :                 json_status = json_object_new_object();
    9555           0 :                 json_net = json_object_new_object();
    9556             :         } else {
    9557           0 :                 vty_out(vty, " *");
    9558           0 :                 vty_out(vty, ">");
    9559           0 :                 vty_out(vty, " ");
    9560             :         }
    9561             : 
    9562             :         /* print prefix and mask */
    9563           0 :         if (use_json) {
    9564           0 :                 if (safi == SAFI_EVPN)
    9565           0 :                         bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
    9566           0 :                 else if (p->family == AF_INET || p->family == AF_INET6) {
    9567           0 :                         json_object_string_add(
    9568             :                                 json_net, "addrPrefix",
    9569           0 :                                 inet_ntop(p->family, &p->u.prefix, buff,
    9570             :                                 BUFSIZ));
    9571           0 :                         json_object_int_add(json_net, "prefixLen",
    9572           0 :                                 p->prefixlen);
    9573           0 :                         json_object_string_addf(json_net, "network", "%pFX", p);
    9574             :                 }
    9575             :         } else
    9576           0 :                 route_vty_out_route(dest, p, vty, NULL, wide);
    9577             : 
    9578             :         /* Print attribute */
    9579           0 :         if (attr) {
    9580           0 :                 if (use_json) {
    9581           0 :                         if (p->family == AF_INET &&
    9582           0 :                             (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
    9583           0 :                              !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
    9584           0 :                                 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
    9585           0 :                                         json_object_string_addf(
    9586             :                                                 json_net, "nextHop", "%pI4",
    9587             :                                                 &attr->mp_nexthop_global_in);
    9588             :                                 else
    9589           0 :                                         json_object_string_addf(
    9590             :                                                 json_net, "nextHop", "%pI4",
    9591             :                                                 &attr->nexthop);
    9592           0 :                         } else if (p->family == AF_INET6 ||
    9593           0 :                                    BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
    9594           0 :                                 json_object_string_addf(
    9595             :                                         json_net, "nextHopGlobal", "%pI6",
    9596             :                                         &attr->mp_nexthop_global);
    9597           0 :                         } else if (p->family == AF_EVPN &&
    9598             :                                    !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
    9599           0 :                                 json_object_string_addf(
    9600             :                                         json_net, "nextHop", "%pI4",
    9601             :                                         &attr->mp_nexthop_global_in);
    9602             :                         }
    9603             : 
    9604           0 :                         if (attr->flag
    9605           0 :                             & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
    9606           0 :                                 json_object_int_add(json_net, "metric",
    9607           0 :                                                     attr->med);
    9608             : 
    9609           0 :                         if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
    9610           0 :                                 json_object_int_add(json_net, "locPrf",
    9611           0 :                                                     attr->local_pref);
    9612             : 
    9613           0 :                         json_object_int_add(json_net, "weight", attr->weight);
    9614             : 
    9615             :                         /* Print aspath */
    9616           0 :                         if (attr->aspath)
    9617           0 :                                 json_object_string_add(json_net, "path",
    9618           0 :                                                        attr->aspath->str);
    9619             : 
    9620             :                         /* Print origin */
    9621             : #if CONFDATE > 20231208
    9622             : CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
    9623             : #endif
    9624           0 :                         json_object_string_add(json_net, "bgpOriginCode",
    9625           0 :                                                bgp_origin_str[attr->origin]);
    9626           0 :                         json_object_string_add(
    9627             :                                 json_net, "origin",
    9628           0 :                                 bgp_origin_long_str[attr->origin]);
    9629             :                 } else {
    9630           0 :                         if (p->family == AF_INET &&
    9631           0 :                             (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
    9632           0 :                              safi == SAFI_EVPN ||
    9633           0 :                              !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
    9634           0 :                                 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
    9635             :                                     || safi == SAFI_EVPN)
    9636           0 :                                         vty_out(vty, "%-16pI4",
    9637             :                                                 &attr->mp_nexthop_global_in);
    9638           0 :                                 else if (wide)
    9639           0 :                                         vty_out(vty, "%-41pI4", &attr->nexthop);
    9640             :                                 else
    9641           0 :                                         vty_out(vty, "%-16pI4", &attr->nexthop);
    9642           0 :                         } else if (p->family == AF_INET6 ||
    9643           0 :                                    BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
    9644           0 :                                 len = vty_out(vty, "%pI6",
    9645             :                                               &attr->mp_nexthop_global);
    9646           0 :                                 len = wide ? (41 - len) : (16 - len);
    9647           0 :                                 if (len < 1)
    9648           0 :                                         vty_out(vty, "\n%*s", 36, " ");
    9649             :                                 else
    9650           0 :                                         vty_out(vty, "%*s", len, " ");
    9651             :                         }
    9652           0 :                         if (attr->flag
    9653           0 :                             & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
    9654           0 :                                 if (wide)
    9655           0 :                                         vty_out(vty, "%7u", attr->med);
    9656             :                                 else
    9657           0 :                                         vty_out(vty, "%10u", attr->med);
    9658           0 :                         else if (wide)
    9659           0 :                                 vty_out(vty, "       ");
    9660             :                         else
    9661           0 :                                 vty_out(vty, "          ");
    9662             : 
    9663           0 :                         if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
    9664           0 :                                 vty_out(vty, "%7u", attr->local_pref);
    9665             :                         else
    9666           0 :                                 vty_out(vty, "       ");
    9667             : 
    9668           0 :                         vty_out(vty, "%7u ", attr->weight);
    9669             : 
    9670             :                         /* Print aspath */
    9671           0 :                         if (attr->aspath)
    9672           0 :                                 aspath_print_vty(vty, attr->aspath);
    9673             : 
    9674             :                         /* Print origin */
    9675           0 :                         vty_out(vty, "%s", bgp_origin_str[attr->origin]);
    9676             :                 }
    9677             :         }
    9678           0 :         if (use_json) {
    9679           0 :                 struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(dest);
    9680             : 
    9681             : #if CONFDATE > 20231208
    9682             : CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
    9683             : #endif
    9684           0 :                 json_object_boolean_true_add(json_status, "*");
    9685           0 :                 json_object_boolean_true_add(json_status, ">");
    9686           0 :                 json_object_boolean_true_add(json_net, "valid");
    9687           0 :                 json_object_boolean_true_add(json_net, "best");
    9688             : 
    9689           0 :                 if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_MULTIPATH)) {
    9690           0 :                         json_object_boolean_true_add(json_status, "=");
    9691           0 :                         json_object_boolean_true_add(json_net, "multipath");
    9692             :                 }
    9693           0 :                 json_object_object_add(json_net, "appliedStatusSymbols",
    9694             :                                        json_status);
    9695           0 :                 json_object_object_addf(json_ar, json_net, "%pFX", p);
    9696             :         } else
    9697           0 :                 vty_out(vty, "\n");
    9698           0 : }
    9699             : 
    9700           0 : void route_vty_out_tag(struct vty *vty, const struct prefix *p,
    9701             :                        struct bgp_path_info *path, int display, safi_t safi,
    9702             :                        json_object *json)
    9703             : {
    9704           0 :         json_object *json_out = NULL;
    9705           0 :         struct attr *attr;
    9706           0 :         mpls_label_t label = MPLS_INVALID_LABEL;
    9707             : 
    9708           0 :         if (!path->extra)
    9709           0 :                 return;
    9710             : 
    9711           0 :         if (json)
    9712           0 :                 json_out = json_object_new_object();
    9713             : 
    9714             :         /* short status lead text */
    9715           0 :         route_vty_short_status_out(vty, path, p, json_out);
    9716             : 
    9717             :         /* print prefix and mask */
    9718           0 :         if (json == NULL) {
    9719           0 :                 if (!display)
    9720           0 :                         route_vty_out_route(path->net, p, vty, NULL, false);
    9721             :                 else
    9722           0 :                         vty_out(vty, "%*s", 17, " ");
    9723             :         }
    9724             : 
    9725             :         /* Print attribute */
    9726           0 :         attr = path->attr;
    9727           0 :         if (((p->family == AF_INET) &&
    9728           0 :              ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
    9729           0 :             (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) ||
    9730           0 :             (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
    9731           0 :                 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
    9732           0 :                     || safi == SAFI_EVPN) {
    9733           0 :                         if (json)
    9734           0 :                                 json_object_string_addf(
    9735             :                                         json_out, "mpNexthopGlobalIn", "%pI4",
    9736             :                                         &attr->mp_nexthop_global_in);
    9737             :                         else
    9738           0 :                                 vty_out(vty, "%-16pI4",
    9739             :                                         &attr->mp_nexthop_global_in);
    9740             :                 } else {
    9741           0 :                         if (json)
    9742           0 :                                 json_object_string_addf(json_out, "nexthop",
    9743             :                                                         "%pI4", &attr->nexthop);
    9744             :                         else
    9745           0 :                                 vty_out(vty, "%-16pI4", &attr->nexthop);
    9746             :                 }
    9747           0 :         } else if (((p->family == AF_INET6) &&
    9748           0 :                     ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
    9749           0 :                    (safi == SAFI_EVPN && BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) ||
    9750           0 :                    (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
    9751           0 :                 char buf_a[512];
    9752             : 
    9753           0 :                 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
    9754           0 :                         if (json)
    9755           0 :                                 json_object_string_addf(
    9756             :                                         json_out, "mpNexthopGlobalIn", "%pI6",
    9757             :                                         &attr->mp_nexthop_global);
    9758             :                         else
    9759           0 :                                 vty_out(vty, "%s",
    9760             :                                         inet_ntop(AF_INET6,
    9761           0 :                                                   &attr->mp_nexthop_global,
    9762             :                                                   buf_a, sizeof(buf_a)));
    9763           0 :                 } else if (attr->mp_nexthop_len
    9764             :                            == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
    9765           0 :                         snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
    9766             :                                    &attr->mp_nexthop_global,
    9767             :                                    &attr->mp_nexthop_local);
    9768           0 :                         if (json)
    9769           0 :                                 json_object_string_add(json_out,
    9770             :                                                        "mpNexthopGlobalLocal",
    9771             :                                                        buf_a);
    9772             :                         else
    9773           0 :                                 vty_out(vty, "%s", buf_a);
    9774             :                 }
    9775             :         }
    9776             : 
    9777           0 :         label = decode_label(&path->extra->label[0]);
    9778             : 
    9779           0 :         if (bgp_is_valid_label(&label)) {
    9780           0 :                 if (json) {
    9781           0 :                         json_object_int_add(json_out, "notag", label);
    9782           0 :                         json_object_array_add(json, json_out);
    9783             :                 } else {
    9784           0 :                         vty_out(vty, "notag/%d", label);
    9785           0 :                         vty_out(vty, "\n");
    9786             :                 }
    9787           0 :         } else if (!json)
    9788           0 :                 vty_out(vty, "\n");
    9789             : }
    9790             : 
    9791           0 : void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
    9792             :                            struct bgp_path_info *path, int display,
    9793             :                            json_object *json_paths)
    9794             : {
    9795           0 :         struct attr *attr;
    9796           0 :         json_object *json_path = NULL;
    9797           0 :         json_object *json_nexthop = NULL;
    9798           0 :         json_object *json_overlay = NULL;
    9799             : 
    9800           0 :         if (!path->extra)
    9801             :                 return;
    9802             : 
    9803           0 :         if (json_paths) {
    9804           0 :                 json_path = json_object_new_object();
    9805           0 :                 json_overlay = json_object_new_object();
    9806           0 :                 json_nexthop = json_object_new_object();
    9807             :         }
    9808             : 
    9809             :         /* short status lead text */
    9810           0 :         route_vty_short_status_out(vty, path, p, json_path);
    9811             : 
    9812             :         /* print prefix and mask */
    9813           0 :         if (!display)
    9814           0 :                 route_vty_out_route(path->net, p, vty, json_path, false);
    9815             :         else
    9816           0 :                 vty_out(vty, "%*s", 17, " ");
    9817             : 
    9818             :         /* Print attribute */
    9819           0 :         attr = path->attr;
    9820           0 :         int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
    9821             : 
    9822           0 :         switch (af) {
    9823             :         case AF_INET:
    9824           0 :                 if (!json_path) {
    9825           0 :                         vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
    9826             :                 } else {
    9827           0 :                         json_object_string_addf(json_nexthop, "ip", "%pI4",
    9828             :                                                 &attr->mp_nexthop_global_in);
    9829             : 
    9830           0 :                         json_object_string_add(json_nexthop, "afi", "ipv4");
    9831             : 
    9832           0 :                         json_object_object_add(json_path, "nexthop",
    9833             :                                                json_nexthop);
    9834             :                 }
    9835             :                 break;
    9836           0 :         case AF_INET6:
    9837           0 :                 if (!json_path) {
    9838           0 :                         vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
    9839             :                                 &attr->mp_nexthop_local);
    9840             :                 } else {
    9841           0 :                         json_object_string_addf(json_nexthop, "ipv6Global",
    9842             :                                                 "%pI6",
    9843             :                                                 &attr->mp_nexthop_global);
    9844             : 
    9845           0 :                         json_object_string_addf(json_nexthop, "ipv6LinkLocal",
    9846             :                                                 "%pI6",
    9847             :                                                 &attr->mp_nexthop_local);
    9848             : 
    9849           0 :                         json_object_string_add(json_nexthop, "afi", "ipv6");
    9850             : 
    9851           0 :                         json_object_object_add(json_path, "nexthop",
    9852             :                                                json_nexthop);
    9853             :                 }
    9854             :                 break;
    9855             :         default:
    9856           0 :                 if (!json_path) {
    9857           0 :                         vty_out(vty, "?");
    9858             :                 } else {
    9859           0 :                         json_object_string_add(json_nexthop, "error",
    9860             :                                                "Unsupported address-family");
    9861             :                 }
    9862             :         }
    9863             : 
    9864           0 :         const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
    9865             : 
    9866           0 :         if (!json_path)
    9867           0 :                 vty_out(vty, "/%pIA", &eo->gw_ip);
    9868             :         else
    9869           0 :                 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
    9870             : 
    9871           0 :         if (bgp_attr_get_ecommunity(attr)) {
    9872           0 :                 char *mac = NULL;
    9873           0 :                 struct ecommunity_val *routermac = ecommunity_lookup(
    9874           0 :                         bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
    9875             :                         ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
    9876             : 
    9877           0 :                 if (routermac)
    9878           0 :                         mac = ecom_mac2str((char *)routermac->val);
    9879           0 :                 if (mac) {
    9880           0 :                         if (!json_path) {
    9881           0 :                                 vty_out(vty, "/%s", mac);
    9882             :                         } else {
    9883           0 :                                 json_object_string_add(json_overlay, "rmac",
    9884             :                                                        mac);
    9885             :                         }
    9886           0 :                         XFREE(MTYPE_TMP, mac);
    9887             :                 }
    9888             :         }
    9889             : 
    9890           0 :         if (!json_path) {
    9891           0 :                 vty_out(vty, "\n");
    9892             :         } else {
    9893           0 :                 json_object_object_add(json_path, "overlay", json_overlay);
    9894             : 
    9895           0 :                 json_object_array_add(json_paths, json_path);
    9896             :         }
    9897             : }
    9898             : 
    9899             : /* dampening route */
    9900           0 : static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
    9901             :                                struct bgp_path_info *path, int display,
    9902             :                                afi_t afi, safi_t safi, bool use_json,
    9903             :                                json_object *json_paths)
    9904             : {
    9905           0 :         struct attr *attr = path->attr;
    9906           0 :         int len;
    9907           0 :         char timebuf[BGP_UPTIME_LEN];
    9908           0 :         json_object *json_path = NULL;
    9909             : 
    9910           0 :         if (use_json)
    9911           0 :                 json_path = json_object_new_object();
    9912             : 
    9913             :         /* short status lead text */
    9914           0 :         route_vty_short_status_out(vty, path, p, json_path);
    9915             : 
    9916             :         /* print prefix and mask */
    9917           0 :         if (!use_json) {
    9918           0 :                 if (!display)
    9919           0 :                         route_vty_out_route(path->net, p, vty, NULL, false);
    9920             :                 else
    9921           0 :                         vty_out(vty, "%*s", 17, " ");
    9922             : 
    9923           0 :                 len = vty_out(vty, "%s", path->peer->host);
    9924           0 :                 len = 17 - len;
    9925             : 
    9926           0 :                 if (len < 1)
    9927           0 :                         vty_out(vty, "\n%*s", 34, " ");
    9928             :                 else
    9929           0 :                         vty_out(vty, "%*s", len, " ");
    9930             : 
    9931           0 :                 vty_out(vty, "%s ",
    9932             :                         bgp_damp_reuse_time_vty(vty, path, timebuf,
    9933             :                                                 BGP_UPTIME_LEN, afi, safi,
    9934             :                                                 use_json, NULL));
    9935             : 
    9936           0 :                 if (attr->aspath)
    9937           0 :                         aspath_print_vty(vty, attr->aspath);
    9938             : 
    9939           0 :                 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
    9940             : 
    9941           0 :                 vty_out(vty, "\n");
    9942             :         } else {
    9943           0 :                 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
    9944             :                                         safi, use_json, json_path);
    9945             : 
    9946           0 :                 if (attr->aspath)
    9947           0 :                         json_object_string_add(json_path, "asPath",
    9948           0 :                                                attr->aspath->str);
    9949             : 
    9950           0 :                 json_object_string_add(json_path, "origin",
    9951           0 :                                        bgp_origin_str[attr->origin]);
    9952           0 :                 json_object_string_add(json_path, "peerHost", path->peer->host);
    9953             : 
    9954           0 :                 json_object_array_add(json_paths, json_path);
    9955             :         }
    9956           0 : }
    9957             : 
    9958             : /* flap route */
    9959           0 : static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
    9960             :                                struct bgp_path_info *path, int display,
    9961             :                                afi_t afi, safi_t safi, bool use_json,
    9962             :                                json_object *json_paths)
    9963             : {
    9964           0 :         struct attr *attr = path->attr;
    9965           0 :         struct bgp_damp_info *bdi;
    9966           0 :         char timebuf[BGP_UPTIME_LEN];
    9967           0 :         int len;
    9968           0 :         json_object *json_path = NULL;
    9969             : 
    9970           0 :         if (!path->extra)
    9971           0 :                 return;
    9972             : 
    9973           0 :         if (use_json)
    9974           0 :                 json_path = json_object_new_object();
    9975             : 
    9976           0 :         bdi = path->extra->damp_info;
    9977             : 
    9978             :         /* short status lead text */
    9979           0 :         route_vty_short_status_out(vty, path, p, json_path);
    9980             : 
    9981           0 :         if (!use_json) {
    9982           0 :                 if (!display)
    9983           0 :                         route_vty_out_route(path->net, p, vty, NULL, false);
    9984             :                 else
    9985           0 :                         vty_out(vty, "%*s", 17, " ");
    9986             : 
    9987           0 :                 len = vty_out(vty, "%s", path->peer->host);
    9988           0 :                 len = 16 - len;
    9989           0 :                 if (len < 1)
    9990           0 :                         vty_out(vty, "\n%*s", 33, " ");
    9991             :                 else
    9992           0 :                         vty_out(vty, "%*s", len, " ");
    9993             : 
    9994           0 :                 len = vty_out(vty, "%d", bdi->flap);
    9995           0 :                 len = 5 - len;
    9996           0 :                 if (len < 1)
    9997           0 :                         vty_out(vty, " ");
    9998             :                 else
    9999           0 :                         vty_out(vty, "%*s", len, " ");
   10000             : 
   10001           0 :                 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
   10002             :                                                 BGP_UPTIME_LEN, 0, NULL));
   10003             : 
   10004           0 :                 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
   10005           0 :                     && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
   10006           0 :                         vty_out(vty, "%s ",
   10007             :                                 bgp_damp_reuse_time_vty(vty, path, timebuf,
   10008             :                                                         BGP_UPTIME_LEN, afi,
   10009             :                                                         safi, use_json, NULL));
   10010             :                 else
   10011           0 :                         vty_out(vty, "%*s ", 8, " ");
   10012             : 
   10013           0 :                 if (attr->aspath)
   10014           0 :                         aspath_print_vty(vty, attr->aspath);
   10015             : 
   10016           0 :                 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
   10017             : 
   10018           0 :                 vty_out(vty, "\n");
   10019             :         } else {
   10020           0 :                 json_object_string_add(json_path, "peerHost", path->peer->host);
   10021           0 :                 json_object_int_add(json_path, "bdiFlap", bdi->flap);
   10022             : 
   10023           0 :                 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
   10024             :                             json_path);
   10025             : 
   10026           0 :                 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
   10027           0 :                     && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
   10028           0 :                         bgp_damp_reuse_time_vty(vty, path, timebuf,
   10029             :                                                 BGP_UPTIME_LEN, afi, safi,
   10030             :                                                 use_json, json_path);
   10031             : 
   10032           0 :                 if (attr->aspath)
   10033           0 :                         json_object_string_add(json_path, "asPath",
   10034           0 :                                                attr->aspath->str);
   10035             : 
   10036           0 :                 json_object_string_add(json_path, "origin",
   10037           0 :                                        bgp_origin_str[attr->origin]);
   10038             : 
   10039           0 :                 json_object_array_add(json_paths, json_path);
   10040             :         }
   10041             : }
   10042             : 
   10043           0 : static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
   10044             :                                         int *first, const char *header,
   10045             :                                         json_object *json_adv_to)
   10046             : {
   10047           0 :         json_object *json_peer = NULL;
   10048             : 
   10049           0 :         if (json_adv_to) {
   10050             :                 /* 'advertised-to' is a dictionary of peers we have advertised
   10051             :                  * this
   10052             :                  * prefix too.  The key is the peer's IP or swpX, the value is
   10053             :                  * the
   10054             :                  * hostname if we know it and "" if not.
   10055             :                  */
   10056           0 :                 json_peer = json_object_new_object();
   10057             : 
   10058           0 :                 if (peer->hostname)
   10059           0 :                         json_object_string_add(json_peer, "hostname",
   10060             :                                                peer->hostname);
   10061             : 
   10062           0 :                 if (peer->conf_if)
   10063           0 :                         json_object_object_add(json_adv_to, peer->conf_if,
   10064             :                                                json_peer);
   10065             :                 else
   10066           0 :                         json_object_object_addf(json_adv_to, json_peer, "%pSU",
   10067             :                                                 &peer->su);
   10068             :         } else {
   10069           0 :                 if (*first) {
   10070           0 :                         vty_out(vty, "%s", header);
   10071           0 :                         *first = 0;
   10072             :                 }
   10073             : 
   10074           0 :                 if (peer->hostname
   10075           0 :                     && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
   10076           0 :                         if (peer->conf_if)
   10077           0 :                                 vty_out(vty, " %s(%s)", peer->hostname,
   10078             :                                         peer->conf_if);
   10079             :                         else
   10080           0 :                                 vty_out(vty, " %s(%pSU)", peer->hostname,
   10081             :                                         &peer->su);
   10082             :                 } else {
   10083           0 :                         if (peer->conf_if)
   10084           0 :                                 vty_out(vty, " %s", peer->conf_if);
   10085             :                         else
   10086           0 :                                 vty_out(vty, " %pSU", &peer->su);
   10087             :                 }
   10088             :         }
   10089           0 : }
   10090             : 
   10091           0 : static void route_vty_out_tx_ids(struct vty *vty,
   10092             :                                  struct bgp_addpath_info_data *d)
   10093             : {
   10094           0 :         int i;
   10095             : 
   10096           0 :         for (i = 0; i < BGP_ADDPATH_MAX; i++) {
   10097           0 :                 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
   10098             :                         d->addpath_tx_id[i],
   10099             :                         i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
   10100             :         }
   10101           0 : }
   10102             : 
   10103           0 : static void route_vty_out_detail_es_info(struct vty *vty,
   10104             :                                          struct bgp_path_info *pi,
   10105             :                                          struct attr *attr,
   10106             :                                          json_object *json_path)
   10107             : {
   10108           0 :         char esi_buf[ESI_STR_LEN];
   10109           0 :         bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
   10110           0 :         bool peer_router = !!CHECK_FLAG(attr->es_flags,
   10111             :                         ATTR_ES_PEER_ROUTER);
   10112           0 :         bool peer_active = !!CHECK_FLAG(attr->es_flags,
   10113             :                         ATTR_ES_PEER_ACTIVE);
   10114           0 :         bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
   10115             :                         ATTR_ES_PEER_PROXY);
   10116           0 :         esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
   10117           0 :         if (json_path) {
   10118           0 :                 json_object *json_es_info = NULL;
   10119             : 
   10120           0 :                 json_object_string_add(
   10121             :                                 json_path, "esi",
   10122             :                                 esi_buf);
   10123           0 :                 if (es_local || bgp_evpn_attr_is_sync(attr)) {
   10124           0 :                         json_es_info = json_object_new_object();
   10125           0 :                         if (es_local)
   10126           0 :                                 json_object_boolean_true_add(
   10127             :                                                 json_es_info, "localEs");
   10128           0 :                         if (peer_active)
   10129           0 :                                 json_object_boolean_true_add(
   10130             :                                                 json_es_info, "peerActive");
   10131           0 :                         if (peer_proxy)
   10132           0 :                                 json_object_boolean_true_add(
   10133             :                                                 json_es_info, "peerProxy");
   10134           0 :                         if (peer_router)
   10135           0 :                                 json_object_boolean_true_add(
   10136             :                                                 json_es_info, "peerRouter");
   10137           0 :                         if (attr->mm_sync_seqnum)
   10138           0 :                                 json_object_int_add(
   10139             :                                                 json_es_info, "peerSeq",
   10140             :                                                 attr->mm_sync_seqnum);
   10141           0 :                         json_object_object_add(
   10142             :                                         json_path, "es_info",
   10143             :                                         json_es_info);
   10144             :                 }
   10145             :         } else {
   10146           0 :                 if (bgp_evpn_attr_is_sync(attr))
   10147           0 :                         vty_out(vty,
   10148             :                                         "      ESI %s %s peer-info: (%s%s%sMM: %d)\n",
   10149             :                                         esi_buf,
   10150             :                                         es_local ? "local-es":"",
   10151             :                                         peer_proxy ? "proxy " : "",
   10152             :                                         peer_active ? "active ":"",
   10153             :                                         peer_router ? "router ":"",
   10154             :                                         attr->mm_sync_seqnum);
   10155             :                 else
   10156           0 :                         vty_out(vty, "      ESI %s %s\n",
   10157             :                                         esi_buf,
   10158             :                                         es_local ? "local-es":"");
   10159             :         }
   10160           0 : }
   10161             : 
   10162           0 : void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
   10163             :                           const struct prefix *p, struct bgp_path_info *path,
   10164             :                           afi_t afi, safi_t safi,
   10165             :                           enum rpki_states rpki_curr_state,
   10166             :                           json_object *json_paths)
   10167             : {
   10168           0 :         char buf[INET6_ADDRSTRLEN];
   10169           0 :         char tag_buf[30];
   10170           0 :         struct attr *attr = path->attr;
   10171           0 :         time_t tbuf;
   10172           0 :         json_object *json_bestpath = NULL;
   10173           0 :         json_object *json_cluster_list = NULL;
   10174           0 :         json_object *json_cluster_list_list = NULL;
   10175           0 :         json_object *json_ext_community = NULL;
   10176           0 :         json_object *json_last_update = NULL;
   10177           0 :         json_object *json_pmsi = NULL;
   10178           0 :         json_object *json_nexthop_global = NULL;
   10179           0 :         json_object *json_nexthop_ll = NULL;
   10180           0 :         json_object *json_nexthops = NULL;
   10181           0 :         json_object *json_path = NULL;
   10182           0 :         json_object *json_peer = NULL;
   10183           0 :         json_object *json_string = NULL;
   10184           0 :         json_object *json_adv_to = NULL;
   10185           0 :         int first = 0;
   10186           0 :         struct listnode *node, *nnode;
   10187           0 :         struct peer *peer;
   10188           0 :         bool addpath_capable;
   10189           0 :         int has_adj;
   10190           0 :         unsigned int first_as;
   10191           0 :         bool nexthop_self =
   10192           0 :                 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
   10193           0 :         int i;
   10194           0 :         char *nexthop_hostname =
   10195           0 :                 bgp_nexthop_hostname(path->peer, path->nexthop);
   10196           0 :         uint32_t ttl = 0;
   10197           0 :         uint32_t bos = 0;
   10198           0 :         uint32_t exp = 0;
   10199           0 :         mpls_label_t label = MPLS_INVALID_LABEL;
   10200           0 :         tag_buf[0] = '\0';
   10201           0 :         struct bgp_path_info *bpi_ultimate =
   10202           0 :                 bgp_get_imported_bpi_ultimate(path);
   10203             : 
   10204           0 :         if (json_paths) {
   10205           0 :                 json_path = json_object_new_object();
   10206           0 :                 json_peer = json_object_new_object();
   10207           0 :                 json_nexthop_global = json_object_new_object();
   10208             :         }
   10209             : 
   10210           0 :         if (safi == SAFI_EVPN) {
   10211           0 :                 if (!json_paths)
   10212           0 :                         vty_out(vty, "  Route %pFX", p);
   10213             :         }
   10214             : 
   10215           0 :         if (path->extra) {
   10216           0 :                 if (path->extra && path->extra->num_labels) {
   10217           0 :                         bgp_evpn_label2str(path->extra->label,
   10218             :                                            path->extra->num_labels, tag_buf,
   10219             :                                            sizeof(tag_buf));
   10220             :                 }
   10221           0 :                 if (safi == SAFI_EVPN) {
   10222           0 :                         if (!json_paths) {
   10223           0 :                                 if (tag_buf[0] != '\0')
   10224           0 :                                         vty_out(vty, " VNI %s", tag_buf);
   10225             :                         } else {
   10226           0 :                                 if (tag_buf[0])
   10227           0 :                                         json_object_string_add(json_path, "vni",
   10228             :                                                                tag_buf);
   10229             :                         }
   10230             :                 }
   10231             :         }
   10232             : 
   10233           0 :         if (safi == SAFI_EVPN
   10234           0 :             && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
   10235           0 :                 char gwip_buf[INET6_ADDRSTRLEN];
   10236             : 
   10237           0 :                 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
   10238             :                            sizeof(gwip_buf));
   10239             : 
   10240           0 :                 if (json_paths)
   10241           0 :                         json_object_string_add(json_path, "gatewayIP",
   10242             :                                                gwip_buf);
   10243             :                 else
   10244           0 :                         vty_out(vty, " Gateway IP %s", gwip_buf);
   10245             :         }
   10246             : 
   10247           0 :         if (safi == SAFI_EVPN && !json_path)
   10248           0 :                 vty_out(vty, "\n");
   10249             : 
   10250             : 
   10251           0 :         if (path->extra && path->extra->parent && !json_paths) {
   10252           0 :                 struct bgp_path_info *parent_ri;
   10253           0 :                 struct bgp_dest *dest, *pdest;
   10254             : 
   10255           0 :                 parent_ri = (struct bgp_path_info *)path->extra->parent;
   10256           0 :                 dest = parent_ri->net;
   10257           0 :                 if (dest && dest->pdest) {
   10258           0 :                         pdest = dest->pdest;
   10259           0 :                         if (is_pi_family_evpn(parent_ri)) {
   10260           0 :                                 vty_out(vty,
   10261             :                                         "  Imported from %pRD:%pFX, VNI %s",
   10262           0 :                                         (struct prefix_rd *)bgp_dest_get_prefix(
   10263             :                                                 pdest),
   10264             :                                         (struct prefix_evpn *)
   10265           0 :                                                 bgp_dest_get_prefix(dest),
   10266             :                                         tag_buf);
   10267           0 :                                 if (CHECK_FLAG(attr->es_flags, ATTR_ES_L3_NHG))
   10268           0 :                                         vty_out(vty, ", L3NHG %s",
   10269             :                                                 CHECK_FLAG(
   10270             :                                                         attr->es_flags,
   10271             :                                                         ATTR_ES_L3_NHG_ACTIVE)
   10272             :                                                         ? "active"
   10273             :                                                         : "inactive");
   10274           0 :                                 vty_out(vty, "\n");
   10275             : 
   10276             :                         } else
   10277           0 :                                 vty_out(vty, "  Imported from %pRD:%pFX\n",
   10278           0 :                                         (struct prefix_rd *)bgp_dest_get_prefix(
   10279             :                                                 pdest),
   10280             :                                         (struct prefix_evpn *)
   10281           0 :                                                 bgp_dest_get_prefix(dest));
   10282             :                 }
   10283             :         }
   10284             : 
   10285             :         /* Line1 display AS-path, Aggregator */
   10286           0 :         if (attr->aspath) {
   10287           0 :                 if (json_paths) {
   10288           0 :                         if (!attr->aspath->json)
   10289           0 :                                 aspath_str_update(attr->aspath, true);
   10290           0 :                         json_object_lock(attr->aspath->json);
   10291           0 :                         json_object_object_add(json_path, "aspath",
   10292           0 :                                                attr->aspath->json);
   10293             :                 } else {
   10294           0 :                         if (attr->aspath->segments)
   10295           0 :                                 vty_out(vty, "  %s", attr->aspath->str);
   10296             :                         else
   10297           0 :                                 vty_out(vty, "  Local");
   10298             :                 }
   10299             :         }
   10300             : 
   10301           0 :         if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
   10302           0 :                 if (json_paths)
   10303           0 :                         json_object_boolean_true_add(json_path, "removed");
   10304             :                 else
   10305           0 :                         vty_out(vty, ", (removed)");
   10306             :         }
   10307             : 
   10308           0 :         if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
   10309           0 :                 if (json_paths)
   10310           0 :                         json_object_boolean_true_add(json_path, "stale");
   10311             :                 else
   10312           0 :                         vty_out(vty, ", (stale)");
   10313             :         }
   10314             : 
   10315           0 :         if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
   10316           0 :                 if (json_paths) {
   10317           0 :                         json_object_int_add(json_path, "aggregatorAs",
   10318           0 :                                             attr->aggregator_as);
   10319           0 :                         json_object_string_addf(json_path, "aggregatorId",
   10320             :                                                 "%pI4", &attr->aggregator_addr);
   10321             :                 } else {
   10322           0 :                         vty_out(vty, ", (aggregated by %u %pI4)",
   10323             :                                 attr->aggregator_as, &attr->aggregator_addr);
   10324             :                 }
   10325             :         }
   10326             : 
   10327           0 :         if (CHECK_FLAG(path->peer->af_flags[afi][safi],
   10328             :                        PEER_FLAG_REFLECTOR_CLIENT)) {
   10329           0 :                 if (json_paths)
   10330           0 :                         json_object_boolean_true_add(json_path,
   10331             :                                                      "rxedFromRrClient");
   10332             :                 else
   10333           0 :                         vty_out(vty, ", (Received from a RR-client)");
   10334             :         }
   10335             : 
   10336           0 :         if (CHECK_FLAG(path->peer->af_flags[afi][safi],
   10337             :                        PEER_FLAG_RSERVER_CLIENT)) {
   10338           0 :                 if (json_paths)
   10339           0 :                         json_object_boolean_true_add(json_path,
   10340             :                                                      "rxedFromRsClient");
   10341             :                 else
   10342           0 :                         vty_out(vty, ", (Received from a RS-client)");
   10343             :         }
   10344             : 
   10345           0 :         if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
   10346           0 :                 if (json_paths)
   10347           0 :                         json_object_boolean_true_add(json_path,
   10348             :                                                      "dampeningHistoryEntry");
   10349             :                 else
   10350           0 :                         vty_out(vty, ", (history entry)");
   10351           0 :         } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
   10352           0 :                 if (json_paths)
   10353           0 :                         json_object_boolean_true_add(json_path,
   10354             :                                                      "dampeningSuppressed");
   10355             :                 else
   10356           0 :                         vty_out(vty, ", (suppressed due to dampening)");
   10357             :         }
   10358             : 
   10359           0 :         if (!json_paths)
   10360           0 :                 vty_out(vty, "\n");
   10361             : 
   10362             :         /* Line2 display Next-hop, Neighbor, Router-id */
   10363             :         /* Display the nexthop */
   10364             : 
   10365           0 :         if ((p->family == AF_INET || p->family == AF_ETHERNET ||
   10366           0 :              p->family == AF_EVPN) &&
   10367           0 :             (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
   10368           0 :              !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
   10369           0 :                 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
   10370             :                     || safi == SAFI_EVPN) {
   10371           0 :                         if (json_paths) {
   10372           0 :                                 json_object_string_addf(
   10373             :                                         json_nexthop_global, "ip", "%pI4",
   10374             :                                         &attr->mp_nexthop_global_in);
   10375             : 
   10376           0 :                                 if (path->peer->hostname)
   10377           0 :                                         json_object_string_add(
   10378             :                                                 json_nexthop_global, "hostname",
   10379             :                                                 path->peer->hostname);
   10380             :                         } else {
   10381           0 :                                 if (nexthop_hostname)
   10382           0 :                                         vty_out(vty, "    %pI4(%s)",
   10383             :                                                 &attr->mp_nexthop_global_in,
   10384             :                                                 nexthop_hostname);
   10385             :                                 else
   10386           0 :                                         vty_out(vty, "    %pI4",
   10387             :                                                 &attr->mp_nexthop_global_in);
   10388             :                         }
   10389             :                 } else {
   10390           0 :                         if (json_paths) {
   10391           0 :                                 json_object_string_addf(json_nexthop_global,
   10392             :                                                         "ip", "%pI4",
   10393             :                                                         &attr->nexthop);
   10394             : 
   10395           0 :                                 if (path->peer->hostname)
   10396           0 :                                         json_object_string_add(
   10397             :                                                 json_nexthop_global, "hostname",
   10398             :                                                 path->peer->hostname);
   10399             :                         } else {
   10400           0 :                                 if (nexthop_hostname)
   10401           0 :                                         vty_out(vty, "    %pI4(%s)",
   10402             :                                                 &attr->nexthop,
   10403             :                                                 nexthop_hostname);
   10404             :                                 else
   10405           0 :                                         vty_out(vty, "    %pI4",
   10406             :                                                 &attr->nexthop);
   10407             :                         }
   10408             :                 }
   10409             : 
   10410           0 :                 if (json_paths)
   10411           0 :                         json_object_string_add(json_nexthop_global, "afi",
   10412             :                                                "ipv4");
   10413             :         } else {
   10414           0 :                 if (json_paths) {
   10415           0 :                         json_object_string_addf(json_nexthop_global, "ip",
   10416             :                                                 "%pI6",
   10417             :                                                 &attr->mp_nexthop_global);
   10418             : 
   10419           0 :                         if (path->peer->hostname)
   10420           0 :                                 json_object_string_add(json_nexthop_global,
   10421             :                                                        "hostname",
   10422             :                                                        path->peer->hostname);
   10423             : 
   10424           0 :                         json_object_string_add(json_nexthop_global, "afi",
   10425             :                                                "ipv6");
   10426           0 :                         json_object_string_add(json_nexthop_global, "scope",
   10427             :                                                "global");
   10428             :                 } else {
   10429           0 :                         if (nexthop_hostname)
   10430           0 :                                 vty_out(vty, "    %pI6(%s)",
   10431             :                                         &attr->mp_nexthop_global,
   10432             :                                         nexthop_hostname);
   10433             :                         else
   10434           0 :                                 vty_out(vty, "    %pI6",
   10435             :                                         &attr->mp_nexthop_global);
   10436             :                 }
   10437             :         }
   10438             : 
   10439             :         /* Display the IGP cost or 'inaccessible' */
   10440           0 :         if (!CHECK_FLAG(bpi_ultimate->flags, BGP_PATH_VALID)) {
   10441           0 :                 bool import = CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK);
   10442             : 
   10443           0 :                 if (json_paths) {
   10444           0 :                         json_object_boolean_false_add(json_nexthop_global,
   10445             :                                                       "accessible");
   10446           0 :                         json_object_boolean_add(json_nexthop_global,
   10447             :                                                 "importCheckEnabled", import);
   10448             :                 } else {
   10449           0 :                         vty_out(vty, " (inaccessible%s)",
   10450             :                                 import ? ", import-check enabled" : "");
   10451             :                 }
   10452             :         } else {
   10453           0 :                 if (bpi_ultimate->extra && bpi_ultimate->extra->igpmetric) {
   10454           0 :                         if (json_paths)
   10455           0 :                                 json_object_int_add(
   10456             :                                         json_nexthop_global, "metric",
   10457             :                                         bpi_ultimate->extra->igpmetric);
   10458             :                         else
   10459           0 :                                 vty_out(vty, " (metric %u)",
   10460             :                                         bpi_ultimate->extra->igpmetric);
   10461             :                 }
   10462             : 
   10463             :                 /* IGP cost is 0, display this only for json */
   10464             :                 else {
   10465           0 :                         if (json_paths)
   10466           0 :                                 json_object_int_add(json_nexthop_global,
   10467             :                                                     "metric", 0);
   10468             :                 }
   10469             : 
   10470           0 :                 if (json_paths)
   10471           0 :                         json_object_boolean_true_add(json_nexthop_global,
   10472             :                                                      "accessible");
   10473             :         }
   10474             : 
   10475             :         /* Display peer "from" output */
   10476             :         /* This path was originated locally */
   10477           0 :         if (path->peer == bgp->peer_self) {
   10478             : 
   10479           0 :                 if (safi == SAFI_EVPN || (p->family == AF_INET &&
   10480           0 :                                           !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
   10481           0 :                         if (json_paths)
   10482           0 :                                 json_object_string_add(json_peer, "peerId",
   10483             :                                                        "0.0.0.0");
   10484             :                         else
   10485           0 :                                 vty_out(vty, " from 0.0.0.0 ");
   10486             :                 } else {
   10487           0 :                         if (json_paths)
   10488           0 :                                 json_object_string_add(json_peer, "peerId",
   10489             :                                                        "::");
   10490             :                         else
   10491           0 :                                 vty_out(vty, " from :: ");
   10492             :                 }
   10493             : 
   10494           0 :                 if (json_paths)
   10495           0 :                         json_object_string_addf(json_peer, "routerId", "%pI4",
   10496             :                                                 &bgp->router_id);
   10497             :                 else
   10498           0 :                         vty_out(vty, "(%pI4)", &bgp->router_id);
   10499             :         }
   10500             : 
   10501             :         /* We RXed this path from one of our peers */
   10502             :         else {
   10503             : 
   10504           0 :                 if (json_paths) {
   10505           0 :                         json_object_string_addf(json_peer, "peerId", "%pSU",
   10506             :                                                 &path->peer->su);
   10507           0 :                         json_object_string_addf(json_peer, "routerId", "%pI4",
   10508           0 :                                                 &path->peer->remote_id);
   10509             : 
   10510           0 :                         if (path->peer->hostname)
   10511           0 :                                 json_object_string_add(json_peer, "hostname",
   10512             :                                                        path->peer->hostname);
   10513             : 
   10514           0 :                         if (path->peer->domainname)
   10515           0 :                                 json_object_string_add(json_peer, "domainname",
   10516             :                                                        path->peer->domainname);
   10517             : 
   10518           0 :                         if (path->peer->conf_if)
   10519           0 :                                 json_object_string_add(json_peer, "interface",
   10520             :                                                        path->peer->conf_if);
   10521             :                 } else {
   10522           0 :                         if (path->peer->conf_if) {
   10523           0 :                                 if (path->peer->hostname
   10524           0 :                                     && CHECK_FLAG(path->peer->bgp->flags,
   10525             :                                                   BGP_FLAG_SHOW_HOSTNAME))
   10526           0 :                                         vty_out(vty, " from %s(%s)",
   10527             :                                                 path->peer->hostname,
   10528             :                                                 path->peer->conf_if);
   10529             :                                 else
   10530           0 :                                         vty_out(vty, " from %s",
   10531             :                                                 path->peer->conf_if);
   10532             :                         } else {
   10533           0 :                                 if (path->peer->hostname
   10534           0 :                                     && CHECK_FLAG(path->peer->bgp->flags,
   10535             :                                                   BGP_FLAG_SHOW_HOSTNAME))
   10536           0 :                                         vty_out(vty, " from %s(%s)",
   10537             :                                                 path->peer->hostname,
   10538             :                                                 path->peer->host);
   10539             :                                 else
   10540           0 :                                         vty_out(vty, " from %pSU",
   10541             :                                                 &path->peer->su);
   10542             :                         }
   10543             : 
   10544           0 :                         if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
   10545           0 :                                 vty_out(vty, " (%pI4)", &attr->originator_id);
   10546             :                         else
   10547           0 :                                 vty_out(vty, " (%pI4)", &path->peer->remote_id);
   10548             :                 }
   10549             :         }
   10550             : 
   10551             :         /*
   10552             :          * Note when vrfid of nexthop is different from that of prefix
   10553             :          */
   10554           0 :         if (path->extra && path->extra->bgp_orig) {
   10555           0 :                 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
   10556             : 
   10557           0 :                 if (json_paths) {
   10558           0 :                         const char *vn;
   10559             : 
   10560           0 :                         if (path->extra->bgp_orig->inst_type
   10561             :                             == BGP_INSTANCE_TYPE_DEFAULT)
   10562           0 :                                 vn = VRF_DEFAULT_NAME;
   10563             :                         else
   10564           0 :                                 vn = path->extra->bgp_orig->name;
   10565             : 
   10566           0 :                         json_object_string_add(json_path, "nhVrfName", vn);
   10567             : 
   10568           0 :                         if (nexthop_vrfid == VRF_UNKNOWN) {
   10569           0 :                                 json_object_int_add(json_path, "nhVrfId", -1);
   10570             :                         } else {
   10571           0 :                                 json_object_int_add(json_path, "nhVrfId",
   10572           0 :                                                     (int)nexthop_vrfid);
   10573             :                         }
   10574             :                 } else {
   10575           0 :                         if (nexthop_vrfid == VRF_UNKNOWN)
   10576           0 :                                 vty_out(vty, " vrf ?");
   10577             :                         else {
   10578           0 :                                 struct vrf *vrf;
   10579             : 
   10580           0 :                                 vrf = vrf_lookup_by_id(nexthop_vrfid);
   10581           0 :                                 vty_out(vty, " vrf %s(%u)",
   10582             :                                         VRF_LOGNAME(vrf), nexthop_vrfid);
   10583             :                         }
   10584             :                 }
   10585             :         }
   10586             : 
   10587           0 :         if (nexthop_self) {
   10588           0 :                 if (json_paths) {
   10589           0 :                         json_object_boolean_true_add(json_path,
   10590             :                                                      "announceNexthopSelf");
   10591             :                 } else {
   10592           0 :                         vty_out(vty, " announce-nh-self");
   10593             :                 }
   10594             :         }
   10595             : 
   10596           0 :         if (!json_paths)
   10597           0 :                 vty_out(vty, "\n");
   10598             : 
   10599             :         /* display the link-local nexthop */
   10600           0 :         if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
   10601           0 :                 if (json_paths) {
   10602           0 :                         json_nexthop_ll = json_object_new_object();
   10603           0 :                         json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
   10604             :                                                 &attr->mp_nexthop_local);
   10605             : 
   10606           0 :                         if (path->peer->hostname)
   10607           0 :                                 json_object_string_add(json_nexthop_ll,
   10608             :                                                        "hostname",
   10609             :                                                        path->peer->hostname);
   10610             : 
   10611           0 :                         json_object_string_add(json_nexthop_ll, "afi", "ipv6");
   10612           0 :                         json_object_string_add(json_nexthop_ll, "scope",
   10613             :                                                "link-local");
   10614             : 
   10615           0 :                         json_object_boolean_true_add(json_nexthop_ll,
   10616             :                                                      "accessible");
   10617             : 
   10618           0 :                         if (!attr->mp_nexthop_prefer_global)
   10619           0 :                                 json_object_boolean_true_add(json_nexthop_ll,
   10620             :                                                              "used");
   10621             :                         else
   10622           0 :                                 json_object_boolean_true_add(
   10623             :                                         json_nexthop_global, "used");
   10624             :                 } else {
   10625           0 :                         vty_out(vty, "    (%s) %s\n",
   10626           0 :                                 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
   10627             :                                           buf, INET6_ADDRSTRLEN),
   10628           0 :                                 attr->mp_nexthop_prefer_global
   10629             :                                         ? "(prefer-global)"
   10630             :                                         : "(used)");
   10631             :                 }
   10632             :         }
   10633             :         /* If we do not have a link-local nexthop then we must flag the
   10634             :            global as "used" */
   10635             :         else {
   10636           0 :                 if (json_paths)
   10637           0 :                         json_object_boolean_true_add(json_nexthop_global,
   10638             :                                                      "used");
   10639             :         }
   10640             : 
   10641           0 :         if (safi == SAFI_EVPN &&
   10642           0 :                         bgp_evpn_is_esi_valid(&attr->esi)) {
   10643           0 :                 route_vty_out_detail_es_info(vty, path, attr, json_path);
   10644             :         }
   10645             : 
   10646             :         /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
   10647             :          * Int/Ext/Local, Atomic, best */
   10648           0 :         if (json_paths)
   10649           0 :                 json_object_string_add(json_path, "origin",
   10650           0 :                                        bgp_origin_long_str[attr->origin]);
   10651             :         else
   10652           0 :                 vty_out(vty, "      Origin %s",
   10653           0 :                         bgp_origin_long_str[attr->origin]);
   10654             : 
   10655           0 :         if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
   10656           0 :                 if (json_paths)
   10657           0 :                         json_object_int_add(json_path, "metric", attr->med);
   10658             :                 else
   10659           0 :                         vty_out(vty, ", metric %u", attr->med);
   10660             :         }
   10661             : 
   10662           0 :         if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
   10663           0 :                 if (json_paths)
   10664           0 :                         json_object_int_add(json_path, "locPrf",
   10665           0 :                                             attr->local_pref);
   10666             :                 else
   10667           0 :                         vty_out(vty, ", localpref %u", attr->local_pref);
   10668             :         }
   10669             : 
   10670           0 :         if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) {
   10671           0 :                 if (json_paths)
   10672           0 :                         json_object_int_add(json_path, "aigpMetric",
   10673           0 :                                             bgp_attr_get_aigp_metric(attr));
   10674             :                 else
   10675           0 :                         vty_out(vty, ", aigp-metric %" PRIu64,
   10676             :                                 bgp_attr_get_aigp_metric(attr));
   10677             :         }
   10678             : 
   10679           0 :         if (attr->weight != 0) {
   10680           0 :                 if (json_paths)
   10681           0 :                         json_object_int_add(json_path, "weight", attr->weight);
   10682             :                 else
   10683           0 :                         vty_out(vty, ", weight %u", attr->weight);
   10684             :         }
   10685             : 
   10686           0 :         if (attr->tag != 0) {
   10687           0 :                 if (json_paths)
   10688           0 :                         json_object_int_add(json_path, "tag", attr->tag);
   10689             :                 else
   10690           0 :                         vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
   10691             :         }
   10692             : 
   10693           0 :         if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
   10694           0 :                 if (json_paths)
   10695           0 :                         json_object_boolean_false_add(json_path, "valid");
   10696             :                 else
   10697           0 :                         vty_out(vty, ", invalid");
   10698           0 :         } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
   10699           0 :                 if (json_paths)
   10700           0 :                         json_object_boolean_true_add(json_path, "valid");
   10701             :                 else
   10702           0 :                         vty_out(vty, ", valid");
   10703             :         }
   10704             : 
   10705           0 :         if (json_paths)
   10706           0 :                 json_object_int_add(json_path, "version", bn->version);
   10707             : 
   10708           0 :         if (path->peer != bgp->peer_self) {
   10709           0 :                 if (path->peer->as == path->peer->local_as) {
   10710           0 :                         if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
   10711           0 :                                 if (json_paths)
   10712           0 :                                         json_object_string_add(
   10713             :                                                 json_peer, "type",
   10714             :                                                 "confed-internal");
   10715             :                                 else
   10716           0 :                                         vty_out(vty, ", confed-internal");
   10717             :                         } else {
   10718           0 :                                 if (json_paths)
   10719           0 :                                         json_object_string_add(
   10720             :                                                 json_peer, "type", "internal");
   10721             :                                 else
   10722           0 :                                         vty_out(vty, ", internal");
   10723             :                         }
   10724             :                 } else {
   10725           0 :                         if (bgp_confederation_peers_check(bgp,
   10726             :                                                           path->peer->as)) {
   10727           0 :                                 if (json_paths)
   10728           0 :                                         json_object_string_add(
   10729             :                                                 json_peer, "type",
   10730             :                                                 "confed-external");
   10731             :                                 else
   10732           0 :                                         vty_out(vty, ", confed-external");
   10733             :                         } else {
   10734           0 :                                 if (json_paths)
   10735           0 :                                         json_object_string_add(
   10736             :                                                 json_peer, "type", "external");
   10737             :                                 else
   10738           0 :                                         vty_out(vty, ", external");
   10739             :                         }
   10740             :                 }
   10741           0 :         } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
   10742           0 :                 if (json_paths) {
   10743           0 :                         json_object_boolean_true_add(json_path, "aggregated");
   10744           0 :                         json_object_boolean_true_add(json_path, "local");
   10745             :                 } else {
   10746           0 :                         vty_out(vty, ", aggregated, local");
   10747             :                 }
   10748           0 :         } else if (path->type != ZEBRA_ROUTE_BGP) {
   10749           0 :                 if (json_paths)
   10750           0 :                         json_object_boolean_true_add(json_path, "sourced");
   10751             :                 else
   10752           0 :                         vty_out(vty, ", sourced");
   10753             :         } else {
   10754           0 :                 if (json_paths) {
   10755           0 :                         json_object_boolean_true_add(json_path, "sourced");
   10756           0 :                         json_object_boolean_true_add(json_path, "local");
   10757             :                 } else {
   10758           0 :                         vty_out(vty, ", sourced, local");
   10759             :                 }
   10760             :         }
   10761             : 
   10762           0 :         if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
   10763           0 :                 if (json_paths)
   10764           0 :                         json_object_boolean_true_add(json_path,
   10765             :                                                      "atomicAggregate");
   10766             :                 else
   10767           0 :                         vty_out(vty, ", atomic-aggregate");
   10768             :         }
   10769             : 
   10770           0 :         if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
   10771           0 :                 if (json_paths)
   10772           0 :                         json_object_int_add(json_path, "otc", attr->otc);
   10773             :                 else
   10774           0 :                         vty_out(vty, ", otc %u", attr->otc);
   10775             :         }
   10776             : 
   10777           0 :         if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
   10778           0 :             || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
   10779           0 :                 && bgp_path_info_mpath_count(path))) {
   10780           0 :                 if (json_paths)
   10781           0 :                         json_object_boolean_true_add(json_path, "multipath");
   10782             :                 else
   10783           0 :                         vty_out(vty, ", multipath");
   10784             :         }
   10785             : 
   10786             :         // Mark the bestpath(s)
   10787           0 :         if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
   10788           0 :                 first_as = aspath_get_first_as(attr->aspath);
   10789             : 
   10790           0 :                 if (json_paths) {
   10791           0 :                         if (!json_bestpath)
   10792           0 :                                 json_bestpath = json_object_new_object();
   10793           0 :                         json_object_int_add(json_bestpath, "bestpathFromAs",
   10794             :                                             first_as);
   10795             :                 } else {
   10796           0 :                         if (first_as)
   10797           0 :                                 vty_out(vty, ", bestpath-from-AS %u", first_as);
   10798             :                         else
   10799           0 :                                 vty_out(vty, ", bestpath-from-AS Local");
   10800             :                 }
   10801             :         }
   10802             : 
   10803           0 :         if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
   10804           0 :                 if (json_paths) {
   10805           0 :                         if (!json_bestpath)
   10806           0 :                                 json_bestpath = json_object_new_object();
   10807           0 :                         json_object_boolean_true_add(json_bestpath, "overall");
   10808           0 :                         json_object_string_add(
   10809             :                                 json_bestpath, "selectionReason",
   10810             :                                 bgp_path_selection_reason2str(bn->reason));
   10811             :                 } else {
   10812           0 :                         vty_out(vty, ", best");
   10813           0 :                         vty_out(vty, " (%s)",
   10814             :                                 bgp_path_selection_reason2str(bn->reason));
   10815             :                 }
   10816             :         }
   10817             : 
   10818           0 :         if (rpki_curr_state != RPKI_NOT_BEING_USED) {
   10819           0 :                 if (json_paths)
   10820           0 :                         json_object_string_add(
   10821             :                                 json_path, "rpkiValidationState",
   10822             :                                 bgp_rpki_validation2str(rpki_curr_state));
   10823             :                 else
   10824           0 :                         vty_out(vty, ", rpki validation-state: %s",
   10825             :                                 bgp_rpki_validation2str(rpki_curr_state));
   10826             :         }
   10827             : 
   10828           0 :         if (json_bestpath)
   10829           0 :                 json_object_object_add(json_path, "bestpath", json_bestpath);
   10830             : 
   10831           0 :         if (!json_paths)
   10832           0 :                 vty_out(vty, "\n");
   10833             : 
   10834             :         /* Line 4 display Community */
   10835           0 :         if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
   10836           0 :                 if (json_paths) {
   10837           0 :                         if (!bgp_attr_get_community(attr)->json)
   10838           0 :                                 community_str(bgp_attr_get_community(attr),
   10839             :                                               true, true);
   10840           0 :                         json_object_lock(bgp_attr_get_community(attr)->json);
   10841           0 :                         json_object_object_add(
   10842             :                                 json_path, "community",
   10843           0 :                                 bgp_attr_get_community(attr)->json);
   10844             :                 } else {
   10845           0 :                         vty_out(vty, "      Community: %s\n",
   10846           0 :                                 bgp_attr_get_community(attr)->str);
   10847             :                 }
   10848             :         }
   10849             : 
   10850             :         /* Line 5 display Extended-community */
   10851           0 :         if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
   10852           0 :                 if (json_paths) {
   10853           0 :                         json_ext_community = json_object_new_object();
   10854           0 :                         json_object_string_add(
   10855             :                                 json_ext_community, "string",
   10856           0 :                                 bgp_attr_get_ecommunity(attr)->str);
   10857           0 :                         json_object_object_add(json_path, "extendedCommunity",
   10858             :                                                json_ext_community);
   10859             :                 } else {
   10860           0 :                         vty_out(vty, "      Extended Community: %s\n",
   10861           0 :                                 bgp_attr_get_ecommunity(attr)->str);
   10862             :                 }
   10863             :         }
   10864             : 
   10865             :         /* Line 6 display Large community */
   10866           0 :         if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
   10867           0 :                 if (json_paths) {
   10868           0 :                         if (!bgp_attr_get_lcommunity(attr)->json)
   10869           0 :                                 lcommunity_str(bgp_attr_get_lcommunity(attr),
   10870             :                                                true, true);
   10871           0 :                         json_object_lock(bgp_attr_get_lcommunity(attr)->json);
   10872           0 :                         json_object_object_add(
   10873             :                                 json_path, "largeCommunity",
   10874           0 :                                 bgp_attr_get_lcommunity(attr)->json);
   10875             :                 } else {
   10876           0 :                         vty_out(vty, "      Large Community: %s\n",
   10877           0 :                                 bgp_attr_get_lcommunity(attr)->str);
   10878             :                 }
   10879             :         }
   10880             : 
   10881             :         /* Line 7 display Originator, Cluster-id */
   10882           0 :         if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
   10883           0 :             || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
   10884           0 :                 char buf[BUFSIZ] = {0};
   10885             : 
   10886           0 :                 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
   10887           0 :                         if (json_paths)
   10888           0 :                                 json_object_string_addf(json_path,
   10889             :                                                         "originatorId", "%pI4",
   10890             :                                                         &attr->originator_id);
   10891             :                         else
   10892           0 :                                 vty_out(vty, "      Originator: %pI4",
   10893             :                                         &attr->originator_id);
   10894             :                 }
   10895             : 
   10896           0 :                 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
   10897           0 :                         struct cluster_list *cluster =
   10898           0 :                                 bgp_attr_get_cluster(attr);
   10899           0 :                         int i;
   10900             : 
   10901           0 :                         if (json_paths) {
   10902           0 :                                 json_cluster_list = json_object_new_object();
   10903           0 :                                 json_cluster_list_list =
   10904           0 :                                         json_object_new_array();
   10905             : 
   10906           0 :                                 for (i = 0; i < cluster->length / 4; i++) {
   10907           0 :                                         json_string = json_object_new_string(
   10908             :                                                 inet_ntop(AF_INET,
   10909           0 :                                                           &cluster->list[i],
   10910             :                                                           buf, sizeof(buf)));
   10911           0 :                                         json_object_array_add(
   10912             :                                                 json_cluster_list_list,
   10913             :                                                 json_string);
   10914             :                                 }
   10915             : 
   10916             :                                 /*
   10917             :                                  * struct cluster_list does not have
   10918             :                                  * "str" variable like aspath and community
   10919             :                                  * do.  Add this someday if someone asks
   10920             :                                  * for it.
   10921             :                                  * json_object_string_add(json_cluster_list,
   10922             :                                  * "string", cluster->str);
   10923             :                                  */
   10924           0 :                                 json_object_object_add(json_cluster_list,
   10925             :                                                        "list",
   10926             :                                                        json_cluster_list_list);
   10927           0 :                                 json_object_object_add(json_path, "clusterList",
   10928             :                                                        json_cluster_list);
   10929             :                         } else {
   10930           0 :                                 vty_out(vty, ", Cluster list: ");
   10931             : 
   10932           0 :                                 for (i = 0; i < cluster->length / 4; i++) {
   10933           0 :                                         vty_out(vty, "%pI4 ",
   10934           0 :                                                 &cluster->list[i]);
   10935             :                                 }
   10936             :                         }
   10937             :                 }
   10938             : 
   10939           0 :                 if (!json_paths)
   10940           0 :                         vty_out(vty, "\n");
   10941             :         }
   10942             : 
   10943           0 :         if (path->extra && path->extra->damp_info)
   10944           0 :                 bgp_damp_info_vty(vty, path, afi, safi, json_path);
   10945             : 
   10946             :         /* Remote Label */
   10947           0 :         if (path->extra && bgp_is_valid_label(&path->extra->label[0])
   10948           0 :             && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
   10949           0 :                 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
   10950             :                                 &bos);
   10951             : 
   10952           0 :                 if (json_paths)
   10953           0 :                         json_object_int_add(json_path, "remoteLabel", label);
   10954             :                 else
   10955           0 :                         vty_out(vty, "      Remote label: %d\n", label);
   10956             :         }
   10957             : 
   10958             :         /* Remote SID */
   10959           0 :         if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
   10960           0 :                 if (json_paths)
   10961           0 :                         json_object_string_addf(json_path, "remoteSid", "%pI6",
   10962             :                                                 &path->extra->sid[0].sid);
   10963             :                 else
   10964           0 :                         vty_out(vty, "      Remote SID: %pI6\n",
   10965             :                                 &path->extra->sid[0].sid);
   10966             :         }
   10967             : 
   10968             :         /* Label Index */
   10969           0 :         if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
   10970           0 :                 if (json_paths)
   10971           0 :                         json_object_int_add(json_path, "labelIndex",
   10972             :                                             attr->label_index);
   10973             :                 else
   10974           0 :                         vty_out(vty, "      Label Index: %d\n",
   10975             :                                 attr->label_index);
   10976             :         }
   10977             : 
   10978             :         /* Line 8 display Addpath IDs */
   10979           0 :         if (path->addpath_rx_id
   10980           0 :             || bgp_addpath_info_has_ids(&path->tx_addpath)) {
   10981           0 :                 if (json_paths) {
   10982           0 :                         json_object_int_add(json_path, "addpathRxId",
   10983           0 :                                             path->addpath_rx_id);
   10984             : 
   10985             :                         /* Keep backwards compatibility with the old API
   10986             :                          * by putting TX All's ID in the old field
   10987             :                          */
   10988           0 :                         json_object_int_add(
   10989             :                                 json_path, "addpathTxId",
   10990             :                                 path->tx_addpath
   10991           0 :                                         .addpath_tx_id[BGP_ADDPATH_ALL]);
   10992             : 
   10993             :                         /* ... but create a specific field for each
   10994             :                          * strategy
   10995             :                          */
   10996           0 :                         for (i = 0; i < BGP_ADDPATH_MAX; i++) {
   10997           0 :                                 json_object_int_add(
   10998             :                                         json_path,
   10999           0 :                                         bgp_addpath_names(i)->id_json_name,
   11000           0 :                                         path->tx_addpath.addpath_tx_id[i]);
   11001             :                         }
   11002             :                 } else {
   11003           0 :                         vty_out(vty, "      AddPath ID: RX %u, ",
   11004             :                                 path->addpath_rx_id);
   11005             : 
   11006           0 :                         route_vty_out_tx_ids(vty, &path->tx_addpath);
   11007             :                 }
   11008             :         }
   11009             : 
   11010             :         /* If we used addpath to TX a non-bestpath we need to display
   11011             :          * "Advertised to" on a path-by-path basis
   11012             :          */
   11013           0 :         if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
   11014           0 :                 first = 1;
   11015             : 
   11016           0 :                 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
   11017           0 :                         addpath_capable =
   11018           0 :                                 bgp_addpath_encode_tx(peer, afi, safi);
   11019           0 :                         has_adj = bgp_adj_out_lookup(
   11020             :                                 peer, path->net,
   11021             :                                 bgp_addpath_id_for_peer(peer, afi, safi,
   11022             :                                                         &path->tx_addpath));
   11023             : 
   11024           0 :                         if ((addpath_capable && has_adj)
   11025           0 :                             || (!addpath_capable && has_adj
   11026           0 :                                 && CHECK_FLAG(path->flags,
   11027             :                                               BGP_PATH_SELECTED))) {
   11028           0 :                                 if (json_path && !json_adv_to)
   11029           0 :                                         json_adv_to = json_object_new_object();
   11030             : 
   11031           0 :                                 route_vty_out_advertised_to(
   11032             :                                         vty, peer, &first,
   11033             :                                         "      Advertised to:", json_adv_to);
   11034             :                         }
   11035             :                 }
   11036             : 
   11037           0 :                 if (json_path) {
   11038           0 :                         if (json_adv_to) {
   11039           0 :                                 json_object_object_add(
   11040             :                                         json_path, "advertisedTo", json_adv_to);
   11041             :                         }
   11042             :                 } else {
   11043           0 :                         if (!first) {
   11044           0 :                                 vty_out(vty, "\n");
   11045             :                         }
   11046             :                 }
   11047             :         }
   11048             : 
   11049             :         /* Line 9 display Uptime */
   11050           0 :         tbuf = time(NULL) - (monotime(NULL) - path->uptime);
   11051           0 :         if (json_paths) {
   11052           0 :                 json_last_update = json_object_new_object();
   11053           0 :                 json_object_int_add(json_last_update, "epoch", tbuf);
   11054           0 :                 json_object_string_add(json_last_update, "string",
   11055           0 :                                        ctime(&tbuf));
   11056           0 :                 json_object_object_add(json_path, "lastUpdate",
   11057             :                                        json_last_update);
   11058             :         } else
   11059           0 :                 vty_out(vty, "      Last update: %s", ctime(&tbuf));
   11060             : 
   11061             :         /* Line 10 display PMSI tunnel attribute, if present */
   11062           0 :         if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
   11063           0 :                 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
   11064           0 :                                              bgp_attr_get_pmsi_tnl_type(attr),
   11065             :                                              PMSI_TNLTYPE_STR_DEFAULT);
   11066             : 
   11067           0 :                 if (json_paths) {
   11068           0 :                         json_pmsi = json_object_new_object();
   11069           0 :                         json_object_string_add(json_pmsi, "tunnelType", str);
   11070           0 :                         json_object_int_add(json_pmsi, "label",
   11071           0 :                                             label2vni(&attr->label));
   11072           0 :                         json_object_object_add(json_path, "pmsi", json_pmsi);
   11073             :                 } else
   11074           0 :                         vty_out(vty, "      PMSI Tunnel Type: %s, label: %d\n",
   11075             :                                 str, label2vni(&attr->label));
   11076             :         }
   11077             : 
   11078           0 :         if (path->peer->t_gr_restart &&
   11079           0 :             CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
   11080           0 :                 unsigned long gr_remaining =
   11081           0 :                         thread_timer_remain_second(path->peer->t_gr_restart);
   11082             : 
   11083           0 :                 if (json_paths) {
   11084           0 :                         json_object_int_add(json_path,
   11085             :                                             "gracefulRestartSecondsRemaining",
   11086             :                                             gr_remaining);
   11087             :                 } else
   11088           0 :                         vty_out(vty,
   11089             :                                 "      Time until Graceful Restart stale route deleted: %lu\n",
   11090             :                                 gr_remaining);
   11091             :         }
   11092             : 
   11093           0 :         if (path->peer->t_llgr_stale[afi][safi] &&
   11094           0 :             bgp_attr_get_community(attr) &&
   11095           0 :             community_include(bgp_attr_get_community(attr),
   11096             :                               COMMUNITY_LLGR_STALE)) {
   11097           0 :                 unsigned long llgr_remaining = thread_timer_remain_second(
   11098           0 :                         path->peer->t_llgr_stale[afi][safi]);
   11099             : 
   11100           0 :                 if (json_paths) {
   11101           0 :                         json_object_int_add(json_path, "llgrSecondsRemaining",
   11102             :                                             llgr_remaining);
   11103             :                 } else
   11104           0 :                         vty_out(vty,
   11105             :                                 "      Time until Long-lived stale route deleted: %lu\n",
   11106             :                                 llgr_remaining);
   11107             :         }
   11108             : 
   11109             :         /* Output some debug about internal state of the dest flags */
   11110           0 :         if (json_paths) {
   11111           0 :                 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
   11112           0 :                         json_object_boolean_true_add(json_path, "processScheduled");
   11113           0 :                 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
   11114           0 :                         json_object_boolean_true_add(json_path, "userCleared");
   11115           0 :                 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
   11116           0 :                         json_object_boolean_true_add(json_path, "labelChanged");
   11117           0 :                 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
   11118           0 :                         json_object_boolean_true_add(json_path, "registeredForLabel");
   11119           0 :                 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
   11120           0 :                         json_object_boolean_true_add(json_path, "selectDefered");
   11121           0 :                 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
   11122           0 :                         json_object_boolean_true_add(json_path, "fibInstalled");
   11123           0 :                 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
   11124           0 :                         json_object_boolean_true_add(json_path, "fibPending");
   11125             : 
   11126           0 :                 if (json_nexthop_global || json_nexthop_ll) {
   11127           0 :                         json_nexthops = json_object_new_array();
   11128             : 
   11129           0 :                         if (json_nexthop_global)
   11130           0 :                                 json_object_array_add(json_nexthops,
   11131             :                                                       json_nexthop_global);
   11132             : 
   11133           0 :                         if (json_nexthop_ll)
   11134           0 :                                 json_object_array_add(json_nexthops,
   11135             :                                                       json_nexthop_ll);
   11136             : 
   11137           0 :                         json_object_object_add(json_path, "nexthops",
   11138             :                                                json_nexthops);
   11139             :                 }
   11140             : 
   11141           0 :                 json_object_object_add(json_path, "peer", json_peer);
   11142           0 :                 json_object_array_add(json_paths, json_path);
   11143             :         }
   11144           0 : }
   11145             : 
   11146             : #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
   11147             : #define BGP_SHOW_DAMP_HEADER "   Network          From             Reuse    Path\n"
   11148             : #define BGP_SHOW_FLAP_HEADER "   Network          From            Flaps Duration Reuse    Path\n"
   11149             : 
   11150             : static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
   11151             :                            afi_t afi, safi_t safi, enum bgp_show_type type,
   11152             :                            bool use_json);
   11153             : static int bgp_show_community(struct vty *vty, struct bgp *bgp,
   11154             :                               const char *comstr, int exact, afi_t afi,
   11155             :                               safi_t safi, uint16_t show_flags);
   11156             : 
   11157          48 : static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
   11158             :                           struct bgp_table *table, enum bgp_show_type type,
   11159             :                           void *output_arg, const char *rd, int is_last,
   11160             :                           unsigned long *output_cum, unsigned long *total_cum,
   11161             :                           unsigned long *json_header_depth, uint16_t show_flags,
   11162             :                           enum rpki_states rpki_target_state)
   11163             : {
   11164          48 :         struct bgp_path_info *pi;
   11165          48 :         struct bgp_dest *dest;
   11166          48 :         bool header = true;
   11167          48 :         bool json_detail_header = false;
   11168          48 :         int display;
   11169          48 :         unsigned long output_count = 0;
   11170          48 :         unsigned long total_count = 0;
   11171          48 :         struct prefix *p;
   11172          48 :         json_object *json_paths = NULL;
   11173          48 :         int first = 1;
   11174          48 :         bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
   11175          48 :         bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
   11176          48 :         bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
   11177          48 :         bool detail_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
   11178          48 :         bool detail_routes = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
   11179             : 
   11180          48 :         if (output_cum && *output_cum != 0)
   11181          48 :                 header = false;
   11182             : 
   11183          48 :         if (use_json && !*json_header_depth) {
   11184          48 :                 if (all)
   11185           0 :                         *json_header_depth = 1;
   11186             :                 else {
   11187          48 :                         vty_out(vty, "{\n");
   11188          48 :                         *json_header_depth = 2;
   11189             :                 }
   11190             : 
   11191          48 :                 vty_out(vty,
   11192             :                         " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
   11193             :                         ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
   11194             :                         " \"localAS\": %u,\n \"routes\": { ",
   11195          48 :                         bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
   11196          48 :                         bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
   11197          48 :                                 ? VRF_DEFAULT_NAME
   11198             :                                 : bgp->name,
   11199             :                         table->version, &bgp->router_id,
   11200             :                         bgp->default_local_pref, bgp->as);
   11201          48 :                 if (rd) {
   11202           0 :                         vty_out(vty, " \"routeDistinguishers\" : {");
   11203           0 :                         ++*json_header_depth;
   11204             :                 }
   11205             :         }
   11206             : 
   11207          48 :         if (use_json && rd) {
   11208           0 :                 vty_out(vty, " \"%s\" : { ", rd);
   11209             :         }
   11210             : 
   11211             :         /* Check for 'json detail', where we need header output once per dest */
   11212          48 :         if (use_json && detail_json && type != bgp_show_type_dampend_paths &&
   11213             :             type != bgp_show_type_damp_neighbor &&
   11214           0 :             type != bgp_show_type_flap_statistics &&
   11215             :             type != bgp_show_type_flap_neighbor)
   11216          48 :                 json_detail_header = true;
   11217             : 
   11218             :         /* Start processing of routes. */
   11219         103 :         for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
   11220           7 :                 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
   11221           7 :                 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
   11222           7 :                 bool json_detail = json_detail_header;
   11223             : 
   11224           7 :                 pi = bgp_dest_get_bgp_path_info(dest);
   11225           7 :                 if (pi == NULL)
   11226           3 :                         continue;
   11227             : 
   11228           4 :                 display = 0;
   11229           4 :                 if (use_json)
   11230           4 :                         json_paths = json_object_new_array();
   11231             :                 else
   11232           4 :                         json_paths = NULL;
   11233             : 
   11234           8 :                 for (; pi; pi = pi->next) {
   11235           4 :                         struct community *picomm = NULL;
   11236             : 
   11237           4 :                         picomm = bgp_attr_get_community(pi->attr);
   11238             : 
   11239           4 :                         total_count++;
   11240             : 
   11241           4 :                         if (type == bgp_show_type_prefix_version) {
   11242           0 :                                 uint32_t version =
   11243           0 :                                         strtoul(output_arg, NULL, 10);
   11244           0 :                                 if (dest->version < version)
   11245           0 :                                         continue;
   11246             :                         }
   11247             : 
   11248           4 :                         if (type == bgp_show_type_community_alias) {
   11249           0 :                                 char *alias = output_arg;
   11250           0 :                                 char **communities;
   11251           0 :                                 int num;
   11252           0 :                                 bool found = false;
   11253             : 
   11254           0 :                                 if (picomm) {
   11255           0 :                                         frrstr_split(picomm->str, " ",
   11256             :                                                      &communities, &num);
   11257           0 :                                         for (int i = 0; i < num; i++) {
   11258           0 :                                                 const char *com2alias =
   11259           0 :                                                         bgp_community2alias(
   11260           0 :                                                                 communities[i]);
   11261           0 :                                                 if (!found
   11262           0 :                                                     && strcmp(alias, com2alias)
   11263             :                                                                == 0)
   11264           0 :                                                         found = true;
   11265           0 :                                                 XFREE(MTYPE_TMP,
   11266             :                                                       communities[i]);
   11267             :                                         }
   11268           0 :                                         XFREE(MTYPE_TMP, communities);
   11269             :                                 }
   11270             : 
   11271           0 :                                 if (!found &&
   11272           0 :                                     bgp_attr_get_lcommunity(pi->attr)) {
   11273           0 :                                         frrstr_split(bgp_attr_get_lcommunity(
   11274           0 :                                                              pi->attr)
   11275           0 :                                                              ->str,
   11276             :                                                      " ", &communities, &num);
   11277           0 :                                         for (int i = 0; i < num; i++) {
   11278           0 :                                                 const char *com2alias =
   11279           0 :                                                         bgp_community2alias(
   11280           0 :                                                                 communities[i]);
   11281           0 :                                                 if (!found
   11282           0 :                                                     && strcmp(alias, com2alias)
   11283             :                                                                == 0)
   11284           0 :                                                         found = true;
   11285           0 :                                                 XFREE(MTYPE_TMP,
   11286             :                                                       communities[i]);
   11287             :                                         }
   11288           0 :                                         XFREE(MTYPE_TMP, communities);
   11289             :                                 }
   11290             : 
   11291           0 :                                 if (!found)
   11292           0 :                                         continue;
   11293             :                         }
   11294             : 
   11295           4 :                         if (type == bgp_show_type_rpki) {
   11296           0 :                                 if (dest_p->family == AF_INET
   11297           0 :                                     || dest_p->family == AF_INET6)
   11298           0 :                                         rpki_curr_state = hook_call(
   11299             :                                                 bgp_rpki_prefix_status,
   11300             :                                                 pi->peer, pi->attr, dest_p);
   11301           0 :                                 if (rpki_target_state != RPKI_NOT_BEING_USED
   11302           0 :                                     && rpki_curr_state != rpki_target_state)
   11303           0 :                                         continue;
   11304             :                         }
   11305             : 
   11306           4 :                         if (type == bgp_show_type_flap_statistics
   11307             :                             || type == bgp_show_type_flap_neighbor
   11308             :                             || type == bgp_show_type_dampend_paths
   11309           4 :                             || type == bgp_show_type_damp_neighbor) {
   11310           0 :                                 if (!(pi->extra && pi->extra->damp_info))
   11311           0 :                                         continue;
   11312             :                         }
   11313           4 :                         if (type == bgp_show_type_regexp) {
   11314           0 :                                 regex_t *regex = output_arg;
   11315             : 
   11316           0 :                                 if (bgp_regexec(regex, pi->attr->aspath)
   11317             :                                     == REG_NOMATCH)
   11318           0 :                                         continue;
   11319             :                         }
   11320           4 :                         if (type == bgp_show_type_prefix_list) {
   11321           0 :                                 struct prefix_list *plist = output_arg;
   11322             : 
   11323           0 :                                 if (prefix_list_apply(plist, dest_p)
   11324             :                                     != PREFIX_PERMIT)
   11325           0 :                                         continue;
   11326             :                         }
   11327           4 :                         if (type == bgp_show_type_access_list) {
   11328           0 :                                 struct access_list *alist = output_arg;
   11329             : 
   11330           0 :                                 if (access_list_apply(alist, dest_p) !=
   11331             :                                     FILTER_PERMIT)
   11332           0 :                                         continue;
   11333             :                         }
   11334           4 :                         if (type == bgp_show_type_filter_list) {
   11335           0 :                                 struct as_list *as_list = output_arg;
   11336             : 
   11337           0 :                                 if (as_list_apply(as_list, pi->attr->aspath)
   11338             :                                     != AS_FILTER_PERMIT)
   11339           0 :                                         continue;
   11340             :                         }
   11341           4 :                         if (type == bgp_show_type_route_map) {
   11342           0 :                                 struct route_map *rmap = output_arg;
   11343           0 :                                 struct bgp_path_info path;
   11344           0 :                                 struct bgp_path_info_extra extra;
   11345           0 :                                 struct attr dummy_attr = {};
   11346           0 :                                 route_map_result_t ret;
   11347             : 
   11348           0 :                                 dummy_attr = *pi->attr;
   11349             : 
   11350           0 :                                 prep_for_rmap_apply(&path, &extra, dest, pi,
   11351             :                                                     pi->peer, &dummy_attr);
   11352             : 
   11353           0 :                                 ret = route_map_apply(rmap, dest_p, &path);
   11354           0 :                                 bgp_attr_flush(&dummy_attr);
   11355           0 :                                 if (ret == RMAP_DENYMATCH)
   11356           0 :                                         continue;
   11357             :                         }
   11358           4 :                         if (type == bgp_show_type_neighbor
   11359           4 :                             || type == bgp_show_type_flap_neighbor
   11360           4 :                             || type == bgp_show_type_damp_neighbor) {
   11361           0 :                                 union sockunion *su = output_arg;
   11362             : 
   11363           0 :                                 if (pi->peer == NULL
   11364           0 :                                     || pi->peer->su_remote == NULL
   11365           0 :                                     || !sockunion_same(pi->peer->su_remote, su))
   11366           0 :                                         continue;
   11367             :                         }
   11368           4 :                         if (type == bgp_show_type_cidr_only) {
   11369           0 :                                 uint32_t destination;
   11370             : 
   11371           0 :                                 destination = ntohl(dest_p->u.prefix4.s_addr);
   11372           0 :                                 if (IN_CLASSC(destination)
   11373           0 :                                     && dest_p->prefixlen == 24)
   11374           0 :                                         continue;
   11375           0 :                                 if (IN_CLASSB(destination)
   11376           0 :                                     && dest_p->prefixlen == 16)
   11377           0 :                                         continue;
   11378           0 :                                 if (IN_CLASSA(destination)
   11379           0 :                                     && dest_p->prefixlen == 8)
   11380           0 :                                         continue;
   11381             :                         }
   11382           4 :                         if (type == bgp_show_type_prefix_longer) {
   11383           0 :                                 p = output_arg;
   11384           0 :                                 if (!prefix_match(p, dest_p))
   11385           0 :                                         continue;
   11386             :                         }
   11387           4 :                         if (type == bgp_show_type_community_all) {
   11388           0 :                                 if (!picomm)
   11389           0 :                                         continue;
   11390             :                         }
   11391           4 :                         if (type == bgp_show_type_community) {
   11392           0 :                                 struct community *com = output_arg;
   11393             : 
   11394           0 :                                 if (!picomm || !community_match(picomm, com))
   11395           0 :                                         continue;
   11396             :                         }
   11397           4 :                         if (type == bgp_show_type_community_exact) {
   11398           0 :                                 struct community *com = output_arg;
   11399             : 
   11400           0 :                                 if (!picomm || !community_cmp(picomm, com))
   11401           0 :                                         continue;
   11402             :                         }
   11403           4 :                         if (type == bgp_show_type_community_list) {
   11404           0 :                                 struct community_list *list = output_arg;
   11405             : 
   11406           0 :                                 if (!community_list_match(picomm, list))
   11407           0 :                                         continue;
   11408             :                         }
   11409           4 :                         if (type == bgp_show_type_community_list_exact) {
   11410           0 :                                 struct community_list *list = output_arg;
   11411             : 
   11412           0 :                                 if (!community_list_exact_match(picomm, list))
   11413           0 :                                         continue;
   11414             :                         }
   11415           4 :                         if (type == bgp_show_type_lcommunity) {
   11416           0 :                                 struct lcommunity *lcom = output_arg;
   11417             : 
   11418           0 :                                 if (!bgp_attr_get_lcommunity(pi->attr) ||
   11419           0 :                                     !lcommunity_match(
   11420           0 :                                             bgp_attr_get_lcommunity(pi->attr),
   11421             :                                             lcom))
   11422           0 :                                         continue;
   11423             :                         }
   11424             : 
   11425           4 :                         if (type == bgp_show_type_lcommunity_exact) {
   11426           0 :                                 struct lcommunity *lcom = output_arg;
   11427             : 
   11428           0 :                                 if (!bgp_attr_get_lcommunity(pi->attr) ||
   11429           0 :                                     !lcommunity_cmp(
   11430           0 :                                             bgp_attr_get_lcommunity(pi->attr),
   11431             :                                             lcom))
   11432           0 :                                         continue;
   11433             :                         }
   11434           4 :                         if (type == bgp_show_type_lcommunity_list) {
   11435           0 :                                 struct community_list *list = output_arg;
   11436             : 
   11437           0 :                                 if (!lcommunity_list_match(
   11438           0 :                                             bgp_attr_get_lcommunity(pi->attr),
   11439             :                                             list))
   11440           0 :                                         continue;
   11441             :                         }
   11442           4 :                         if (type
   11443             :                             == bgp_show_type_lcommunity_list_exact) {
   11444           0 :                                 struct community_list *list = output_arg;
   11445             : 
   11446           0 :                                 if (!lcommunity_list_exact_match(
   11447           0 :                                             bgp_attr_get_lcommunity(pi->attr),
   11448             :                                             list))
   11449           0 :                                         continue;
   11450             :                         }
   11451           4 :                         if (type == bgp_show_type_lcommunity_all) {
   11452           0 :                                 if (!bgp_attr_get_lcommunity(pi->attr))
   11453           0 :                                         continue;
   11454             :                         }
   11455           4 :                         if (type == bgp_show_type_dampend_paths
   11456           4 :                             || type == bgp_show_type_damp_neighbor) {
   11457           0 :                                 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
   11458           0 :                                     || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
   11459           0 :                                         continue;
   11460             :                         }
   11461             : 
   11462           4 :                         if (!use_json && header) {
   11463           0 :                                 vty_out(vty,
   11464             :                                         "BGP table version is %" PRIu64
   11465             :                                         ", local router ID is %pI4, vrf id ",
   11466             :                                         table->version, &bgp->router_id);
   11467           0 :                                 if (bgp->vrf_id == VRF_UNKNOWN)
   11468           0 :                                         vty_out(vty, "%s", VRFID_NONE_STR);
   11469             :                                 else
   11470           0 :                                         vty_out(vty, "%u", bgp->vrf_id);
   11471           0 :                                 vty_out(vty, "\n");
   11472           0 :                                 vty_out(vty, "Default local pref %u, ",
   11473             :                                         bgp->default_local_pref);
   11474           0 :                                 vty_out(vty, "local AS %u\n", bgp->as);
   11475           0 :                                 if (!detail_routes) {
   11476           0 :                                         vty_out(vty, BGP_SHOW_SCODE_HEADER);
   11477           0 :                                         vty_out(vty, BGP_SHOW_NCODE_HEADER);
   11478           0 :                                         vty_out(vty, BGP_SHOW_OCODE_HEADER);
   11479           0 :                                         vty_out(vty, BGP_SHOW_RPKI_HEADER);
   11480             :                                 }
   11481           0 :                                 if (type == bgp_show_type_dampend_paths
   11482             :                                     || type == bgp_show_type_damp_neighbor)
   11483           0 :                                         vty_out(vty, BGP_SHOW_DAMP_HEADER);
   11484           0 :                                 else if (type == bgp_show_type_flap_statistics
   11485             :                                          || type == bgp_show_type_flap_neighbor)
   11486           0 :                                         vty_out(vty, BGP_SHOW_FLAP_HEADER);
   11487           0 :                                 else if (!detail_routes)
   11488           0 :                                         vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
   11489             :                                                            : BGP_SHOW_HEADER));
   11490             :                                 header = false;
   11491             : 
   11492           4 :                         } else if (json_detail && json_paths != NULL) {
   11493           0 :                                 const struct prefix_rd *prd;
   11494           0 :                                 json_object *jtemp;
   11495             : 
   11496             :                                 /* Use common detail header, for most types;
   11497             :                                  * need a json 'object'.
   11498             :                                  */
   11499             : 
   11500           0 :                                 jtemp = json_object_new_object();
   11501           0 :                                 prd = bgp_rd_from_dest(dest, safi);
   11502             : 
   11503           0 :                                 route_vty_out_detail_header(
   11504             :                                         vty, bgp, dest,
   11505             :                                         bgp_dest_get_prefix(dest), prd,
   11506             :                                         table->afi, safi, jtemp);
   11507             : 
   11508           0 :                                 json_object_array_add(json_paths, jtemp);
   11509             : 
   11510           0 :                                 json_detail = false;
   11511             :                         }
   11512             : 
   11513           4 :                         if (rd != NULL && !display && !output_count) {
   11514           0 :                                 if (!use_json)
   11515           0 :                                         vty_out(vty,
   11516             :                                                 "Route Distinguisher: %s\n",
   11517             :                                                 rd);
   11518             :                         }
   11519           4 :                         if (type == bgp_show_type_dampend_paths
   11520             :                             || type == bgp_show_type_damp_neighbor)
   11521           0 :                                 damp_route_vty_out(vty, dest_p, pi, display,
   11522             :                                                    AFI_IP, safi, use_json,
   11523             :                                                    json_paths);
   11524           4 :                         else if (type == bgp_show_type_flap_statistics
   11525             :                                  || type == bgp_show_type_flap_neighbor)
   11526           0 :                                 flap_route_vty_out(vty, dest_p, pi, display,
   11527             :                                                    AFI_IP, safi, use_json,
   11528             :                                                    json_paths);
   11529             :                         else {
   11530           4 :                                 if (detail_routes || detail_json) {
   11531           0 :                                         const struct prefix_rd *prd = NULL;
   11532             : 
   11533           0 :                                         if (dest->pdest)
   11534           0 :                                                 prd = bgp_rd_from_dest(
   11535             :                                                         dest->pdest, safi);
   11536             : 
   11537           0 :                                         if (!use_json)
   11538           0 :                                                 route_vty_out_detail_header(
   11539             :                                                         vty, bgp, dest,
   11540             :                                                         bgp_dest_get_prefix(
   11541             :                                                                 dest),
   11542             :                                                         prd, table->afi, safi,
   11543             :                                                         NULL);
   11544             : 
   11545           0 :                                         route_vty_out_detail(
   11546             :                                                 vty, bgp, dest, dest_p, pi,
   11547           0 :                                                 family2afi(dest_p->family),
   11548             :                                                 safi, RPKI_NOT_BEING_USED,
   11549             :                                                 json_paths);
   11550             :                                 } else {
   11551           4 :                                         route_vty_out(vty, dest_p, pi, display,
   11552             :                                                       safi, json_paths, wide);
   11553             :                                 }
   11554             :                         }
   11555           4 :                         display++;
   11556             :                 }
   11557             : 
   11558           4 :                 if (display) {
   11559           4 :                         output_count++;
   11560           4 :                         if (!use_json)
   11561           0 :                                 continue;
   11562             : 
   11563             :                         /* encode prefix */
   11564           4 :                         if (dest_p->family == AF_FLOWSPEC) {
   11565           0 :                                 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
   11566             : 
   11567             : 
   11568           0 :                                 bgp_fs_nlri_get_string(
   11569             :                                         (unsigned char *)
   11570           0 :                                                 dest_p->u.prefix_flowspec.ptr,
   11571           0 :                                         dest_p->u.prefix_flowspec.prefixlen,
   11572             :                                         retstr, NLRI_STRING_FORMAT_MIN, NULL,
   11573             :                                         family2afi(dest_p->u
   11574           0 :                                                    .prefix_flowspec.family));
   11575           0 :                                 if (first)
   11576           0 :                                         vty_out(vty, "\"%s/%d\": ", retstr,
   11577             :                                                 dest_p->u.prefix_flowspec
   11578           0 :                                                         .prefixlen);
   11579             :                                 else
   11580           0 :                                         vty_out(vty, ",\"%s/%d\": ", retstr,
   11581             :                                                 dest_p->u.prefix_flowspec
   11582           0 :                                                         .prefixlen);
   11583             :                         } else {
   11584           4 :                                 if (first)
   11585           1 :                                         vty_out(vty, "\"%pFX\": ", dest_p);
   11586             :                                 else
   11587           3 :                                         vty_out(vty, ",\"%pFX\": ", dest_p);
   11588             :                         }
   11589             :                         /*
   11590             :                          * We are using no_pretty here because under
   11591             :                          * extremely high settings( say lots and lots of
   11592             :                          * routes with lots and lots of ways to reach
   11593             :                          * that route via different paths ) this can
   11594             :                          * save several minutes of output when FRR
   11595             :                          * is run on older cpu's or more underperforming
   11596             :                          * routers out there
   11597             :                          */
   11598           4 :                         vty_json_no_pretty(vty, json_paths);
   11599           4 :                         json_paths = NULL;
   11600           4 :                         first = 0;
   11601             :                 } else
   11602           0 :                         json_object_free(json_paths);
   11603             :         }
   11604             : 
   11605          48 :         if (output_cum) {
   11606           0 :                 output_count += *output_cum;
   11607           0 :                 *output_cum = output_count;
   11608             :         }
   11609          48 :         if (total_cum) {
   11610           0 :                 total_count += *total_cum;
   11611           0 :                 *total_cum = total_count;
   11612             :         }
   11613          48 :         if (use_json) {
   11614          48 :                 if (rd) {
   11615           0 :                         vty_out(vty, " }%s ", (is_last ? "" : ","));
   11616             :                 }
   11617          48 :                 if (is_last) {
   11618             :                         unsigned long i;
   11619         144 :                         for (i = 0; i < *json_header_depth; ++i)
   11620          96 :                                 vty_out(vty, " } ");
   11621          48 :                         if (!all)
   11622          48 :                                 vty_out(vty, "\n");
   11623             :                 }
   11624             :         } else {
   11625           0 :                 if (is_last) {
   11626             :                         /* No route is displayed */
   11627           0 :                         if (output_count == 0) {
   11628           0 :                                 if (type == bgp_show_type_normal)
   11629           0 :                                         vty_out(vty,
   11630             :                                                 "No BGP prefixes displayed, %ld exist\n",
   11631             :                                                 total_count);
   11632             :                         } else
   11633           0 :                                 vty_out(vty,
   11634             :                                         "\nDisplayed  %ld routes and %ld total paths\n",
   11635             :                                         output_count, total_count);
   11636             :                 }
   11637             :         }
   11638             : 
   11639          48 :         return CMD_SUCCESS;
   11640             : }
   11641             : 
   11642           0 : int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
   11643             :                       struct bgp_table *table, struct prefix_rd *prd_match,
   11644             :                       enum bgp_show_type type, void *output_arg,
   11645             :                       uint16_t show_flags)
   11646             : {
   11647           0 :         struct bgp_dest *dest, *next;
   11648           0 :         unsigned long output_cum = 0;
   11649           0 :         unsigned long total_cum = 0;
   11650           0 :         unsigned long json_header_depth = 0;
   11651           0 :         struct bgp_table *itable;
   11652           0 :         bool show_msg;
   11653           0 :         bool use_json = !!CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
   11654             : 
   11655           0 :         show_msg = (!use_json && type == bgp_show_type_normal);
   11656             : 
   11657           0 :         for (dest = bgp_table_top(table); dest; dest = next) {
   11658           0 :                 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
   11659             : 
   11660           0 :                 next = bgp_route_next(dest);
   11661           0 :                 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
   11662           0 :                         continue;
   11663             : 
   11664           0 :                 itable = bgp_dest_get_bgp_table_info(dest);
   11665           0 :                 if (itable != NULL) {
   11666           0 :                         struct prefix_rd prd;
   11667           0 :                         char rd[RD_ADDRSTRLEN];
   11668             : 
   11669           0 :                         memcpy(&prd, dest_p, sizeof(struct prefix_rd));
   11670           0 :                         prefix_rd2str(&prd, rd, sizeof(rd));
   11671           0 :                         bgp_show_table(vty, bgp, safi, itable, type, output_arg,
   11672             :                                        rd, next == NULL, &output_cum,
   11673             :                                        &total_cum, &json_header_depth,
   11674             :                                        show_flags, RPKI_NOT_BEING_USED);
   11675           0 :                         if (next == NULL)
   11676           0 :                                 show_msg = false;
   11677             :                 }
   11678             :         }
   11679           0 :         if (show_msg) {
   11680           0 :                 if (output_cum == 0)
   11681           0 :                         vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
   11682             :                                 total_cum);
   11683             :                 else
   11684           0 :                         vty_out(vty,
   11685             :                                 "\nDisplayed  %ld routes and %ld total paths\n",
   11686             :                                 output_cum, total_cum);
   11687             :         } else {
   11688           0 :                 if (use_json && output_cum == 0)
   11689           0 :                         vty_out(vty, "{}\n");
   11690             :         }
   11691           0 :         return CMD_SUCCESS;
   11692             : }
   11693             : 
   11694          48 : static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
   11695             :                     enum bgp_show_type type, void *output_arg,
   11696             :                     uint16_t show_flags, enum rpki_states rpki_target_state)
   11697             : {
   11698          48 :         struct bgp_table *table;
   11699          48 :         unsigned long json_header_depth = 0;
   11700          48 :         bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
   11701             : 
   11702          48 :         if (bgp == NULL) {
   11703           0 :                 bgp = bgp_get_default();
   11704             :         }
   11705             : 
   11706           0 :         if (bgp == NULL) {
   11707           0 :                 if (!use_json)
   11708           0 :                         vty_out(vty, "No BGP process is configured\n");
   11709             :                 else
   11710           0 :                         vty_out(vty, "{}\n");
   11711           0 :                 return CMD_WARNING;
   11712             :         }
   11713             : 
   11714             :         /* Labeled-unicast routes live in the unicast table. */
   11715          48 :         if (safi == SAFI_LABELED_UNICAST)
   11716           0 :                 safi = SAFI_UNICAST;
   11717             : 
   11718          48 :         table = bgp->rib[afi][safi];
   11719             :         /* use MPLS and ENCAP specific shows until they are merged */
   11720          48 :         if (safi == SAFI_MPLS_VPN) {
   11721           0 :                 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
   11722             :                                          output_arg, show_flags);
   11723             :         }
   11724             : 
   11725          48 :         if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
   11726           0 :                 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
   11727             :                                                output_arg, use_json,
   11728             :                                                1, NULL, NULL);
   11729             :         }
   11730             : 
   11731          48 :         if (safi == SAFI_EVPN)
   11732           0 :                 return bgp_evpn_show_all_routes(vty, bgp, type, use_json, 0);
   11733             : 
   11734          48 :         return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
   11735             :                               NULL, NULL, &json_header_depth, show_flags,
   11736             :                               rpki_target_state);
   11737             : }
   11738             : 
   11739           0 : static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
   11740             :                                               safi_t safi, uint16_t show_flags)
   11741             : {
   11742           0 :         struct listnode *node, *nnode;
   11743           0 :         struct bgp *bgp;
   11744           0 :         int is_first = 1;
   11745           0 :         bool route_output = false;
   11746           0 :         bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
   11747             : 
   11748           0 :         if (use_json)
   11749           0 :                 vty_out(vty, "{\n");
   11750             : 
   11751           0 :         for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
   11752           0 :                 route_output = true;
   11753           0 :                 if (use_json) {
   11754           0 :                         if (!is_first)
   11755           0 :                                 vty_out(vty, ",\n");
   11756             :                         else
   11757             :                                 is_first = 0;
   11758             : 
   11759           0 :                         vty_out(vty, "\"%s\":",
   11760           0 :                                 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
   11761           0 :                                         ? VRF_DEFAULT_NAME
   11762             :                                         : bgp->name);
   11763             :                 } else {
   11764           0 :                         vty_out(vty, "\nInstance %s:\n",
   11765           0 :                                 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
   11766           0 :                                         ? VRF_DEFAULT_NAME
   11767             :                                         : bgp->name);
   11768             :                 }
   11769           0 :                 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
   11770             :                          show_flags, RPKI_NOT_BEING_USED);
   11771             :         }
   11772             : 
   11773           0 :         if (use_json)
   11774           0 :                 vty_out(vty, "}\n");
   11775           0 :         else if (!route_output)
   11776           0 :                 vty_out(vty, "%% BGP instance not found\n");
   11777           0 : }
   11778             : 
   11779             : /* Header of detailed BGP route information */
   11780           0 : void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
   11781             :                                  struct bgp_dest *dest, const struct prefix *p,
   11782             :                                  const struct prefix_rd *prd, afi_t afi,
   11783             :                                  safi_t safi, json_object *json)
   11784             : {
   11785           0 :         struct bgp_path_info *pi;
   11786           0 :         struct peer *peer;
   11787           0 :         struct listnode *node, *nnode;
   11788           0 :         char buf1[RD_ADDRSTRLEN];
   11789           0 :         int count = 0;
   11790           0 :         int best = 0;
   11791           0 :         int suppress = 0;
   11792           0 :         int accept_own = 0;
   11793           0 :         int route_filter_translated_v4 = 0;
   11794           0 :         int route_filter_v4 = 0;
   11795           0 :         int route_filter_translated_v6 = 0;
   11796           0 :         int route_filter_v6 = 0;
   11797           0 :         int llgr_stale = 0;
   11798           0 :         int no_llgr = 0;
   11799           0 :         int accept_own_nexthop = 0;
   11800           0 :         int blackhole = 0;
   11801           0 :         int no_export = 0;
   11802           0 :         int no_advertise = 0;
   11803           0 :         int local_as = 0;
   11804           0 :         int no_peer = 0;
   11805           0 :         int first = 1;
   11806           0 :         int has_valid_label = 0;
   11807           0 :         mpls_label_t label = 0;
   11808           0 :         json_object *json_adv_to = NULL;
   11809           0 :         uint32_t ttl = 0;
   11810           0 :         uint32_t bos = 0;
   11811           0 :         uint32_t exp = 0;
   11812             : 
   11813           0 :         mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
   11814             : 
   11815           0 :         has_valid_label = bgp_is_valid_label(&label);
   11816             : 
   11817           0 :         if (safi == SAFI_EVPN) {
   11818           0 :                 if (!json) {
   11819           0 :                         vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
   11820           0 :                                 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
   11821             :                                     : "",
   11822             :                                 prd ? ":" : "", (struct prefix_evpn *)p);
   11823             :                 } else {
   11824           0 :                         json_object_string_add(json, "rd",
   11825           0 :                                 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
   11826             :                                 "");
   11827           0 :                         bgp_evpn_route2json((struct prefix_evpn *)p, json);
   11828             :                 }
   11829             :         } else {
   11830           0 :                 if (!json) {
   11831           0 :                         vty_out(vty,
   11832             :                                 "BGP routing table entry for %s%s%pFX, version %" PRIu64
   11833             :                                 "\n",
   11834           0 :                                 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
   11835           0 :                                          ? prefix_rd2str(prd, buf1,
   11836             :                                                          sizeof(buf1))
   11837             :                                          : ""),
   11838             :                                 safi == SAFI_MPLS_VPN ? ":" : "", p,
   11839             :                                 dest->version);
   11840             : 
   11841             :                 } else {
   11842           0 :                         json_object_string_addf(json, "prefix", "%pFX", p);
   11843           0 :                         json_object_int_add(json, "version", dest->version);
   11844             : 
   11845             :                 }
   11846             :         }
   11847             : 
   11848           0 :         if (has_valid_label) {
   11849           0 :                 if (json)
   11850           0 :                         json_object_int_add(json, "localLabel", label);
   11851             :                 else
   11852           0 :                         vty_out(vty, "Local label: %d\n", label);
   11853             :         }
   11854             : 
   11855           0 :         if (!json)
   11856           0 :                 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
   11857           0 :                         vty_out(vty, "not allocated\n");
   11858             : 
   11859           0 :         for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
   11860           0 :                 struct community *picomm = NULL;
   11861             : 
   11862           0 :                 picomm = bgp_attr_get_community(pi->attr);
   11863             : 
   11864           0 :                 count++;
   11865           0 :                 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
   11866           0 :                         best = count;
   11867           0 :                         if (bgp_path_suppressed(pi))
   11868           0 :                                 suppress = 1;
   11869             : 
   11870           0 :                         if (!picomm)
   11871           0 :                                 continue;
   11872             : 
   11873           0 :                         no_advertise += community_include(
   11874             :                                 picomm, COMMUNITY_NO_ADVERTISE);
   11875           0 :                         no_export +=
   11876           0 :                                 community_include(picomm, COMMUNITY_NO_EXPORT);
   11877           0 :                         local_as +=
   11878           0 :                                 community_include(picomm, COMMUNITY_LOCAL_AS);
   11879           0 :                         accept_own +=
   11880           0 :                                 community_include(picomm, COMMUNITY_ACCEPT_OWN);
   11881           0 :                         route_filter_translated_v4 += community_include(
   11882             :                                 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
   11883           0 :                         route_filter_translated_v6 += community_include(
   11884             :                                 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
   11885           0 :                         route_filter_v4 += community_include(
   11886             :                                 picomm, COMMUNITY_ROUTE_FILTER_v4);
   11887           0 :                         route_filter_v6 += community_include(
   11888             :                                 picomm, COMMUNITY_ROUTE_FILTER_v6);
   11889           0 :                         llgr_stale +=
   11890           0 :                                 community_include(picomm, COMMUNITY_LLGR_STALE);
   11891           0 :                         no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
   11892           0 :                         accept_own_nexthop += community_include(
   11893             :                                 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
   11894           0 :                         blackhole +=
   11895           0 :                                 community_include(picomm, COMMUNITY_BLACKHOLE);
   11896           0 :                         no_peer += community_include(picomm, COMMUNITY_NO_PEER);
   11897             :                 }
   11898             :         }
   11899             : 
   11900           0 :         if (!json) {
   11901           0 :                 vty_out(vty, "Paths: (%d available", count);
   11902           0 :                 if (best) {
   11903           0 :                         vty_out(vty, ", best #%d", best);
   11904           0 :                         if (safi == SAFI_UNICAST) {
   11905           0 :                                 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
   11906           0 :                                         vty_out(vty, ", table %s",
   11907             :                                                 VRF_DEFAULT_NAME);
   11908             :                                 else
   11909           0 :                                         vty_out(vty, ", vrf %s",
   11910             :                                                 bgp->name);
   11911             :                         }
   11912             :                 } else
   11913           0 :                         vty_out(vty, ", no best path");
   11914             : 
   11915           0 :                 if (accept_own)
   11916           0 :                         vty_out(vty,
   11917             :                         ", accept own local route exported and imported in different VRF");
   11918           0 :                 else if (route_filter_translated_v4)
   11919           0 :                         vty_out(vty,
   11920             :                         ", mark translated RTs for VPNv4 route filtering");
   11921           0 :                 else if (route_filter_v4)
   11922           0 :                         vty_out(vty,
   11923             :                         ", attach RT as-is for VPNv4 route filtering");
   11924           0 :                 else if (route_filter_translated_v6)
   11925           0 :                         vty_out(vty,
   11926             :                         ", mark translated RTs for VPNv6 route filtering");
   11927           0 :                 else if (route_filter_v6)
   11928           0 :                         vty_out(vty,
   11929             :                         ", attach RT as-is for VPNv6 route filtering");
   11930           0 :                 else if (llgr_stale)
   11931           0 :                         vty_out(vty,
   11932             :                                 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
   11933           0 :                 else if (no_llgr)
   11934           0 :                         vty_out(vty,
   11935             :                         ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
   11936           0 :                 else if (accept_own_nexthop)
   11937           0 :                         vty_out(vty,
   11938             :                         ", accept local nexthop");
   11939           0 :                 else if (blackhole)
   11940           0 :                         vty_out(vty, ", inform peer to blackhole prefix");
   11941           0 :                 else if (no_export)
   11942           0 :                         vty_out(vty, ", not advertised to EBGP peer");
   11943           0 :                 else if (no_advertise)
   11944           0 :                         vty_out(vty, ", not advertised to any peer");
   11945           0 :                 else if (local_as)
   11946           0 :                         vty_out(vty, ", not advertised outside local AS");
   11947           0 :                 else if (no_peer)
   11948           0 :                         vty_out(vty,
   11949             :                         ", inform EBGP peer not to advertise to their EBGP peers");
   11950             : 
   11951           0 :                 if (suppress)
   11952           0 :                         vty_out(vty,
   11953             :                                 ", Advertisements suppressed by an aggregate.");
   11954           0 :                 vty_out(vty, ")\n");
   11955             :         }
   11956             : 
   11957             :         /* If we are not using addpath then we can display Advertised to and
   11958             :          * that will
   11959             :          * show what peers we advertised the bestpath to.  If we are using
   11960             :          * addpath
   11961             :          * though then we must display Advertised to on a path-by-path basis. */
   11962           0 :         if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
   11963           0 :                 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
   11964           0 :                         if (bgp_adj_out_lookup(peer, dest, 0)) {
   11965           0 :                                 if (json && !json_adv_to)
   11966           0 :                                         json_adv_to = json_object_new_object();
   11967             : 
   11968           0 :                                 route_vty_out_advertised_to(
   11969             :                                         vty, peer, &first,
   11970             :                                         "  Advertised to non peer-group peers:\n ",
   11971             :                                         json_adv_to);
   11972             :                         }
   11973             :                 }
   11974             : 
   11975           0 :                 if (json) {
   11976           0 :                         if (json_adv_to) {
   11977           0 :                                 json_object_object_add(json, "advertisedTo",
   11978             :                                                        json_adv_to);
   11979             :                         }
   11980             :                 } else {
   11981           0 :                         if (first)
   11982           0 :                                 vty_out(vty, "  Not advertised to any peer");
   11983           0 :                         vty_out(vty, "\n");
   11984             :                 }
   11985             :         }
   11986           0 : }
   11987             : 
   11988           0 : static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
   11989             :                                struct bgp_dest *bgp_node, struct vty *vty,
   11990             :                                struct bgp *bgp, afi_t afi, safi_t safi,
   11991             :                                json_object *json, enum bgp_path_type pathtype,
   11992             :                                int *display, enum rpki_states rpki_target_state)
   11993             : {
   11994           0 :         struct bgp_path_info *pi;
   11995           0 :         int header = 1;
   11996           0 :         json_object *json_header = NULL;
   11997           0 :         json_object *json_paths = NULL;
   11998           0 :         const struct prefix *p = bgp_dest_get_prefix(bgp_node);
   11999             : 
   12000           0 :         for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
   12001           0 :                 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
   12002             : 
   12003           0 :                 if (p->family == AF_INET || p->family == AF_INET6)
   12004           0 :                         rpki_curr_state = hook_call(bgp_rpki_prefix_status,
   12005             :                                                     pi->peer, pi->attr, p);
   12006             : 
   12007           0 :                 if (rpki_target_state != RPKI_NOT_BEING_USED
   12008           0 :                     && rpki_curr_state != rpki_target_state)
   12009           0 :                         continue;
   12010             : 
   12011           0 :                 if (json && !json_paths) {
   12012             :                         /* Instantiate json_paths only if path is valid */
   12013           0 :                         json_paths = json_object_new_array();
   12014           0 :                         if (pfx_rd)
   12015           0 :                                 json_header = json_object_new_object();
   12016             :                         else
   12017             :                                 json_header = json;
   12018             :                 }
   12019             : 
   12020           0 :                 if (header) {
   12021           0 :                         route_vty_out_detail_header(
   12022             :                                 vty, bgp, bgp_node,
   12023             :                                 bgp_dest_get_prefix(bgp_node), pfx_rd, AFI_IP,
   12024             :                                 safi, json_header);
   12025           0 :                         header = 0;
   12026             :                 }
   12027           0 :                 (*display)++;
   12028             : 
   12029           0 :                 if (pathtype == BGP_PATH_SHOW_ALL
   12030           0 :                     || (pathtype == BGP_PATH_SHOW_BESTPATH
   12031           0 :                         && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
   12032           0 :                     || (pathtype == BGP_PATH_SHOW_MULTIPATH
   12033           0 :                         && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
   12034           0 :                             || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
   12035           0 :                         route_vty_out_detail(vty, bgp, bgp_node,
   12036             :                                              bgp_dest_get_prefix(bgp_node), pi,
   12037             :                                              AFI_IP, safi, rpki_curr_state,
   12038             :                                              json_paths);
   12039             :         }
   12040             : 
   12041           0 :         if (json && json_paths) {
   12042           0 :                 json_object_object_add(json_header, "paths", json_paths);
   12043             : 
   12044           0 :                 if (pfx_rd)
   12045           0 :                         json_object_object_addf(json, json_header, "%pRD",
   12046             :                                                 pfx_rd);
   12047             :         }
   12048           0 : }
   12049             : 
   12050             : /*
   12051             :  * Return rd based on safi
   12052             :  */
   12053           0 : const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
   12054             :                                          safi_t safi)
   12055             : {
   12056           0 :         switch (safi) {
   12057             :         case SAFI_MPLS_VPN:
   12058             :         case SAFI_ENCAP:
   12059             :         case SAFI_EVPN:
   12060           0 :                 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
   12061             :         case SAFI_UNSPEC:
   12062             :         case SAFI_UNICAST:
   12063             :         case SAFI_MULTICAST:
   12064             :         case SAFI_LABELED_UNICAST:
   12065             :         case SAFI_FLOWSPEC:
   12066             :         case SAFI_MAX:
   12067             :                 return NULL;
   12068             :         }
   12069             : 
   12070           0 :         assert(!"Reached end of function when we were not expecting it");
   12071             : }
   12072             : 
   12073             : /* Display specified route of BGP table. */
   12074           0 : static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
   12075             :                                    struct bgp_table *rib, const char *ip_str,
   12076             :                                    afi_t afi, safi_t safi,
   12077             :                                    enum rpki_states rpki_target_state,
   12078             :                                    struct prefix_rd *prd, int prefix_check,
   12079             :                                    enum bgp_path_type pathtype, bool use_json)
   12080             : {
   12081           0 :         int ret;
   12082           0 :         int display = 0;
   12083           0 :         struct prefix match;
   12084           0 :         struct bgp_dest *dest;
   12085           0 :         struct bgp_dest *rm;
   12086           0 :         struct bgp_table *table;
   12087           0 :         json_object *json = NULL;
   12088           0 :         json_object *json_paths = NULL;
   12089             : 
   12090             :         /* Check IP address argument. */
   12091           0 :         ret = str2prefix(ip_str, &match);
   12092           0 :         if (!ret) {
   12093           0 :                 vty_out(vty, "address is malformed\n");
   12094           0 :                 return CMD_WARNING;
   12095             :         }
   12096             : 
   12097           0 :         match.family = afi2family(afi);
   12098             : 
   12099           0 :         if (use_json)
   12100           0 :                 json = json_object_new_object();
   12101             : 
   12102           0 :         if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
   12103           0 :                 for (dest = bgp_table_top(rib); dest;
   12104           0 :                      dest = bgp_route_next(dest)) {
   12105           0 :                         const struct prefix *dest_p = bgp_dest_get_prefix(dest);
   12106             : 
   12107           0 :                         if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
   12108           0 :                                 continue;
   12109           0 :                         table = bgp_dest_get_bgp_table_info(dest);
   12110           0 :                         if (!table)
   12111           0 :                                 continue;
   12112             : 
   12113           0 :                         rm = bgp_node_match(table, &match);
   12114           0 :                         if (rm == NULL)
   12115           0 :                                 continue;
   12116             : 
   12117           0 :                         const struct prefix *rm_p = bgp_dest_get_prefix(rm);
   12118           0 :                         if (prefix_check
   12119           0 :                             && rm_p->prefixlen != match.prefixlen) {
   12120           0 :                                 bgp_dest_unlock_node(rm);
   12121           0 :                                 continue;
   12122             :                         }
   12123             : 
   12124           0 :                         bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
   12125             :                                            bgp, afi, safi, json, pathtype,
   12126             :                                            &display, rpki_target_state);
   12127             : 
   12128           0 :                         bgp_dest_unlock_node(rm);
   12129             :                 }
   12130           0 :         } else if (safi == SAFI_EVPN) {
   12131           0 :                 struct bgp_dest *longest_pfx;
   12132           0 :                 bool is_exact_pfxlen_match = false;
   12133             : 
   12134           0 :                 for (dest = bgp_table_top(rib); dest;
   12135           0 :                      dest = bgp_route_next(dest)) {
   12136           0 :                         const struct prefix *dest_p = bgp_dest_get_prefix(dest);
   12137             : 
   12138           0 :                         if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
   12139           0 :                                 continue;
   12140           0 :                         table = bgp_dest_get_bgp_table_info(dest);
   12141           0 :                         if (!table)
   12142           0 :                                 continue;
   12143             : 
   12144           0 :                         longest_pfx = NULL;
   12145           0 :                         is_exact_pfxlen_match = false;
   12146             :                         /*
   12147             :                          * Search through all the prefixes for a match.  The
   12148             :                          * pfx's are enumerated in ascending order of pfxlens.
   12149             :                          * So, the last pfx match is the longest match.  Set
   12150             :                          * is_exact_pfxlen_match when we get exact pfxlen match
   12151             :                          */
   12152           0 :                         for (rm = bgp_table_top(table); rm;
   12153           0 :                                 rm = bgp_route_next(rm)) {
   12154           0 :                                 const struct prefix *rm_p =
   12155           0 :                                         bgp_dest_get_prefix(rm);
   12156             :                                 /*
   12157             :                                  * Get prefixlen of the ip-prefix within type5
   12158             :                                  * evpn route
   12159             :                                  */
   12160           0 :                                 if (evpn_type5_prefix_match(rm_p, &match)
   12161           0 :                                     && rm->info) {
   12162           0 :                                         longest_pfx = rm;
   12163           0 :                                         int type5_pfxlen =
   12164           0 :                                                 bgp_evpn_get_type5_prefixlen(
   12165             :                                                         rm_p);
   12166           0 :                                         if (type5_pfxlen == match.prefixlen) {
   12167           0 :                                                 is_exact_pfxlen_match = true;
   12168           0 :                                                 bgp_dest_unlock_node(rm);
   12169           0 :                                                 break;
   12170             :                                         }
   12171             :                                 }
   12172             :                         }
   12173             : 
   12174           0 :                         if (!longest_pfx)
   12175           0 :                                 continue;
   12176             : 
   12177           0 :                         if (prefix_check && !is_exact_pfxlen_match)
   12178           0 :                                 continue;
   12179             : 
   12180           0 :                         rm = longest_pfx;
   12181           0 :                         bgp_dest_lock_node(rm);
   12182             : 
   12183           0 :                         bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
   12184             :                                            bgp, afi, safi, json, pathtype,
   12185             :                                            &display, rpki_target_state);
   12186             : 
   12187           0 :                         bgp_dest_unlock_node(rm);
   12188             :                 }
   12189           0 :         } else if (safi == SAFI_FLOWSPEC) {
   12190           0 :                 if (use_json)
   12191           0 :                         json_paths = json_object_new_array();
   12192             : 
   12193           0 :                 display = bgp_flowspec_display_match_per_ip(afi, rib,
   12194             :                                            &match, prefix_check,
   12195             :                                            vty,
   12196             :                                            use_json,
   12197             :                                            json_paths);
   12198           0 :                 if (use_json) {
   12199           0 :                         if (display)
   12200           0 :                                 json_object_object_add(json, "paths",
   12201             :                                                        json_paths);
   12202             :                         else
   12203           0 :                                 json_object_free(json_paths);
   12204             :                 }
   12205             :         } else {
   12206           0 :                 dest = bgp_node_match(rib, &match);
   12207           0 :                 if (dest != NULL) {
   12208           0 :                         const struct prefix *dest_p = bgp_dest_get_prefix(dest);
   12209           0 :                         if (!prefix_check
   12210           0 :                             || dest_p->prefixlen == match.prefixlen) {
   12211           0 :                                 bgp_show_path_info(NULL, dest, vty, bgp, afi,
   12212             :                                                    safi, json, pathtype,
   12213             :                                                    &display, rpki_target_state);
   12214             :                         }
   12215             : 
   12216           0 :                         bgp_dest_unlock_node(dest);
   12217             :                 }
   12218             :         }
   12219             : 
   12220           0 :         if (use_json) {
   12221           0 :                 vty_json(vty, json);
   12222             :         } else {
   12223           0 :                 if (!display) {
   12224           0 :                         vty_out(vty, "%% Network not in table\n");
   12225           0 :                         return CMD_WARNING;
   12226             :                 }
   12227             :         }
   12228             : 
   12229             :         return CMD_SUCCESS;
   12230             : }
   12231             : 
   12232             : /* Display specified route of Main RIB */
   12233           0 : static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
   12234             :                           afi_t afi, safi_t safi, struct prefix_rd *prd,
   12235             :                           int prefix_check, enum bgp_path_type pathtype,
   12236             :                           enum rpki_states rpki_target_state, bool use_json)
   12237             : {
   12238           0 :         if (!bgp) {
   12239           0 :                 bgp = bgp_get_default();
   12240           0 :                 if (!bgp) {
   12241           0 :                         if (!use_json)
   12242           0 :                                 vty_out(vty, "No BGP process is configured\n");
   12243             :                         else
   12244           0 :                                 vty_out(vty, "{}\n");
   12245           0 :                         return CMD_WARNING;
   12246             :                 }
   12247             :         }
   12248             : 
   12249             :         /* labeled-unicast routes live in the unicast table */
   12250           0 :         if (safi == SAFI_LABELED_UNICAST)
   12251           0 :                 safi = SAFI_UNICAST;
   12252             : 
   12253           0 :         return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
   12254             :                                        afi, safi, rpki_target_state, prd,
   12255             :                                        prefix_check, pathtype, use_json);
   12256             : }
   12257             : 
   12258           0 : static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
   12259             :                                struct cmd_token **argv, bool exact, afi_t afi,
   12260             :                                safi_t safi, bool uj)
   12261             : {
   12262           0 :         struct lcommunity *lcom;
   12263           0 :         struct buffer *b;
   12264           0 :         int i;
   12265           0 :         char *str;
   12266           0 :         int first = 0;
   12267           0 :         uint16_t show_flags = 0;
   12268           0 :         int ret;
   12269             : 
   12270           0 :         if (uj)
   12271           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
   12272             : 
   12273           0 :         b = buffer_new(1024);
   12274           0 :         for (i = 0; i < argc; i++) {
   12275           0 :                 if (first)
   12276           0 :                         buffer_putc(b, ' ');
   12277             :                 else {
   12278           0 :                         if (strmatch(argv[i]->text, "AA:BB:CC")) {
   12279           0 :                                 first = 1;
   12280           0 :                                 buffer_putstr(b, argv[i]->arg);
   12281             :                         }
   12282             :                 }
   12283             :         }
   12284           0 :         buffer_putc(b, '\0');
   12285             : 
   12286           0 :         str = buffer_getstr(b);
   12287           0 :         buffer_free(b);
   12288             : 
   12289           0 :         lcom = lcommunity_str2com(str);
   12290           0 :         XFREE(MTYPE_TMP, str);
   12291           0 :         if (!lcom) {
   12292           0 :                 vty_out(vty, "%% Large-community malformed\n");
   12293           0 :                 return CMD_WARNING;
   12294             :         }
   12295             : 
   12296           0 :         ret = bgp_show(vty, bgp, afi, safi,
   12297             :                        (exact ? bgp_show_type_lcommunity_exact
   12298             :                               : bgp_show_type_lcommunity),
   12299             :                        lcom, show_flags, RPKI_NOT_BEING_USED);
   12300             : 
   12301           0 :         lcommunity_free(&lcom);
   12302           0 :         return ret;
   12303             : }
   12304             : 
   12305           0 : static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
   12306             :                                     const char *lcom, bool exact, afi_t afi,
   12307             :                                     safi_t safi, bool uj)
   12308             : {
   12309           0 :         struct community_list *list;
   12310           0 :         uint16_t show_flags = 0;
   12311             : 
   12312           0 :         if (uj)
   12313           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
   12314             : 
   12315             : 
   12316           0 :         list = community_list_lookup(bgp_clist, lcom, 0,
   12317             :                                      LARGE_COMMUNITY_LIST_MASTER);
   12318           0 :         if (list == NULL) {
   12319           0 :                 vty_out(vty, "%% %s is not a valid large-community-list name\n",
   12320             :                         lcom);
   12321           0 :                 return CMD_WARNING;
   12322             :         }
   12323             : 
   12324           0 :         return bgp_show(vty, bgp, afi, safi,
   12325             :                         (exact ? bgp_show_type_lcommunity_list_exact
   12326             :                                : bgp_show_type_lcommunity_list),
   12327             :                         list, show_flags, RPKI_NOT_BEING_USED);
   12328             : }
   12329             : 
   12330           0 : DEFUN (show_ip_bgp_large_community_list,
   12331             :        show_ip_bgp_large_community_list_cmd,
   12332             :        "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community-list <(1-500)|LCOMMUNITY_LIST_NAME> [exact-match] [json]",
   12333             :        SHOW_STR
   12334             :        IP_STR
   12335             :        BGP_STR
   12336             :        BGP_INSTANCE_HELP_STR
   12337             :        BGP_AFI_HELP_STR
   12338             :        BGP_SAFI_WITH_LABEL_HELP_STR
   12339             :        "Display routes matching the large-community-list\n"
   12340             :        "large-community-list number\n"
   12341             :        "large-community-list name\n"
   12342             :        "Exact match of the large-communities\n"
   12343             :        JSON_STR)
   12344             : {
   12345           0 :         afi_t afi = AFI_IP6;
   12346           0 :         safi_t safi = SAFI_UNICAST;
   12347           0 :         int idx = 0;
   12348           0 :         bool exact_match = 0;
   12349           0 :         struct bgp *bgp = NULL;
   12350           0 :         bool uj = use_json(argc, argv);
   12351             : 
   12352           0 :         if (uj)
   12353           0 :                 argc--;
   12354             : 
   12355           0 :         bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
   12356             :                                             &bgp, uj);
   12357           0 :         if (!idx)
   12358             :                 return CMD_WARNING;
   12359             : 
   12360           0 :         argv_find(argv, argc, "large-community-list", &idx);
   12361             : 
   12362           0 :         const char *clist_number_or_name = argv[++idx]->arg;
   12363             : 
   12364           0 :         if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
   12365           0 :                 exact_match = 1;
   12366             : 
   12367           0 :         return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
   12368             :                                         exact_match, afi, safi, uj);
   12369             : }
   12370           0 : DEFUN (show_ip_bgp_large_community,
   12371             :        show_ip_bgp_large_community_cmd,
   12372             :        "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community [<AA:BB:CC> [exact-match]] [json]",
   12373             :        SHOW_STR
   12374             :        IP_STR
   12375             :        BGP_STR
   12376             :        BGP_INSTANCE_HELP_STR
   12377             :        BGP_AFI_HELP_STR
   12378             :        BGP_SAFI_WITH_LABEL_HELP_STR
   12379             :        "Display routes matching the large-communities\n"
   12380             :        "List of large-community numbers\n"
   12381             :        "Exact match of the large-communities\n"
   12382             :        JSON_STR)
   12383             : {
   12384           0 :         afi_t afi = AFI_IP6;
   12385           0 :         safi_t safi = SAFI_UNICAST;
   12386           0 :         int idx = 0;
   12387           0 :         bool exact_match = 0;
   12388           0 :         struct bgp *bgp = NULL;
   12389           0 :         bool uj = use_json(argc, argv);
   12390           0 :         uint16_t show_flags = 0;
   12391             : 
   12392           0 :         if (uj) {
   12393           0 :                 argc--;
   12394           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
   12395             :         }
   12396             : 
   12397           0 :         bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
   12398             :                                             &bgp, uj);
   12399           0 :         if (!idx)
   12400             :                 return CMD_WARNING;
   12401             : 
   12402           0 :         if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
   12403           0 :                 if (argv_find(argv, argc, "exact-match", &idx)) {
   12404           0 :                         argc--;
   12405           0 :                         exact_match = 1;
   12406             :                 }
   12407           0 :                 return bgp_show_lcommunity(vty, bgp, argc, argv,
   12408             :                                         exact_match, afi, safi, uj);
   12409             :         } else
   12410           0 :                 return bgp_show(vty, bgp, afi, safi,
   12411             :                                 bgp_show_type_lcommunity_all, NULL, show_flags,
   12412             :                                 RPKI_NOT_BEING_USED);
   12413             : }
   12414             : 
   12415             : static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
   12416             :                                   safi_t safi, struct json_object *json_array);
   12417             : static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
   12418             :                            safi_t safi, struct json_object *json);
   12419             : 
   12420             : 
   12421           0 : DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
   12422             :       "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
   12423             :       SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
   12424             :       "Display number of prefixes for all afi/safi\n" JSON_STR)
   12425             : {
   12426           0 :         bool uj = use_json(argc, argv);
   12427           0 :         struct bgp *bgp = NULL;
   12428           0 :         safi_t safi = SAFI_UNICAST;
   12429           0 :         afi_t afi = AFI_IP6;
   12430           0 :         int idx = 0;
   12431           0 :         struct json_object *json_all = NULL;
   12432           0 :         struct json_object *json_afi_safi = NULL;
   12433             : 
   12434           0 :         bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
   12435             :                                             &bgp, false);
   12436           0 :         if (!idx)
   12437             :                 return CMD_WARNING;
   12438             : 
   12439           0 :         if (uj)
   12440           0 :                 json_all = json_object_new_object();
   12441             : 
   12442           0 :         FOREACH_AFI_SAFI (afi, safi) {
   12443             :                 /*
   12444             :                  * So limit output to those afi/safi pairs that
   12445             :                  * actually have something interesting in them
   12446             :                  */
   12447           0 :                 if (strmatch(get_afi_safi_str(afi, safi, true),
   12448             :                              "Unknown")) {
   12449           0 :                         continue;
   12450             :                 }
   12451           0 :                 if (uj) {
   12452           0 :                         json_afi_safi = json_object_new_array();
   12453           0 :                         json_object_object_add(
   12454             :                                                json_all,
   12455             :                                                get_afi_safi_str(afi, safi, true),
   12456             :                                                json_afi_safi);
   12457             :                 } else {
   12458             :                         json_afi_safi = NULL;
   12459             :                 }
   12460             : 
   12461           0 :                 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
   12462             :         }
   12463             : 
   12464           0 :         if (uj)
   12465           0 :                 vty_json(vty, json_all);
   12466             : 
   12467             :         return CMD_SUCCESS;
   12468             : }
   12469             : 
   12470             : /* BGP route print out function without JSON */
   12471           0 : DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
   12472             :        show_ip_bgp_l2vpn_evpn_statistics_cmd,
   12473             :        "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
   12474             :        SHOW_STR
   12475             :        IP_STR
   12476             :        BGP_STR
   12477             :        BGP_INSTANCE_HELP_STR
   12478             :        L2VPN_HELP_STR
   12479             :        EVPN_HELP_STR
   12480             :        "BGP RIB advertisement statistics\n"
   12481             :        JSON_STR)
   12482             : {
   12483           0 :         afi_t afi = AFI_IP6;
   12484           0 :         safi_t safi = SAFI_UNICAST;
   12485           0 :         struct bgp *bgp = NULL;
   12486           0 :         int idx = 0, ret;
   12487           0 :         bool uj = use_json(argc, argv);
   12488           0 :         struct json_object *json_afi_safi = NULL, *json = NULL;
   12489             : 
   12490           0 :         bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
   12491             :                                             &bgp, false);
   12492           0 :         if (!idx)
   12493             :                 return CMD_WARNING;
   12494             : 
   12495           0 :         if (uj)
   12496           0 :                 json_afi_safi = json_object_new_array();
   12497             :         else
   12498             :                 json_afi_safi = NULL;
   12499             : 
   12500           0 :         ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
   12501             : 
   12502           0 :         if (uj) {
   12503           0 :                 json = json_object_new_object();
   12504           0 :                 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
   12505             :                                        json_afi_safi);
   12506           0 :                 vty_json(vty, json);
   12507             :         }
   12508             :         return ret;
   12509             : }
   12510             : 
   12511             : /* BGP route print out function without JSON */
   12512           0 : DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
   12513             :       "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
   12514             :       " [" BGP_SAFI_WITH_LABEL_CMD_STR
   12515             :       "]]\
   12516             :          statistics [json]",
   12517             :       SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
   12518             :               BGP_SAFI_WITH_LABEL_HELP_STR
   12519             :       "BGP RIB advertisement statistics\n" JSON_STR)
   12520             : {
   12521           0 :         afi_t afi = AFI_IP6;
   12522           0 :         safi_t safi = SAFI_UNICAST;
   12523           0 :         struct bgp *bgp = NULL;
   12524           0 :         int idx = 0, ret;
   12525           0 :         bool uj = use_json(argc, argv);
   12526           0 :         struct json_object *json_afi_safi = NULL, *json = NULL;
   12527             : 
   12528           0 :         bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
   12529             :                                             &bgp, false);
   12530           0 :         if (!idx)
   12531             :                 return CMD_WARNING;
   12532             : 
   12533           0 :         if (uj)
   12534           0 :                 json_afi_safi = json_object_new_array();
   12535             :         else
   12536             :                 json_afi_safi = NULL;
   12537             : 
   12538           0 :         ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
   12539             : 
   12540           0 :         if (uj) {
   12541           0 :                 json = json_object_new_object();
   12542           0 :                 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
   12543             :                                        json_afi_safi);
   12544           0 :                 vty_json(vty, json);
   12545             :         }
   12546             :         return ret;
   12547             : }
   12548             : 
   12549           0 : DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
   12550             :       "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
   12551             :       " [" BGP_SAFI_WITH_LABEL_CMD_STR
   12552             :       "]] [all$all] dampening parameters [json]",
   12553             :       SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
   12554             :               BGP_SAFI_WITH_LABEL_HELP_STR
   12555             :       "Display the entries for all address families\n"
   12556             :       "Display detailed information about dampening\n"
   12557             :       "Display detail of configured dampening parameters\n"
   12558             :       JSON_STR)
   12559             : {
   12560           0 :         afi_t afi = AFI_IP6;
   12561           0 :         safi_t safi = SAFI_UNICAST;
   12562           0 :         struct bgp *bgp = NULL;
   12563           0 :         int idx = 0;
   12564           0 :         uint16_t show_flags = 0;
   12565           0 :         bool uj = use_json(argc, argv);
   12566             : 
   12567           0 :         if (uj) {
   12568           0 :                 argc--;
   12569           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
   12570             :         }
   12571             : 
   12572             :         /* [<ipv4|ipv6> [all]] */
   12573           0 :         if (all) {
   12574           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
   12575           0 :                 if (argv_find(argv, argc, "ipv4", &idx))
   12576           0 :                         SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
   12577             : 
   12578           0 :                 if (argv_find(argv, argc, "ipv6", &idx))
   12579           0 :                         SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
   12580             :         }
   12581             : 
   12582           0 :         bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
   12583             :                                             &bgp, false);
   12584           0 :         if (!idx)
   12585             :                 return CMD_WARNING;
   12586             : 
   12587           0 :         return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
   12588             : }
   12589             : 
   12590             : /* BGP route print out function */
   12591          48 : DEFPY(show_ip_bgp, show_ip_bgp_cmd,
   12592             :       "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
   12593             :       " [" BGP_SAFI_WITH_LABEL_CMD_STR
   12594             :       "]]\
   12595             :           [all$all]\
   12596             :           [cidr-only\
   12597             :           |dampening <flap-statistics|dampened-paths>\
   12598             :           |community [AA:NN|local-AS|no-advertise|no-export\
   12599             :                      |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
   12600             :                      |accept-own|accept-own-nexthop|route-filter-v6\
   12601             :                      |route-filter-v4|route-filter-translated-v6\
   12602             :                      |route-filter-translated-v4] [exact-match]\
   12603             :           |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
   12604             :           |filter-list AS_PATH_FILTER_NAME\
   12605             :           |prefix-list WORD\
   12606             :           |access-list ACCESSLIST_NAME\
   12607             :           |route-map RMAP_NAME\
   12608             :           |rpki <invalid|valid|notfound>\
   12609             :           |version (1-4294967295)\
   12610             :           |alias ALIAS_NAME\
   12611             :           |A.B.C.D/M longer-prefixes\
   12612             :           |X:X::X:X/M longer-prefixes\
   12613             :           |detail-routes$detail_routes\
   12614             :           ] [json$uj [detail$detail_json] | wide$wide]",
   12615             :       SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
   12616             :               BGP_SAFI_WITH_LABEL_HELP_STR
   12617             :       "Display the entries for all address families\n"
   12618             :       "Display only routes with non-natural netmasks\n"
   12619             :       "Display detailed information about dampening\n"
   12620             :       "Display flap statistics of routes\n"
   12621             :       "Display paths suppressed due to dampening\n"
   12622             :       "Display routes matching the communities\n" COMMUNITY_AANN_STR
   12623             :       "Do not send outside local AS (well-known community)\n"
   12624             :       "Do not advertise to any peer (well-known community)\n"
   12625             :       "Do not export to next AS (well-known community)\n"
   12626             :       "Graceful shutdown (well-known community)\n"
   12627             :       "Do not export to any peer (well-known community)\n"
   12628             :       "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
   12629             :       "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
   12630             :       "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
   12631             :       "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
   12632             :       "Should accept VPN route with local nexthop (well-known community)\n"
   12633             :       "RT VPNv6 route filtering (well-known community)\n"
   12634             :       "RT VPNv4 route filtering (well-known community)\n"
   12635             :       "RT translated VPNv6 route filtering (well-known community)\n"
   12636             :       "RT translated VPNv4 route filtering (well-known community)\n"
   12637             :       "Exact match of the communities\n"
   12638             :       "Community-list number\n"
   12639             :       "Community-list name\n"
   12640             :       "Display routes matching the community-list\n"
   12641             :       "Exact match of the communities\n"
   12642             :       "Display routes conforming to the filter-list\n"
   12643             :       "Regular expression access list name\n"
   12644             :       "Display routes conforming to the prefix-list\n"
   12645             :       "Prefix-list name\n"
   12646             :       "Display routes conforming to the access-list\n"
   12647             :       "Access-list name\n"
   12648             :       "Display routes matching the route-map\n"
   12649             :       "A route-map to match on\n"
   12650             :       "RPKI route types\n"
   12651             :       "A valid path as determined by rpki\n"
   12652             :       "A invalid path as determined by rpki\n"
   12653             :       "A path that has no rpki data\n"
   12654             :       "Display prefixes with matching version numbers\n"
   12655             :       "Version number and above\n"
   12656             :       "Display prefixes with matching BGP community alias\n"
   12657             :       "BGP community alias\n"
   12658             :       "IPv4 prefix\n"
   12659             :       "Display route and more specific routes\n"
   12660             :       "IPv6 prefix\n"
   12661             :       "Display route and more specific routes\n"
   12662             :       "Display detailed version of all routes\n"
   12663             :       JSON_STR
   12664             :       "Display detailed version of JSON output\n"
   12665             :       "Increase table width for longer prefixes\n")
   12666             : {
   12667          48 :         afi_t afi = AFI_IP6;
   12668          48 :         safi_t safi = SAFI_UNICAST;
   12669          48 :         enum bgp_show_type sh_type = bgp_show_type_normal;
   12670          48 :         void *output_arg = NULL;
   12671          48 :         struct bgp *bgp = NULL;
   12672          48 :         int idx = 0;
   12673          48 :         int exact_match = 0;
   12674          48 :         char *community = NULL;
   12675          48 :         bool first = true;
   12676          48 :         uint16_t show_flags = 0;
   12677          48 :         enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
   12678          48 :         struct prefix p;
   12679             : 
   12680          48 :         if (uj) {
   12681          48 :                 argc--;
   12682          48 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
   12683             :         }
   12684             : 
   12685          48 :         if (detail_json)
   12686           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
   12687             : 
   12688          48 :         if (detail_routes)
   12689           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
   12690             : 
   12691             :         /* [<ipv4|ipv6> [all]] */
   12692          48 :         if (all) {
   12693           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
   12694             : 
   12695           0 :                 if (argv_find(argv, argc, "ipv4", &idx))
   12696           0 :                         SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
   12697             : 
   12698           0 :                 if (argv_find(argv, argc, "ipv6", &idx))
   12699           0 :                         SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
   12700             :         }
   12701             : 
   12702          48 :         if (wide)
   12703           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
   12704             : 
   12705          48 :         bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
   12706             :                                             &bgp, uj);
   12707          48 :         if (!idx)
   12708             :                 return CMD_WARNING;
   12709             : 
   12710          48 :         if (argv_find(argv, argc, "cidr-only", &idx))
   12711           0 :                 sh_type = bgp_show_type_cidr_only;
   12712             : 
   12713          48 :         if (argv_find(argv, argc, "dampening", &idx)) {
   12714           0 :                 if (argv_find(argv, argc, "dampened-paths", &idx))
   12715             :                         sh_type = bgp_show_type_dampend_paths;
   12716           0 :                 else if (argv_find(argv, argc, "flap-statistics", &idx))
   12717          48 :                         sh_type = bgp_show_type_flap_statistics;
   12718             :         }
   12719             : 
   12720          48 :         if (argv_find(argv, argc, "community", &idx)) {
   12721           0 :                 char *maybecomm = NULL;
   12722             : 
   12723           0 :                 if (idx + 1 < argc) {
   12724           0 :                         if (argv[idx + 1]->type == VARIABLE_TKN)
   12725           0 :                                 maybecomm = argv[idx + 1]->arg;
   12726             :                         else
   12727           0 :                                 maybecomm = argv[idx + 1]->text;
   12728             :                 }
   12729             : 
   12730           0 :                 if (maybecomm && !strmatch(maybecomm, "json")
   12731           0 :                     && !strmatch(maybecomm, "exact-match"))
   12732           0 :                         community = maybecomm;
   12733             : 
   12734           0 :                 if (argv_find(argv, argc, "exact-match", &idx))
   12735           0 :                         exact_match = 1;
   12736             : 
   12737           0 :                 if (!community)
   12738           0 :                         sh_type = bgp_show_type_community_all;
   12739             :         }
   12740             : 
   12741          48 :         if (argv_find(argv, argc, "community-list", &idx)) {
   12742           0 :                 const char *clist_number_or_name = argv[++idx]->arg;
   12743           0 :                 struct community_list *list;
   12744             : 
   12745           0 :                 if (argv_find(argv, argc, "exact-match", &idx))
   12746           0 :                         exact_match = 1;
   12747             : 
   12748           0 :                 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
   12749             :                                              COMMUNITY_LIST_MASTER);
   12750           0 :                 if (list == NULL) {
   12751           0 :                         vty_out(vty, "%% %s community-list not found\n",
   12752             :                                 clist_number_or_name);
   12753           0 :                         return CMD_WARNING;
   12754             :                 }
   12755             : 
   12756           0 :                 if (exact_match)
   12757             :                         sh_type = bgp_show_type_community_list_exact;
   12758             :                 else
   12759           0 :                         sh_type = bgp_show_type_community_list;
   12760             :                 output_arg = list;
   12761             :         }
   12762             : 
   12763          48 :         if (argv_find(argv, argc, "filter-list", &idx)) {
   12764           0 :                 const char *filter = argv[++idx]->arg;
   12765           0 :                 struct as_list *as_list;
   12766             : 
   12767           0 :                 as_list = as_list_lookup(filter);
   12768           0 :                 if (as_list == NULL) {
   12769           0 :                         vty_out(vty, "%% %s AS-path access-list not found\n",
   12770             :                                 filter);
   12771           0 :                         return CMD_WARNING;
   12772             :                 }
   12773             : 
   12774             :                 sh_type = bgp_show_type_filter_list;
   12775             :                 output_arg = as_list;
   12776             :         }
   12777             : 
   12778          48 :         if (argv_find(argv, argc, "prefix-list", &idx)) {
   12779           0 :                 const char *prefix_list_str = argv[++idx]->arg;
   12780           0 :                 struct prefix_list *plist;
   12781             : 
   12782           0 :                 plist = prefix_list_lookup(afi, prefix_list_str);
   12783           0 :                 if (plist == NULL) {
   12784           0 :                         vty_out(vty, "%% %s prefix-list not found\n",
   12785             :                                 prefix_list_str);
   12786           0 :                         return CMD_WARNING;
   12787             :                 }
   12788             : 
   12789             :                 sh_type = bgp_show_type_prefix_list;
   12790             :                 output_arg = plist;
   12791             :         }
   12792             : 
   12793          48 :         if (argv_find(argv, argc, "access-list", &idx)) {
   12794           0 :                 const char *access_list_str = argv[++idx]->arg;
   12795           0 :                 struct access_list *alist;
   12796             : 
   12797           0 :                 alist = access_list_lookup(afi, access_list_str);
   12798           0 :                 if (!alist) {
   12799           0 :                         vty_out(vty, "%% %s access-list not found\n",
   12800             :                                 access_list_str);
   12801           0 :                         return CMD_WARNING;
   12802             :                 }
   12803             : 
   12804             :                 sh_type = bgp_show_type_access_list;
   12805             :                 output_arg = alist;
   12806             :         }
   12807             : 
   12808          48 :         if (argv_find(argv, argc, "route-map", &idx)) {
   12809           0 :                 const char *rmap_str = argv[++idx]->arg;
   12810           0 :                 struct route_map *rmap;
   12811             : 
   12812           0 :                 rmap = route_map_lookup_by_name(rmap_str);
   12813           0 :                 if (!rmap) {
   12814           0 :                         vty_out(vty, "%% %s route-map not found\n", rmap_str);
   12815           0 :                         return CMD_WARNING;
   12816             :                 }
   12817             : 
   12818             :                 sh_type = bgp_show_type_route_map;
   12819             :                 output_arg = rmap;
   12820             :         }
   12821             : 
   12822          48 :         if (argv_find(argv, argc, "rpki", &idx)) {
   12823           0 :                 sh_type = bgp_show_type_rpki;
   12824           0 :                 if (argv_find(argv, argc, "valid", &idx))
   12825             :                         rpki_target_state = RPKI_VALID;
   12826           0 :                 else if (argv_find(argv, argc, "invalid", &idx))
   12827           0 :                         rpki_target_state = RPKI_INVALID;
   12828             :         }
   12829             : 
   12830             :         /* Display prefixes with matching version numbers */
   12831          48 :         if (argv_find(argv, argc, "version", &idx)) {
   12832           0 :                 sh_type = bgp_show_type_prefix_version;
   12833           0 :                 output_arg = argv[idx + 1]->arg;
   12834             :         }
   12835             : 
   12836             :         /* Display prefixes with matching BGP community alias */
   12837          48 :         if (argv_find(argv, argc, "alias", &idx)) {
   12838           0 :                 sh_type = bgp_show_type_community_alias;
   12839           0 :                 output_arg = argv[idx + 1]->arg;
   12840             :         }
   12841             : 
   12842             :         /* prefix-longer */
   12843          48 :         if (argv_find(argv, argc, "A.B.C.D/M", &idx)
   12844          48 :             || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
   12845           0 :                 const char *prefix_str = argv[idx]->arg;
   12846             : 
   12847           0 :                 if (!str2prefix(prefix_str, &p)) {
   12848           0 :                         vty_out(vty, "%% Malformed Prefix\n");
   12849           0 :                         return CMD_WARNING;
   12850             :                 }
   12851             : 
   12852             :                 sh_type = bgp_show_type_prefix_longer;
   12853             :                 output_arg = &p;
   12854             :         }
   12855             : 
   12856          48 :         if (!all) {
   12857             :                 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
   12858          48 :                 if (community)
   12859           0 :                         return bgp_show_community(vty, bgp, community,
   12860             :                                                   exact_match, afi, safi,
   12861             :                                                   show_flags);
   12862             :                 else
   12863          48 :                         return bgp_show(vty, bgp, afi, safi, sh_type,
   12864             :                                         output_arg, show_flags,
   12865             :                                         rpki_target_state);
   12866             :         } else {
   12867           0 :                 struct listnode *node;
   12868           0 :                 struct bgp *abgp;
   12869             :                 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
   12870             :                  * AFI_IP6 */
   12871             : 
   12872           0 :                 if (uj)
   12873           0 :                         vty_out(vty, "{\n");
   12874             : 
   12875           0 :                 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
   12876             :                     || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
   12877           0 :                         afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
   12878             :                                       ? AFI_IP
   12879           0 :                                       : AFI_IP6;
   12880           0 :                         for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
   12881           0 :                                 FOREACH_SAFI (safi) {
   12882           0 :                                         if (!bgp_afi_safi_peer_exists(abgp, afi,
   12883             :                                                                       safi))
   12884           0 :                                                 continue;
   12885             : 
   12886           0 :                                         if (uj) {
   12887           0 :                                                 if (first)
   12888             :                                                         first = false;
   12889             :                                                 else
   12890           0 :                                                         vty_out(vty, ",\n");
   12891           0 :                                                 vty_out(vty, "\"%s\":{\n",
   12892             :                                                         get_afi_safi_str(afi,
   12893             :                                                                          safi,
   12894             :                                                                          true));
   12895             :                                         } else
   12896           0 :                                                 vty_out(vty,
   12897             :                                                         "\nFor address family: %s\n",
   12898             :                                                         get_afi_safi_str(
   12899             :                                                                 afi, safi,
   12900             :                                                                 false));
   12901             : 
   12902           0 :                                         if (community)
   12903           0 :                                                 bgp_show_community(
   12904             :                                                         vty, abgp, community,
   12905             :                                                         exact_match, afi, safi,
   12906             :                                                         show_flags);
   12907             :                                         else
   12908           0 :                                                 bgp_show(vty, abgp, afi, safi,
   12909             :                                                          sh_type, output_arg,
   12910             :                                                          show_flags,
   12911             :                                                          rpki_target_state);
   12912           0 :                                         if (uj)
   12913           0 :                                                 vty_out(vty, "}\n");
   12914             :                                 }
   12915             :                         }
   12916             :                 } else {
   12917             :                         /* show <ip> bgp all: for each AFI and SAFI*/
   12918           0 :                         for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
   12919           0 :                                 FOREACH_AFI_SAFI (afi, safi) {
   12920           0 :                                         if (!bgp_afi_safi_peer_exists(abgp, afi,
   12921             :                                                                       safi))
   12922           0 :                                                 continue;
   12923             : 
   12924           0 :                                         if (uj) {
   12925           0 :                                                 if (first)
   12926             :                                                         first = false;
   12927             :                                                 else
   12928           0 :                                                         vty_out(vty, ",\n");
   12929             : 
   12930           0 :                                                 vty_out(vty, "\"%s\":{\n",
   12931             :                                                         get_afi_safi_str(afi,
   12932             :                                                                          safi,
   12933             :                                                                          true));
   12934             :                                         } else
   12935           0 :                                                 vty_out(vty,
   12936             :                                                         "\nFor address family: %s\n",
   12937             :                                                         get_afi_safi_str(
   12938             :                                                                 afi, safi,
   12939             :                                                                 false));
   12940             : 
   12941           0 :                                         if (community)
   12942           0 :                                                 bgp_show_community(
   12943             :                                                         vty, abgp, community,
   12944             :                                                         exact_match, afi, safi,
   12945             :                                                         show_flags);
   12946             :                                         else
   12947           0 :                                                 bgp_show(vty, abgp, afi, safi,
   12948             :                                                          sh_type, output_arg,
   12949             :                                                          show_flags,
   12950             :                                                          rpki_target_state);
   12951           0 :                                         if (uj)
   12952           0 :                                                 vty_out(vty, "}\n");
   12953             :                                 }
   12954             :                         }
   12955             :                 }
   12956           0 :                 if (uj)
   12957           0 :                         vty_out(vty, "}\n");
   12958             :         }
   12959             :         return CMD_SUCCESS;
   12960             : }
   12961             : 
   12962           0 : DEFUN (show_ip_bgp_route,
   12963             :        show_ip_bgp_route_cmd,
   12964             :        "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [rpki <valid|invalid|notfound>] [json]",
   12965             :        SHOW_STR
   12966             :        IP_STR
   12967             :        BGP_STR
   12968             :        BGP_INSTANCE_HELP_STR
   12969             :        BGP_AFI_HELP_STR
   12970             :        BGP_SAFI_WITH_LABEL_HELP_STR
   12971             :        "Network in the BGP routing table to display\n"
   12972             :        "IPv4 prefix\n"
   12973             :        "Network in the BGP routing table to display\n"
   12974             :        "IPv6 prefix\n"
   12975             :        "Display only the bestpath\n"
   12976             :        "Display only multipaths\n"
   12977             :        "Display only paths that match the specified rpki state\n"
   12978             :        "A valid path as determined by rpki\n"
   12979             :        "A invalid path as determined by rpki\n"
   12980             :        "A path that has no rpki data\n"
   12981             :        JSON_STR)
   12982             : {
   12983           0 :         int prefix_check = 0;
   12984             : 
   12985           0 :         afi_t afi = AFI_IP6;
   12986           0 :         safi_t safi = SAFI_UNICAST;
   12987           0 :         char *prefix = NULL;
   12988           0 :         struct bgp *bgp = NULL;
   12989           0 :         enum bgp_path_type path_type;
   12990           0 :         bool uj = use_json(argc, argv);
   12991             : 
   12992           0 :         int idx = 0;
   12993             : 
   12994           0 :         bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
   12995             :                                             &bgp, uj);
   12996           0 :         if (!idx)
   12997             :                 return CMD_WARNING;
   12998             : 
   12999           0 :         if (!bgp) {
   13000           0 :                 vty_out(vty,
   13001             :                         "Specified 'all' vrf's but this command currently only works per view/vrf\n");
   13002           0 :                 return CMD_WARNING;
   13003             :         }
   13004             : 
   13005             :         /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
   13006           0 :         if (argv_find(argv, argc, "A.B.C.D", &idx)
   13007           0 :             || argv_find(argv, argc, "X:X::X:X", &idx))
   13008             :                 prefix_check = 0;
   13009           0 :         else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
   13010           0 :                  || argv_find(argv, argc, "X:X::X:X/M", &idx))
   13011             :                 prefix_check = 1;
   13012             : 
   13013           0 :         if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
   13014           0 :             && afi != AFI_IP6) {
   13015           0 :                 vty_out(vty,
   13016             :                         "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
   13017           0 :                 return CMD_WARNING;
   13018             :         }
   13019           0 :         if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
   13020           0 :             && afi != AFI_IP) {
   13021           0 :                 vty_out(vty,
   13022             :                         "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
   13023           0 :                 return CMD_WARNING;
   13024             :         }
   13025             : 
   13026           0 :         prefix = argv[idx]->arg;
   13027             : 
   13028             :         /* [<bestpath|multipath>] */
   13029           0 :         if (argv_find(argv, argc, "bestpath", &idx))
   13030             :                 path_type = BGP_PATH_SHOW_BESTPATH;
   13031           0 :         else if (argv_find(argv, argc, "multipath", &idx))
   13032             :                 path_type = BGP_PATH_SHOW_MULTIPATH;
   13033             :         else
   13034           0 :                 path_type = BGP_PATH_SHOW_ALL;
   13035             : 
   13036           0 :         return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
   13037             :                               path_type, RPKI_NOT_BEING_USED, uj);
   13038             : }
   13039             : 
   13040           0 : DEFUN (show_ip_bgp_regexp,
   13041             :        show_ip_bgp_regexp_cmd,
   13042             :        "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
   13043             :        SHOW_STR
   13044             :        IP_STR
   13045             :        BGP_STR
   13046             :        BGP_INSTANCE_HELP_STR
   13047             :        BGP_AFI_HELP_STR
   13048             :        BGP_SAFI_WITH_LABEL_HELP_STR
   13049             :        "Display routes matching the AS path regular expression\n"
   13050             :        "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
   13051             :        JSON_STR)
   13052             : {
   13053           0 :         afi_t afi = AFI_IP6;
   13054           0 :         safi_t safi = SAFI_UNICAST;
   13055           0 :         struct bgp *bgp = NULL;
   13056           0 :         bool uj = use_json(argc, argv);
   13057           0 :         char *regstr = NULL;
   13058             : 
   13059           0 :         int idx = 0;
   13060           0 :         bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
   13061             :                                             &bgp, false);
   13062           0 :         if (!idx)
   13063             :                 return CMD_WARNING;
   13064             : 
   13065             :         // get index of regex
   13066           0 :         if (argv_find(argv, argc, "REGEX", &idx))
   13067           0 :                 regstr = argv[idx]->arg;
   13068             : 
   13069           0 :         assert(regstr);
   13070           0 :         return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
   13071             :                                  bgp_show_type_regexp, uj);
   13072             : }
   13073             : 
   13074           0 : DEFPY (show_ip_bgp_instance_all,
   13075             :        show_ip_bgp_instance_all_cmd,
   13076             :        "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
   13077             :        SHOW_STR
   13078             :        IP_STR
   13079             :        BGP_STR
   13080             :        BGP_INSTANCE_ALL_HELP_STR
   13081             :        BGP_AFI_HELP_STR
   13082             :        BGP_SAFI_WITH_LABEL_HELP_STR
   13083             :        JSON_STR
   13084             :       "Increase table width for longer prefixes\n")
   13085             : {
   13086           0 :         afi_t afi = AFI_IP6;
   13087           0 :         safi_t safi = SAFI_UNICAST;
   13088           0 :         struct bgp *bgp = NULL;
   13089           0 :         int idx = 0;
   13090           0 :         uint16_t show_flags = 0;
   13091             : 
   13092           0 :         if (uj) {
   13093           0 :                 argc--;
   13094           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
   13095             :         }
   13096             : 
   13097           0 :         if (wide)
   13098           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
   13099             : 
   13100           0 :         bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
   13101             :                                             &bgp, uj);
   13102           0 :         if (!idx)
   13103             :                 return CMD_WARNING;
   13104             : 
   13105           0 :         bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
   13106           0 :         return CMD_SUCCESS;
   13107             : }
   13108             : 
   13109           0 : static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
   13110             :                            afi_t afi, safi_t safi, enum bgp_show_type type,
   13111             :                            bool use_json)
   13112             : {
   13113           0 :         regex_t *regex;
   13114           0 :         int rc;
   13115           0 :         uint16_t show_flags = 0;
   13116             : 
   13117           0 :         if (use_json)
   13118           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
   13119             : 
   13120           0 :         if (!config_bgp_aspath_validate(regstr)) {
   13121           0 :                 vty_out(vty, "Invalid character in REGEX %s\n",
   13122             :                         regstr);
   13123           0 :                 return CMD_WARNING_CONFIG_FAILED;
   13124             :         }
   13125             : 
   13126           0 :         regex = bgp_regcomp(regstr);
   13127           0 :         if (!regex) {
   13128           0 :                 vty_out(vty, "Can't compile regexp %s\n", regstr);
   13129           0 :                 return CMD_WARNING;
   13130             :         }
   13131             : 
   13132           0 :         rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
   13133             :                       RPKI_NOT_BEING_USED);
   13134           0 :         bgp_regex_free(regex);
   13135           0 :         return rc;
   13136             : }
   13137             : 
   13138           0 : static int bgp_show_community(struct vty *vty, struct bgp *bgp,
   13139             :                               const char *comstr, int exact, afi_t afi,
   13140             :                               safi_t safi, uint16_t show_flags)
   13141             : {
   13142           0 :         struct community *com;
   13143           0 :         int ret = 0;
   13144             : 
   13145           0 :         com = community_str2com(comstr);
   13146           0 :         if (!com) {
   13147           0 :                 vty_out(vty, "%% Community malformed: %s\n", comstr);
   13148           0 :                 return CMD_WARNING;
   13149             :         }
   13150             : 
   13151           0 :         ret = bgp_show(vty, bgp, afi, safi,
   13152             :                        (exact ? bgp_show_type_community_exact
   13153             :                               : bgp_show_type_community),
   13154             :                        com, show_flags, RPKI_NOT_BEING_USED);
   13155           0 :         community_free(&com);
   13156             : 
   13157           0 :         return ret;
   13158             : }
   13159             : 
   13160             : enum bgp_stats {
   13161             :         BGP_STATS_MAXBITLEN = 0,
   13162             :         BGP_STATS_RIB,
   13163             :         BGP_STATS_PREFIXES,
   13164             :         BGP_STATS_TOTPLEN,
   13165             :         BGP_STATS_UNAGGREGATEABLE,
   13166             :         BGP_STATS_MAX_AGGREGATEABLE,
   13167             :         BGP_STATS_AGGREGATES,
   13168             :         BGP_STATS_SPACE,
   13169             :         BGP_STATS_ASPATH_COUNT,
   13170             :         BGP_STATS_ASPATH_MAXHOPS,
   13171             :         BGP_STATS_ASPATH_TOTHOPS,
   13172             :         BGP_STATS_ASPATH_MAXSIZE,
   13173             :         BGP_STATS_ASPATH_TOTSIZE,
   13174             :         BGP_STATS_ASN_HIGHEST,
   13175             :         BGP_STATS_MAX,
   13176             : };
   13177             : 
   13178             : #define TABLE_STATS_IDX_VTY 0
   13179             : #define TABLE_STATS_IDX_JSON 1
   13180             : 
   13181             : static const char *table_stats_strs[][2] = {
   13182             :         [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
   13183             :         [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
   13184             :         [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
   13185             :         [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
   13186             :                                        "unaggregateablePrefixes"},
   13187             :         [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
   13188             :                                          "maximumAggregateablePrefixes"},
   13189             :         [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
   13190             :                                   "bgpAggregateAdvertisements"},
   13191             :         [BGP_STATS_SPACE] = {"Address space advertised",
   13192             :                              "addressSpaceAdvertised"},
   13193             :         [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
   13194             :                                     "advertisementsWithPaths"},
   13195             :         [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
   13196             :                                       "longestAsPath"},
   13197             :         [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
   13198             :                                       "largestAsPath"},
   13199             :         [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
   13200             :                                       "averageAsPathLengthHops"},
   13201             :         [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
   13202             :                                       "averageAsPathSizeBytes"},
   13203             :         [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
   13204             :         [BGP_STATS_MAX] = {NULL, NULL}
   13205             : };
   13206             : 
   13207             : struct bgp_table_stats {
   13208             :         struct bgp_table *table;
   13209             :         unsigned long long counts[BGP_STATS_MAX];
   13210             : 
   13211             :         unsigned long long
   13212             :                 prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
   13213             :                                  1];
   13214             : 
   13215             :         double total_space;
   13216             : };
   13217             : 
   13218           0 : static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
   13219             :                                struct bgp_table_stats *ts, unsigned int space)
   13220             : {
   13221           0 :         struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
   13222           0 :         struct bgp_path_info *pi;
   13223           0 :         const struct prefix *rn_p;
   13224             : 
   13225           0 :         if (!bgp_dest_has_bgp_path_info_data(dest))
   13226             :                 return;
   13227             : 
   13228           0 :         rn_p = bgp_dest_get_prefix(dest);
   13229           0 :         ts->counts[BGP_STATS_PREFIXES]++;
   13230           0 :         ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
   13231             : 
   13232           0 :         ts->prefix_len_count[rn_p->prefixlen]++;
   13233             :         /* check if the prefix is included by any other announcements */
   13234           0 :         while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
   13235           0 :                 pdest = bgp_dest_parent_nolock(pdest);
   13236             : 
   13237           0 :         if (pdest == NULL || pdest == top) {
   13238           0 :                 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
   13239             :                 /* announced address space */
   13240           0 :                 if (space)
   13241           0 :                         ts->total_space += pow(2.0, space - rn_p->prefixlen);
   13242           0 :         } else if (bgp_dest_has_bgp_path_info_data(pdest))
   13243           0 :                 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
   13244             : 
   13245             : 
   13246           0 :         for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
   13247           0 :                 ts->counts[BGP_STATS_RIB]++;
   13248             : 
   13249           0 :                 if (CHECK_FLAG(pi->attr->flag,
   13250             :                                ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
   13251           0 :                         ts->counts[BGP_STATS_AGGREGATES]++;
   13252             : 
   13253             :                 /* as-path stats */
   13254           0 :                 if (pi->attr->aspath) {
   13255           0 :                         unsigned int hops = aspath_count_hops(pi->attr->aspath);
   13256           0 :                         unsigned int size = aspath_size(pi->attr->aspath);
   13257           0 :                         as_t highest = aspath_highest(pi->attr->aspath);
   13258             : 
   13259           0 :                         ts->counts[BGP_STATS_ASPATH_COUNT]++;
   13260             : 
   13261           0 :                         if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
   13262           0 :                                 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
   13263             : 
   13264           0 :                         if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
   13265           0 :                                 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
   13266             : 
   13267           0 :                         ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
   13268           0 :                         ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
   13269           0 :                         if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
   13270           0 :                                 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
   13271             :                 }
   13272             :         }
   13273             : }
   13274             : 
   13275           0 : static void bgp_table_stats_walker(struct thread *t)
   13276             : {
   13277           0 :         struct bgp_dest *dest, *ndest;
   13278           0 :         struct bgp_dest *top;
   13279           0 :         struct bgp_table_stats *ts = THREAD_ARG(t);
   13280           0 :         unsigned int space = 0;
   13281             : 
   13282           0 :         if (!(top = bgp_table_top(ts->table)))
   13283             :                 return;
   13284             : 
   13285           0 :         switch (ts->table->afi) {
   13286           0 :         case AFI_IP:
   13287           0 :                 space = IPV4_MAX_BITLEN;
   13288           0 :                 break;
   13289           0 :         case AFI_IP6:
   13290           0 :                 space = IPV6_MAX_BITLEN;
   13291           0 :                 break;
   13292           0 :         case AFI_L2VPN:
   13293           0 :                 space = EVPN_ROUTE_PREFIXLEN;
   13294           0 :                 break;
   13295             :         case AFI_UNSPEC:
   13296             :         case AFI_MAX:
   13297             :                 return;
   13298             :         }
   13299             : 
   13300           0 :         ts->counts[BGP_STATS_MAXBITLEN] = space;
   13301             : 
   13302           0 :         for (dest = top; dest; dest = bgp_route_next(dest)) {
   13303           0 :                 if (ts->table->safi == SAFI_MPLS_VPN
   13304             :                     || ts->table->safi == SAFI_ENCAP
   13305           0 :                     || ts->table->safi == SAFI_EVPN) {
   13306           0 :                         struct bgp_table *table;
   13307             : 
   13308           0 :                         table = bgp_dest_get_bgp_table_info(dest);
   13309           0 :                         if (!table)
   13310           0 :                                 continue;
   13311             : 
   13312           0 :                         top = bgp_table_top(table);
   13313           0 :                         for (ndest = bgp_table_top(table); ndest;
   13314           0 :                              ndest = bgp_route_next(ndest))
   13315           0 :                                 bgp_table_stats_rn(ndest, top, ts, space);
   13316             :                 } else {
   13317           0 :                         bgp_table_stats_rn(dest, top, ts, space);
   13318             :                 }
   13319             :         }
   13320             : }
   13321             : 
   13322           0 : static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
   13323             :                                 struct json_object *json_array)
   13324             : {
   13325           0 :         struct listnode *node, *nnode;
   13326           0 :         struct bgp *bgp;
   13327             : 
   13328           0 :         for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
   13329           0 :                 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
   13330           0 : }
   13331             : 
   13332           0 : static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
   13333             :                                   safi_t safi, struct json_object *json_array)
   13334             : {
   13335           0 :         struct bgp_table_stats ts;
   13336           0 :         unsigned int i;
   13337           0 :         int ret = CMD_SUCCESS;
   13338           0 :         char temp_buf[20];
   13339           0 :         struct json_object *json = NULL;
   13340           0 :         uint32_t bitlen = 0;
   13341           0 :         struct json_object *json_bitlen;
   13342             : 
   13343           0 :         if (json_array)
   13344           0 :                 json = json_object_new_object();
   13345             : 
   13346           0 :         if (!bgp->rib[afi][safi]) {
   13347           0 :                 char warning_msg[50];
   13348             : 
   13349           0 :                 snprintf(warning_msg, sizeof(warning_msg),
   13350             :                          "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
   13351             :                          safi);
   13352             : 
   13353           0 :                 if (!json)
   13354           0 :                         vty_out(vty, "%s\n", warning_msg);
   13355             :                 else
   13356           0 :                         json_object_string_add(json, "warning", warning_msg);
   13357             : 
   13358           0 :                 ret = CMD_WARNING;
   13359           0 :                 goto end_table_stats;
   13360             :         }
   13361             : 
   13362           0 :         if (!json)
   13363           0 :                 vty_out(vty, "BGP %s RIB statistics (%s)\n",
   13364             :                         get_afi_safi_str(afi, safi, false), bgp->name_pretty);
   13365             :         else
   13366           0 :                 json_object_string_add(json, "instance", bgp->name_pretty);
   13367             : 
   13368             :         /* labeled-unicast routes live in the unicast table */
   13369           0 :         if (safi == SAFI_LABELED_UNICAST)
   13370           0 :                 safi = SAFI_UNICAST;
   13371             : 
   13372           0 :         memset(&ts, 0, sizeof(ts));
   13373           0 :         ts.table = bgp->rib[afi][safi];
   13374           0 :         thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
   13375             : 
   13376           0 :         for (i = 0; i < BGP_STATS_MAX; i++) {
   13377           0 :                 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
   13378           0 :                     || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
   13379           0 :                         continue;
   13380             : 
   13381           0 :                 switch (i) {
   13382           0 :                 case BGP_STATS_ASPATH_TOTHOPS:
   13383             :                 case BGP_STATS_ASPATH_TOTSIZE:
   13384           0 :                         if (!json) {
   13385           0 :                                 snprintf(
   13386             :                                         temp_buf, sizeof(temp_buf), "%12.2f",
   13387           0 :                                         ts.counts[i]
   13388           0 :                                                 ? (float)ts.counts[i]
   13389           0 :                                                           / (float)ts.counts
   13390           0 :                                                                     [BGP_STATS_ASPATH_COUNT]
   13391             :                                                 : 0);
   13392           0 :                                 vty_out(vty, "%-30s: %s",
   13393             :                                         table_stats_strs[i]
   13394             :                                                         [TABLE_STATS_IDX_VTY],
   13395             :                                         temp_buf);
   13396             :                         } else {
   13397           0 :                                 json_object_double_add(
   13398             :                                         json,
   13399             :                                         table_stats_strs[i]
   13400             :                                                         [TABLE_STATS_IDX_JSON],
   13401           0 :                                         ts.counts[i]
   13402           0 :                                                 ? (double)ts.counts[i]
   13403           0 :                                                           / (double)ts.counts
   13404           0 :                                                             [BGP_STATS_ASPATH_COUNT]
   13405             :                                                 : 0);
   13406             :                         }
   13407             :                         break;
   13408           0 :                 case BGP_STATS_TOTPLEN:
   13409           0 :                         if (!json) {
   13410           0 :                                 snprintf(
   13411             :                                         temp_buf, sizeof(temp_buf), "%12.2f",
   13412           0 :                                         ts.counts[i]
   13413           0 :                                                 ? (float)ts.counts[i]
   13414           0 :                                                           / (float)ts.counts
   13415           0 :                                                             [BGP_STATS_PREFIXES]
   13416             :                                                 : 0);
   13417           0 :                                 vty_out(vty, "%-30s: %s",
   13418             :                                         table_stats_strs[i]
   13419             :                                                         [TABLE_STATS_IDX_VTY],
   13420             :                                         temp_buf);
   13421             :                         } else {
   13422           0 :                                 json_object_double_add(
   13423             :                                         json,
   13424             :                                         table_stats_strs[i]
   13425             :                                                         [TABLE_STATS_IDX_JSON],
   13426           0 :                                         ts.counts[i]
   13427           0 :                                                 ? (double)ts.counts[i]
   13428           0 :                                                           / (double)ts.counts
   13429           0 :                                                             [BGP_STATS_PREFIXES]
   13430             :                                                 : 0);
   13431             :                         }
   13432             :                         break;
   13433           0 :                 case BGP_STATS_SPACE:
   13434           0 :                         if (!json) {
   13435           0 :                                 snprintf(temp_buf, sizeof(temp_buf), "%12g",
   13436             :                                          ts.total_space);
   13437           0 :                                 vty_out(vty, "%-30s: %s\n",
   13438             :                                         table_stats_strs[i]
   13439             :                                                         [TABLE_STATS_IDX_VTY],
   13440             :                                         temp_buf);
   13441             :                         } else {
   13442           0 :                                 json_object_double_add(
   13443             :                                         json,
   13444             :                                         table_stats_strs[i]
   13445             :                                                         [TABLE_STATS_IDX_JSON],
   13446             :                                         (double)ts.total_space);
   13447             :                         }
   13448           0 :                         if (afi == AFI_IP6) {
   13449           0 :                                 if (!json) {
   13450           0 :                                         snprintf(temp_buf, sizeof(temp_buf),
   13451             :                                                  "%12g",
   13452           0 :                                                  ts.total_space
   13453             :                                                          * pow(2.0, -128 + 32));
   13454           0 :                                         vty_out(vty, "%30s: %s\n",
   13455             :                                                 "/32 equivalent %s\n",
   13456             :                                                 temp_buf);
   13457             :                                 } else {
   13458           0 :                                         json_object_double_add(
   13459             :                                                 json, "/32equivalent",
   13460           0 :                                                 (double)(ts.total_space
   13461             :                                                          * pow(2.0,
   13462             :                                                                -128 + 32)));
   13463             :                                 }
   13464           0 :                                 if (!json) {
   13465           0 :                                         snprintf(temp_buf, sizeof(temp_buf),
   13466             :                                                  "%12g",
   13467           0 :                                                  ts.total_space
   13468             :                                                          * pow(2.0, -128 + 48));
   13469           0 :                                         vty_out(vty, "%30s: %s\n",
   13470             :                                                 "/48 equivalent %s\n",
   13471             :                                                 temp_buf);
   13472             :                                 } else {
   13473           0 :                                         json_object_double_add(
   13474             :                                                 json, "/48equivalent",
   13475           0 :                                                 (double)(ts.total_space
   13476             :                                                          * pow(2.0,
   13477             :                                                                -128 + 48)));
   13478             :                                 }
   13479             :                         } else {
   13480           0 :                                 if (!json) {
   13481           0 :                                         snprintf(temp_buf, sizeof(temp_buf),
   13482             :                                                  "%12.2f",
   13483           0 :                                                  ts.total_space * 100.
   13484             :                                                          * pow(2.0, -32));
   13485           0 :                                         vty_out(vty, "%30s: %s\n",
   13486             :                                                 "% announced ", temp_buf);
   13487             :                                 } else {
   13488           0 :                                         json_object_double_add(
   13489             :                                                 json, "%announced",
   13490           0 :                                                 (double)(ts.total_space * 100.
   13491             :                                                          * pow(2.0, -32)));
   13492             :                                 }
   13493           0 :                                 if (!json) {
   13494           0 :                                         snprintf(temp_buf, sizeof(temp_buf),
   13495             :                                                  "%12.2f",
   13496           0 :                                                  ts.total_space
   13497             :                                                          * pow(2.0, -32 + 8));
   13498           0 :                                         vty_out(vty, "%30s: %s\n",
   13499             :                                                 "/8 equivalent ", temp_buf);
   13500             :                                 } else {
   13501           0 :                                         json_object_double_add(
   13502             :                                                 json, "/8equivalent",
   13503           0 :                                                 (double)(ts.total_space
   13504             :                                                          * pow(2.0, -32 + 8)));
   13505             :                                 }
   13506           0 :                                 if (!json) {
   13507           0 :                                         snprintf(temp_buf, sizeof(temp_buf),
   13508             :                                                  "%12.2f",
   13509           0 :                                                  ts.total_space
   13510             :                                                          * pow(2.0, -32 + 24));
   13511           0 :                                         vty_out(vty, "%30s: %s\n",
   13512             :                                                 "/24 equivalent ", temp_buf);
   13513             :                                 } else {
   13514           0 :                                         json_object_double_add(
   13515             :                                                 json, "/24equivalent",
   13516           0 :                                                 (double)(ts.total_space
   13517             :                                                          * pow(2.0, -32 + 24)));
   13518             :                                 }
   13519             :                         }
   13520             :                         break;
   13521           0 :                 default:
   13522           0 :                         if (!json) {
   13523           0 :                                 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
   13524             :                                          ts.counts[i]);
   13525           0 :                                 vty_out(vty, "%-30s: %s",
   13526             :                                         table_stats_strs[i]
   13527             :                                                         [TABLE_STATS_IDX_VTY],
   13528             :                                         temp_buf);
   13529             :                         } else {
   13530           0 :                                 json_object_int_add(
   13531             :                                         json,
   13532             :                                         table_stats_strs[i]
   13533             :                                                         [TABLE_STATS_IDX_JSON],
   13534           0 :                                         ts.counts[i]);
   13535             :                         }
   13536             :                 }
   13537           0 :                 if (!json)
   13538           0 :                         vty_out(vty, "\n");
   13539             :         }
   13540             : 
   13541           0 :         switch (afi) {
   13542             :         case AFI_IP:
   13543             :                 bitlen = IPV4_MAX_BITLEN;
   13544             :                 break;
   13545             :         case AFI_IP6:
   13546             :                 bitlen = IPV6_MAX_BITLEN;
   13547             :                 break;
   13548             :         case AFI_L2VPN:
   13549             :                 bitlen = EVPN_ROUTE_PREFIXLEN;
   13550             :                 break;
   13551             :         case AFI_UNSPEC:
   13552             :         case AFI_MAX:
   13553             :                 break;
   13554             :         }
   13555             : 
   13556           0 :         if (json) {
   13557           0 :                 json_bitlen = json_object_new_array();
   13558             : 
   13559           0 :                 for (i = 0; i <= bitlen; i++) {
   13560           0 :                         struct json_object *ind_bit = json_object_new_object();
   13561             : 
   13562           0 :                         if (!ts.prefix_len_count[i])
   13563           0 :                                 continue;
   13564             : 
   13565           0 :                         snprintf(temp_buf, sizeof(temp_buf), "%u", i);
   13566           0 :                         json_object_int_add(ind_bit, temp_buf,
   13567           0 :                                             ts.prefix_len_count[i]);
   13568           0 :                         json_object_array_add(json_bitlen, ind_bit);
   13569             :                 }
   13570           0 :                 json_object_object_add(json, "prefixLength", json_bitlen);
   13571             :         }
   13572             : 
   13573           0 : end_table_stats:
   13574           0 :         if (json)
   13575           0 :                 json_object_array_add(json_array, json);
   13576           0 :         return ret;
   13577             : }
   13578             : 
   13579           0 : static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
   13580             :                            safi_t safi, struct json_object *json_array)
   13581             : {
   13582           0 :         if (!bgp) {
   13583           0 :                 bgp_table_stats_all(vty, afi, safi, json_array);
   13584           0 :                 return CMD_SUCCESS;
   13585             :         }
   13586             : 
   13587           0 :         return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
   13588             : }
   13589             : 
   13590             : enum bgp_pcounts {
   13591             :         PCOUNT_ADJ_IN = 0,
   13592             :         PCOUNT_DAMPED,
   13593             :         PCOUNT_REMOVED,
   13594             :         PCOUNT_HISTORY,
   13595             :         PCOUNT_STALE,
   13596             :         PCOUNT_VALID,
   13597             :         PCOUNT_ALL,
   13598             :         PCOUNT_COUNTED,
   13599             :         PCOUNT_BPATH_SELECTED,
   13600             :         PCOUNT_PFCNT, /* the figure we display to users */
   13601             :         PCOUNT_MAX,
   13602             : };
   13603             : 
   13604             : static const char *const pcount_strs[] = {
   13605             :                 [PCOUNT_ADJ_IN] = "Adj-in",
   13606             :                 [PCOUNT_DAMPED] = "Damped",
   13607             :                 [PCOUNT_REMOVED] = "Removed",
   13608             :                 [PCOUNT_HISTORY] = "History",
   13609             :                 [PCOUNT_STALE] = "Stale",
   13610             :                 [PCOUNT_VALID] = "Valid",
   13611             :                 [PCOUNT_ALL] = "All RIB",
   13612             :                 [PCOUNT_COUNTED] = "PfxCt counted",
   13613             :                 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
   13614             :                 [PCOUNT_PFCNT] = "Useable",
   13615             :                 [PCOUNT_MAX] = NULL,
   13616             : };
   13617             : 
   13618             : struct peer_pcounts {
   13619             :         unsigned int count[PCOUNT_MAX];
   13620             :         const struct peer *peer;
   13621             :         const struct bgp_table *table;
   13622             :         safi_t safi;
   13623             : };
   13624             : 
   13625           0 : static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
   13626             : {
   13627           0 :         const struct bgp_adj_in *ain;
   13628           0 :         const struct bgp_path_info *pi;
   13629           0 :         const struct peer *peer = pc->peer;
   13630             : 
   13631           0 :         for (ain = rn->adj_in; ain; ain = ain->next)
   13632           0 :                 if (ain->peer == peer)
   13633           0 :                         pc->count[PCOUNT_ADJ_IN]++;
   13634             : 
   13635           0 :         for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
   13636             : 
   13637           0 :                 if (pi->peer != peer)
   13638           0 :                         continue;
   13639             : 
   13640           0 :                 pc->count[PCOUNT_ALL]++;
   13641             : 
   13642           0 :                 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
   13643           0 :                         pc->count[PCOUNT_DAMPED]++;
   13644           0 :                 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
   13645           0 :                         pc->count[PCOUNT_HISTORY]++;
   13646           0 :                 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
   13647           0 :                         pc->count[PCOUNT_REMOVED]++;
   13648           0 :                 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
   13649           0 :                         pc->count[PCOUNT_STALE]++;
   13650           0 :                 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
   13651           0 :                         pc->count[PCOUNT_VALID]++;
   13652           0 :                 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
   13653           0 :                         pc->count[PCOUNT_PFCNT]++;
   13654           0 :                 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
   13655           0 :                         pc->count[PCOUNT_BPATH_SELECTED]++;
   13656             : 
   13657           0 :                 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
   13658           0 :                         pc->count[PCOUNT_COUNTED]++;
   13659           0 :                         if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
   13660           0 :                                 flog_err(
   13661             :                                         EC_LIB_DEVELOPMENT,
   13662             :                                         "Attempting to count but flags say it is unusable");
   13663             :                 } else {
   13664           0 :                         if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
   13665           0 :                                 flog_err(
   13666             :                                         EC_LIB_DEVELOPMENT,
   13667             :                                         "Not counted but flags say we should");
   13668             :                 }
   13669             :         }
   13670           0 : }
   13671             : 
   13672           0 : static void bgp_peer_count_walker(struct thread *t)
   13673             : {
   13674           0 :         struct bgp_dest *rn, *rm;
   13675           0 :         const struct bgp_table *table;
   13676           0 :         struct peer_pcounts *pc = THREAD_ARG(t);
   13677             : 
   13678           0 :         if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
   13679           0 :             || pc->safi == SAFI_EVPN) {
   13680             :                 /* Special handling for 2-level routing tables. */
   13681           0 :                 for (rn = bgp_table_top(pc->table); rn;
   13682           0 :                      rn = bgp_route_next(rn)) {
   13683           0 :                         table = bgp_dest_get_bgp_table_info(rn);
   13684           0 :                         if (table != NULL)
   13685           0 :                                 for (rm = bgp_table_top(table); rm;
   13686           0 :                                      rm = bgp_route_next(rm))
   13687           0 :                                         bgp_peer_count_proc(rm, pc);
   13688             :                 }
   13689             :         } else
   13690           0 :                 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
   13691           0 :                         bgp_peer_count_proc(rn, pc);
   13692           0 : }
   13693             : 
   13694           0 : static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
   13695             :                            safi_t safi, bool use_json)
   13696             : {
   13697           0 :         struct peer_pcounts pcounts = {.peer = peer};
   13698           0 :         unsigned int i;
   13699           0 :         json_object *json = NULL;
   13700           0 :         json_object *json_loop = NULL;
   13701             : 
   13702           0 :         if (use_json) {
   13703           0 :                 json = json_object_new_object();
   13704           0 :                 json_loop = json_object_new_object();
   13705             :         }
   13706             : 
   13707           0 :         if (!peer || !peer->bgp || !peer->afc[afi][safi]
   13708           0 :             || !peer->bgp->rib[afi][safi]) {
   13709           0 :                 if (use_json) {
   13710           0 :                         json_object_string_add(
   13711             :                                 json, "warning",
   13712             :                                 "No such neighbor or address family");
   13713           0 :                         vty_out(vty, "%s\n", json_object_to_json_string(json));
   13714           0 :                         json_object_free(json);
   13715           0 :                         json_object_free(json_loop);
   13716             :                 } else
   13717           0 :                         vty_out(vty, "%% No such neighbor or address family\n");
   13718             : 
   13719           0 :                 return CMD_WARNING;
   13720             :         }
   13721             : 
   13722           0 :         memset(&pcounts, 0, sizeof(pcounts));
   13723           0 :         pcounts.peer = peer;
   13724           0 :         pcounts.table = peer->bgp->rib[afi][safi];
   13725           0 :         pcounts.safi = safi;
   13726             : 
   13727             :         /* in-place call via thread subsystem so as to record execution time
   13728             :          * stats for the thread-walk (i.e. ensure this can't be blamed on
   13729             :          * on just vty_read()).
   13730             :          */
   13731           0 :         thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
   13732             : 
   13733           0 :         if (use_json) {
   13734           0 :                 json_object_string_add(json, "prefixCountsFor", peer->host);
   13735           0 :                 json_object_string_add(json, "multiProtocol",
   13736             :                                        get_afi_safi_str(afi, safi, true));
   13737           0 :                 json_object_int_add(json, "pfxCounter",
   13738           0 :                                     peer->pcount[afi][safi]);
   13739             : 
   13740           0 :                 for (i = 0; i < PCOUNT_MAX; i++)
   13741           0 :                         json_object_int_add(json_loop, pcount_strs[i],
   13742           0 :                                             pcounts.count[i]);
   13743             : 
   13744           0 :                 json_object_object_add(json, "ribTableWalkCounters", json_loop);
   13745             : 
   13746           0 :                 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
   13747           0 :                         json_object_string_add(json, "pfxctDriftFor",
   13748           0 :                                                peer->host);
   13749           0 :                         json_object_string_add(
   13750             :                                 json, "recommended",
   13751             :                                 "Please report this bug, with the above command output");
   13752             :                 }
   13753           0 :                 vty_json(vty, json);
   13754             :         } else {
   13755             : 
   13756           0 :                 if (peer->hostname
   13757           0 :                     && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
   13758           0 :                         vty_out(vty, "Prefix counts for %s/%s, %s\n",
   13759             :                                 peer->hostname, peer->host,
   13760             :                                 get_afi_safi_str(afi, safi, false));
   13761             :                 } else {
   13762           0 :                         vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
   13763             :                                 get_afi_safi_str(afi, safi, false));
   13764             :                 }
   13765             : 
   13766           0 :                 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
   13767           0 :                 vty_out(vty, "\nCounts from RIB table walk:\n\n");
   13768             : 
   13769           0 :                 for (i = 0; i < PCOUNT_MAX; i++)
   13770           0 :                         vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
   13771             :                                 pcounts.count[i]);
   13772             : 
   13773           0 :                 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
   13774           0 :                         vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
   13775           0 :                         vty_out(vty,
   13776             :                                 "Please report this bug, with the above command output\n");
   13777             :                 }
   13778             :         }
   13779             : 
   13780             :         return CMD_SUCCESS;
   13781             : }
   13782             : 
   13783           0 : DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
   13784             :        show_ip_bgp_instance_neighbor_prefix_counts_cmd,
   13785             :        "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
   13786             :        SHOW_STR
   13787             :        IP_STR
   13788             :        BGP_STR
   13789             :        BGP_INSTANCE_HELP_STR
   13790             :        BGP_AFI_HELP_STR
   13791             :        BGP_SAFI_HELP_STR
   13792             :        "Detailed information on TCP and BGP neighbor connections\n"
   13793             :        "Neighbor to display information about\n"
   13794             :        "Neighbor to display information about\n"
   13795             :        "Neighbor on BGP configured interface\n"
   13796             :        "Display detailed prefix count information\n"
   13797             :        JSON_STR)
   13798             : {
   13799           0 :         afi_t afi = AFI_IP6;
   13800           0 :         safi_t safi = SAFI_UNICAST;
   13801           0 :         struct peer *peer;
   13802           0 :         int idx = 0;
   13803           0 :         struct bgp *bgp = NULL;
   13804           0 :         bool uj = use_json(argc, argv);
   13805             : 
   13806           0 :         if (uj)
   13807           0 :                 argc--;
   13808             : 
   13809           0 :         bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
   13810             :                                             &bgp, uj);
   13811           0 :         if (!idx)
   13812             :                 return CMD_WARNING;
   13813             : 
   13814           0 :         argv_find(argv, argc, "neighbors", &idx);
   13815           0 :         peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
   13816           0 :         if (!peer)
   13817             :                 return CMD_WARNING;
   13818             : 
   13819           0 :         return bgp_peer_counts(vty, peer, afi, safi, uj);
   13820             : }
   13821             : 
   13822             : #ifdef KEEP_OLD_VPN_COMMANDS
   13823             : DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
   13824             :        show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
   13825             :        "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
   13826             :        SHOW_STR
   13827             :        IP_STR
   13828             :        BGP_STR
   13829             :        BGP_VPNVX_HELP_STR
   13830             :        "Display information about all VPNv4 NLRIs\n"
   13831             :        "Detailed information on TCP and BGP neighbor connections\n"
   13832             :        "Neighbor to display information about\n"
   13833             :        "Neighbor to display information about\n"
   13834             :        "Neighbor on BGP configured interface\n"
   13835             :        "Display detailed prefix count information\n"
   13836             :        JSON_STR)
   13837             : {
   13838             :         int idx_peer = 6;
   13839             :         struct peer *peer;
   13840             :         bool uj = use_json(argc, argv);
   13841             : 
   13842             :         peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
   13843             :         if (!peer)
   13844             :                 return CMD_WARNING;
   13845             : 
   13846             :         return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
   13847             : }
   13848             : 
   13849             : DEFUN (show_ip_bgp_vpn_all_route_prefix,
   13850             :        show_ip_bgp_vpn_all_route_prefix_cmd,
   13851             :        "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
   13852             :        SHOW_STR
   13853             :        IP_STR
   13854             :        BGP_STR
   13855             :        BGP_VPNVX_HELP_STR
   13856             :        "Display information about all VPNv4 NLRIs\n"
   13857             :        "Network in the BGP routing table to display\n"
   13858             :        "Network in the BGP routing table to display\n"
   13859             :        JSON_STR)
   13860             : {
   13861             :         int idx = 0;
   13862             :         char *network = NULL;
   13863             :         struct bgp *bgp = bgp_get_default();
   13864             :         if (!bgp) {
   13865             :                 vty_out(vty, "Can't find default instance\n");
   13866             :                 return CMD_WARNING;
   13867             :         }
   13868             : 
   13869             :         if (argv_find(argv, argc, "A.B.C.D", &idx))
   13870             :                 network = argv[idx]->arg;
   13871             :         else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
   13872             :                 network = argv[idx]->arg;
   13873             :         else {
   13874             :                 vty_out(vty, "Unable to figure out Network\n");
   13875             :                 return CMD_WARNING;
   13876             :         }
   13877             : 
   13878             :         return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
   13879             :                               BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
   13880             :                               use_json(argc, argv));
   13881             : }
   13882             : #endif /* KEEP_OLD_VPN_COMMANDS */
   13883             : 
   13884           0 : DEFUN (show_bgp_l2vpn_evpn_route_prefix,
   13885             :        show_bgp_l2vpn_evpn_route_prefix_cmd,
   13886             :        "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
   13887             :        SHOW_STR
   13888             :        BGP_STR
   13889             :        L2VPN_HELP_STR
   13890             :        EVPN_HELP_STR
   13891             :        "Network in the BGP routing table to display\n"
   13892             :        "Network in the BGP routing table to display\n"
   13893             :        "Network in the BGP routing table to display\n"
   13894             :        "Network in the BGP routing table to display\n"
   13895             :        JSON_STR)
   13896             : {
   13897           0 :         int idx = 0;
   13898           0 :         char *network = NULL;
   13899           0 :         int prefix_check = 0;
   13900             : 
   13901           0 :         if (argv_find(argv, argc, "A.B.C.D", &idx) ||
   13902           0 :                 argv_find(argv, argc, "X:X::X:X", &idx))
   13903           0 :                 network = argv[idx]->arg;
   13904           0 :         else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
   13905           0 :                 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
   13906           0 :                 network = argv[idx]->arg;
   13907           0 :                 prefix_check = 1;
   13908             :         } else {
   13909           0 :                 vty_out(vty, "Unable to figure out Network\n");
   13910           0 :                 return CMD_WARNING;
   13911             :         }
   13912           0 :         return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
   13913             :                               prefix_check, BGP_PATH_SHOW_ALL,
   13914           0 :                               RPKI_NOT_BEING_USED, use_json(argc, argv));
   13915             : }
   13916             : 
   13917           0 : static void show_adj_route_header(struct vty *vty, struct peer *peer,
   13918             :                                   struct bgp_table *table, int *header1,
   13919             :                                   int *header2, json_object *json,
   13920             :                                   json_object *json_scode,
   13921             :                                   json_object *json_ocode, bool wide,
   13922             :                                   bool detail)
   13923             : {
   13924           0 :         uint64_t version = table ? table->version : 0;
   13925             : 
   13926           0 :         if (*header1) {
   13927           0 :                 if (json) {
   13928           0 :                         json_object_int_add(json, "bgpTableVersion", version);
   13929           0 :                         json_object_string_addf(json, "bgpLocalRouterId",
   13930           0 :                                                 "%pI4", &peer->bgp->router_id);
   13931           0 :                         json_object_int_add(json, "defaultLocPrf",
   13932           0 :                                             peer->bgp->default_local_pref);
   13933           0 :                         json_object_int_add(json, "localAS",
   13934           0 :                                             peer->change_local_as
   13935             :                                                     ? peer->change_local_as
   13936           0 :                                                     : peer->local_as);
   13937           0 :                         json_object_object_add(json, "bgpStatusCodes",
   13938             :                                                json_scode);
   13939           0 :                         json_object_object_add(json, "bgpOriginCodes",
   13940             :                                                json_ocode);
   13941             :                 } else {
   13942           0 :                         vty_out(vty,
   13943             :                                 "BGP table version is %" PRIu64
   13944             :                                 ", local router ID is %pI4, vrf id ",
   13945           0 :                                 version, &peer->bgp->router_id);
   13946           0 :                         if (peer->bgp->vrf_id == VRF_UNKNOWN)
   13947           0 :                                 vty_out(vty, "%s", VRFID_NONE_STR);
   13948             :                         else
   13949           0 :                                 vty_out(vty, "%u", peer->bgp->vrf_id);
   13950           0 :                         vty_out(vty, "\n");
   13951           0 :                         vty_out(vty, "Default local pref %u, ",
   13952           0 :                                 peer->bgp->default_local_pref);
   13953           0 :                         vty_out(vty, "local AS %u\n",
   13954           0 :                                 peer->change_local_as ? peer->change_local_as
   13955             :                                                       : peer->local_as);
   13956           0 :                         if (!detail) {
   13957           0 :                                 vty_out(vty, BGP_SHOW_SCODE_HEADER);
   13958           0 :                                 vty_out(vty, BGP_SHOW_NCODE_HEADER);
   13959           0 :                                 vty_out(vty, BGP_SHOW_OCODE_HEADER);
   13960           0 :                                 vty_out(vty, BGP_SHOW_RPKI_HEADER);
   13961             :                         }
   13962             :                 }
   13963           0 :                 *header1 = 0;
   13964             :         }
   13965           0 :         if (*header2) {
   13966           0 :                 if (!json && !detail)
   13967           0 :                         vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
   13968             :                                            : BGP_SHOW_HEADER));
   13969           0 :                 *header2 = 0;
   13970             :         }
   13971           0 : }
   13972             : 
   13973             : static void
   13974           0 : show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
   13975             :                afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
   13976             :                const char *rmap_name, json_object *json, json_object *json_ar,
   13977             :                json_object *json_scode, json_object *json_ocode,
   13978             :                uint16_t show_flags, int *header1, int *header2, char *rd_str,
   13979             :                const struct prefix *match, unsigned long *output_count,
   13980             :                unsigned long *filtered_count)
   13981             : {
   13982           0 :         struct bgp_adj_in *ain = NULL;
   13983           0 :         struct bgp_adj_out *adj = NULL;
   13984           0 :         struct bgp_dest *dest;
   13985           0 :         struct bgp *bgp;
   13986           0 :         struct attr attr;
   13987           0 :         int ret;
   13988           0 :         struct update_subgroup *subgrp;
   13989           0 :         struct peer_af *paf = NULL;
   13990           0 :         bool route_filtered;
   13991           0 :         bool detail = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
   13992           0 :         bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
   13993           0 :         bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
   13994           0 :         bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
   13995           0 :                         || (safi == SAFI_EVPN))
   13996             :                                ? true
   13997             :                                : false;
   13998           0 :         int display = 0;
   13999           0 :         json_object *json_net = NULL;
   14000             : 
   14001           0 :         bgp = peer->bgp;
   14002             : 
   14003             :         /* If the user supplied a prefix, look for a matching route instead
   14004             :          * of walking the whole table.
   14005             :          */
   14006           0 :         if (match) {
   14007           0 :                 dest = bgp_node_match(table, match);
   14008           0 :                 if (!dest) {
   14009           0 :                         if (!use_json)
   14010           0 :                                 vty_out(vty, "Network not in table\n");
   14011           0 :                         return;
   14012             :                 }
   14013             : 
   14014           0 :                 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
   14015             : 
   14016           0 :                 if (rn_p->prefixlen != match->prefixlen) {
   14017           0 :                         if (!use_json)
   14018           0 :                                 vty_out(vty, "Network not in table\n");
   14019           0 :                         bgp_dest_unlock_node(dest);
   14020           0 :                         return;
   14021             :                 }
   14022             : 
   14023           0 :                 if (type == bgp_show_adj_route_received ||
   14024             :                     type == bgp_show_adj_route_filtered) {
   14025           0 :                         for (ain = dest->adj_in; ain; ain = ain->next) {
   14026           0 :                                 if (ain->peer == peer) {
   14027           0 :                                         attr = *ain->attr;
   14028           0 :                                         break;
   14029             :                                 }
   14030             :                         }
   14031             :                         /* bail out if if adj_out is empty, or
   14032             :                          * if the prefix isn't in this peer's
   14033             :                          * adj_in
   14034             :                          */
   14035           0 :                         if (!ain || ain->peer != peer) {
   14036           0 :                                 if (!use_json)
   14037           0 :                                         vty_out(vty, "Network not in table\n");
   14038           0 :                                 bgp_dest_unlock_node(dest);
   14039           0 :                                 return;
   14040             :                         }
   14041           0 :                 } else if (type == bgp_show_adj_route_advertised) {
   14042           0 :                         bool peer_found = false;
   14043             : 
   14044           0 :                         RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out) {
   14045           0 :                                 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
   14046           0 :                                         if (paf->peer == peer && adj->attr) {
   14047           0 :                                                 attr = *adj->attr;
   14048           0 :                                                 peer_found = true;
   14049           0 :                                                 break;
   14050             :                                         }
   14051             :                                 }
   14052           0 :                                 if (peer_found)
   14053             :                                         break;
   14054             :                         }
   14055             :                         /* bail out if if adj_out is empty, or
   14056             :                          * if the prefix isn't in this peer's
   14057             :                          * adj_out
   14058             :                          */
   14059           0 :                         if (!paf || !peer_found) {
   14060           0 :                                 if (!use_json)
   14061           0 :                                         vty_out(vty, "Network not in table\n");
   14062           0 :                                 bgp_dest_unlock_node(dest);
   14063           0 :                                 return;
   14064             :                         }
   14065             :                 }
   14066             : 
   14067           0 :                 ret = bgp_output_modifier(peer, rn_p, &attr, afi, safi,
   14068             :                                           rmap_name);
   14069             : 
   14070           0 :                 if (ret != RMAP_DENY) {
   14071           0 :                         show_adj_route_header(vty, peer, table, header1,
   14072             :                                               header2, json, json_scode,
   14073             :                                               json_ocode, wide, detail);
   14074             : 
   14075           0 :                         if (use_json)
   14076           0 :                                 json_net = json_object_new_object();
   14077             : 
   14078           0 :                         bgp_show_path_info(NULL /* prefix_rd */, dest, vty, bgp,
   14079             :                                            afi, safi, json_net,
   14080             :                                            BGP_PATH_SHOW_ALL, &display,
   14081             :                                            RPKI_NOT_BEING_USED);
   14082           0 :                         if (use_json)
   14083           0 :                                 json_object_object_addf(json_ar, json_net,
   14084             :                                                         "%pFX", rn_p);
   14085           0 :                         (*output_count)++;
   14086             :                 } else
   14087           0 :                         (*filtered_count)++;
   14088             : 
   14089           0 :                 bgp_attr_flush(&attr);
   14090           0 :                 bgp_dest_unlock_node(dest);
   14091           0 :                 return;
   14092             :         }
   14093             : 
   14094             : 
   14095           0 :         subgrp = peer_subgroup(peer, afi, safi);
   14096             : 
   14097           0 :         if (type == bgp_show_adj_route_advertised && subgrp
   14098           0 :             && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
   14099           0 :                 if (use_json) {
   14100           0 :                         json_object_int_add(json, "bgpTableVersion",
   14101           0 :                                             table->version);
   14102           0 :                         json_object_string_addf(json, "bgpLocalRouterId",
   14103             :                                                 "%pI4", &bgp->router_id);
   14104           0 :                         json_object_int_add(json, "defaultLocPrf",
   14105           0 :                                                 bgp->default_local_pref);
   14106           0 :                         json_object_int_add(json, "localAS",
   14107           0 :                                             peer->change_local_as
   14108             :                                                     ? peer->change_local_as
   14109           0 :                                                     : peer->local_as);
   14110           0 :                         json_object_object_add(json, "bgpStatusCodes",
   14111             :                                                json_scode);
   14112           0 :                         json_object_object_add(json, "bgpOriginCodes",
   14113             :                                                json_ocode);
   14114           0 :                         json_object_string_add(
   14115             :                                 json, "bgpOriginatingDefaultNetwork",
   14116             :                                 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
   14117             :                 } else {
   14118           0 :                         vty_out(vty,
   14119             :                                 "BGP table version is %" PRIu64
   14120             :                                 ", local router ID is %pI4, vrf id ",
   14121             :                                 table->version, &bgp->router_id);
   14122           0 :                         if (bgp->vrf_id == VRF_UNKNOWN)
   14123           0 :                                 vty_out(vty, "%s", VRFID_NONE_STR);
   14124             :                         else
   14125           0 :                                 vty_out(vty, "%u", bgp->vrf_id);
   14126           0 :                         vty_out(vty, "\n");
   14127           0 :                         vty_out(vty, "Default local pref %u, ",
   14128             :                                 bgp->default_local_pref);
   14129           0 :                         vty_out(vty, "local AS %u\n",
   14130           0 :                                 peer->change_local_as ? peer->change_local_as
   14131             :                                                       : peer->local_as);
   14132           0 :                         if (!detail) {
   14133           0 :                                 vty_out(vty, BGP_SHOW_SCODE_HEADER);
   14134           0 :                                 vty_out(vty, BGP_SHOW_NCODE_HEADER);
   14135           0 :                                 vty_out(vty, BGP_SHOW_OCODE_HEADER);
   14136           0 :                                 vty_out(vty, BGP_SHOW_RPKI_HEADER);
   14137             :                         }
   14138             : 
   14139           0 :                         vty_out(vty, "Originating default network %s\n\n",
   14140             :                                 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
   14141             :                 }
   14142           0 :                 (*output_count)++;
   14143           0 :                 *header1 = 0;
   14144             :         }
   14145             : 
   14146           0 :         for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
   14147           0 :                 if (type == bgp_show_adj_route_received
   14148           0 :                     || type == bgp_show_adj_route_filtered) {
   14149           0 :                         for (ain = dest->adj_in; ain; ain = ain->next) {
   14150           0 :                                 if (ain->peer != peer)
   14151           0 :                                         continue;
   14152             : 
   14153           0 :                                 show_adj_route_header(vty, peer, table, header1,
   14154             :                                                       header2, json, json_scode,
   14155             :                                                       json_ocode, wide, detail);
   14156             : 
   14157           0 :                                 if ((safi == SAFI_MPLS_VPN)
   14158             :                                     || (safi == SAFI_ENCAP)
   14159             :                                     || (safi == SAFI_EVPN)) {
   14160           0 :                                         if (use_json)
   14161           0 :                                                 json_object_string_add(
   14162             :                                                         json_ar, "rd", rd_str);
   14163           0 :                                         else if (show_rd && rd_str) {
   14164           0 :                                                 vty_out(vty,
   14165             :                                                         "Route Distinguisher: %s\n",
   14166             :                                                         rd_str);
   14167           0 :                                                 show_rd = false;
   14168             :                                         }
   14169             :                                 }
   14170             : 
   14171           0 :                                 attr = *ain->attr;
   14172           0 :                                 route_filtered = false;
   14173             : 
   14174             :                                 /* Filter prefix using distribute list,
   14175             :                                  * filter list or prefix list
   14176             :                                  */
   14177           0 :                                 const struct prefix *rn_p =
   14178           0 :                                         bgp_dest_get_prefix(dest);
   14179           0 :                                 if ((bgp_input_filter(peer, rn_p, &attr, afi,
   14180             :                                                       safi))
   14181             :                                     == FILTER_DENY)
   14182           0 :                                         route_filtered = true;
   14183             : 
   14184             :                                 /* Filter prefix using route-map */
   14185           0 :                                 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
   14186             :                                                          safi, rmap_name, NULL,
   14187             :                                                          0, NULL);
   14188             : 
   14189           0 :                                 if (type == bgp_show_adj_route_filtered &&
   14190           0 :                                         !route_filtered && ret != RMAP_DENY) {
   14191           0 :                                         bgp_attr_flush(&attr);
   14192           0 :                                         continue;
   14193             :                                 }
   14194             : 
   14195           0 :                                 if (type == bgp_show_adj_route_received
   14196           0 :                                     && (route_filtered || ret == RMAP_DENY))
   14197           0 :                                         (*filtered_count)++;
   14198             : 
   14199           0 :                                 if (detail) {
   14200           0 :                                         if (use_json)
   14201           0 :                                                 json_net =
   14202           0 :                                                         json_object_new_object();
   14203           0 :                                         bgp_show_path_info(
   14204             :                                                 NULL /* prefix_rd */, dest, vty,
   14205             :                                                 bgp, afi, safi, json_net,
   14206             :                                                 BGP_PATH_SHOW_ALL, &display,
   14207             :                                                 RPKI_NOT_BEING_USED);
   14208           0 :                                         if (use_json)
   14209           0 :                                                 json_object_object_addf(
   14210             :                                                         json_ar, json_net,
   14211             :                                                         "%pFX", rn_p);
   14212             :                                 } else
   14213           0 :                                         route_vty_out_tmp(vty, dest, rn_p,
   14214             :                                                           &attr, safi, use_json,
   14215             :                                                           json_ar, wide);
   14216           0 :                                 bgp_attr_flush(&attr);
   14217           0 :                                 (*output_count)++;
   14218             :                         }
   14219           0 :                 } else if (type == bgp_show_adj_route_advertised) {
   14220           0 :                         RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
   14221           0 :                                 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
   14222           0 :                                         if (paf->peer != peer || !adj->attr)
   14223           0 :                                                 continue;
   14224             : 
   14225           0 :                                         show_adj_route_header(
   14226             :                                                 vty, peer, table, header1,
   14227             :                                                 header2, json, json_scode,
   14228             :                                                 json_ocode, wide, detail);
   14229             : 
   14230           0 :                                         const struct prefix *rn_p =
   14231           0 :                                                 bgp_dest_get_prefix(dest);
   14232             : 
   14233           0 :                                         attr = *adj->attr;
   14234           0 :                                         ret = bgp_output_modifier(
   14235             :                                                 peer, rn_p, &attr, afi, safi,
   14236             :                                                 rmap_name);
   14237             : 
   14238           0 :                                         if (ret != RMAP_DENY) {
   14239           0 :                                                 if ((safi == SAFI_MPLS_VPN)
   14240             :                                                     || (safi == SAFI_ENCAP)
   14241             :                                                     || (safi == SAFI_EVPN)) {
   14242           0 :                                                         if (use_json)
   14243           0 :                                                                 json_object_string_add(
   14244             :                                                                         json_ar,
   14245             :                                                                         "rd",
   14246             :                                                                         rd_str);
   14247           0 :                                                         else if (show_rd
   14248           0 :                                                                  && rd_str) {
   14249           0 :                                                                 vty_out(vty,
   14250             :                                                                         "Route Distinguisher: %s\n",
   14251             :                                                                         rd_str);
   14252           0 :                                                                 show_rd = false;
   14253             :                                                         }
   14254             :                                                 }
   14255           0 :                                                 if (detail) {
   14256           0 :                                                         if (use_json)
   14257           0 :                                                                 json_net =
   14258           0 :                                                                         json_object_new_object();
   14259           0 :                                                         bgp_show_path_info(
   14260             :                                                                 NULL /* prefix_rd
   14261             :                                                                       */
   14262             :                                                                 ,
   14263             :                                                                 dest, vty, bgp,
   14264             :                                                                 afi, safi,
   14265             :                                                                 json_net,
   14266             :                                                                 BGP_PATH_SHOW_ALL,
   14267             :                                                                 &display,
   14268             :                                                                 RPKI_NOT_BEING_USED);
   14269           0 :                                                         if (use_json)
   14270           0 :                                                                 json_object_object_addf(
   14271             :                                                                         json_ar,
   14272             :                                                                         json_net,
   14273             :                                                                         "%pFX",
   14274             :                                                                         rn_p);
   14275             :                                                 } else
   14276           0 :                                                         route_vty_out_tmp(
   14277             :                                                                 vty, dest, rn_p,
   14278             :                                                                 &attr, safi,
   14279             :                                                                 use_json,
   14280             :                                                                 json_ar, wide);
   14281           0 :                                                 (*output_count)++;
   14282             :                                         } else {
   14283           0 :                                                 (*filtered_count)++;
   14284             :                                         }
   14285             : 
   14286           0 :                                         bgp_attr_flush(&attr);
   14287             :                                 }
   14288           0 :                 } else if (type == bgp_show_adj_route_bestpath) {
   14289           0 :                         struct bgp_path_info *pi;
   14290             : 
   14291           0 :                         show_adj_route_header(vty, peer, table, header1,
   14292             :                                               header2, json, json_scode,
   14293             :                                               json_ocode, wide, detail);
   14294             : 
   14295           0 :                         const struct prefix *rn_p = bgp_dest_get_prefix(dest);
   14296             : 
   14297           0 :                         for (pi = bgp_dest_get_bgp_path_info(dest); pi;
   14298           0 :                              pi = pi->next) {
   14299           0 :                                 if (pi->peer != peer)
   14300           0 :                                         continue;
   14301             : 
   14302           0 :                                 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
   14303           0 :                                         continue;
   14304             : 
   14305           0 :                                 if (detail) {
   14306           0 :                                         if (use_json)
   14307           0 :                                                 json_net =
   14308           0 :                                                         json_object_new_object();
   14309           0 :                                         bgp_show_path_info(
   14310             :                                                 NULL /* prefix_rd */, dest, vty,
   14311             :                                                 bgp, afi, safi, json_net,
   14312             :                                                 BGP_PATH_SHOW_BESTPATH,
   14313             :                                                 &display, RPKI_NOT_BEING_USED);
   14314           0 :                                         if (use_json)
   14315           0 :                                                 json_object_object_addf(
   14316             :                                                         json_ar, json_net,
   14317             :                                                         "%pFX", rn_p);
   14318             :                                 } else
   14319           0 :                                         route_vty_out_tmp(
   14320             :                                                 vty, dest, rn_p, pi->attr, safi,
   14321             :                                                 use_json, json_ar, wide);
   14322           0 :                                 (*output_count)++;
   14323             :                         }
   14324             :                 }
   14325             :         }
   14326             : }
   14327             : 
   14328           0 : static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
   14329             :                            safi_t safi, enum bgp_show_adj_route_type type,
   14330             :                            const char *rmap_name, const struct prefix *match,
   14331             :                            uint16_t show_flags)
   14332             : {
   14333           0 :         struct bgp *bgp;
   14334           0 :         struct bgp_table *table;
   14335           0 :         json_object *json = NULL;
   14336           0 :         json_object *json_scode = NULL;
   14337           0 :         json_object *json_ocode = NULL;
   14338           0 :         json_object *json_ar = NULL;
   14339           0 :         bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
   14340             : 
   14341             :         /* Init BGP headers here so they're only displayed once
   14342             :          * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
   14343             :          */
   14344           0 :         int header1 = 1;
   14345           0 :         int header2 = 1;
   14346             : 
   14347             :         /*
   14348             :          * Initialize variables for each RD
   14349             :          * All prefixes under an RD is aggregated within "json_routes"
   14350             :          */
   14351           0 :         char rd_str[BUFSIZ] = {0};
   14352           0 :         json_object *json_routes = NULL;
   14353             : 
   14354             : 
   14355             :         /* For 2-tier tables, prefix counts need to be
   14356             :          * maintained across multiple runs of show_adj_route()
   14357             :          */
   14358           0 :         unsigned long output_count_per_rd;
   14359           0 :         unsigned long filtered_count_per_rd;
   14360           0 :         unsigned long output_count = 0;
   14361           0 :         unsigned long filtered_count = 0;
   14362             : 
   14363           0 :         if (use_json) {
   14364           0 :                 json = json_object_new_object();
   14365           0 :                 json_ar = json_object_new_object();
   14366           0 :                 json_scode = json_object_new_object();
   14367           0 :                 json_ocode = json_object_new_object();
   14368             : #if CONFDATE > 20231208
   14369             : CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
   14370             : #endif
   14371           0 :                 json_object_string_add(json_scode, "suppressed", "s");
   14372           0 :                 json_object_string_add(json_scode, "damped", "d");
   14373           0 :                 json_object_string_add(json_scode, "history", "h");
   14374           0 :                 json_object_string_add(json_scode, "valid", "*");
   14375           0 :                 json_object_string_add(json_scode, "best", ">");
   14376           0 :                 json_object_string_add(json_scode, "multipath", "=");
   14377           0 :                 json_object_string_add(json_scode, "internal", "i");
   14378           0 :                 json_object_string_add(json_scode, "ribFailure", "r");
   14379           0 :                 json_object_string_add(json_scode, "stale", "S");
   14380           0 :                 json_object_string_add(json_scode, "removed", "R");
   14381             : 
   14382             : #if CONFDATE > 20231208
   14383             : CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
   14384             : #endif
   14385           0 :                 json_object_string_add(json_ocode, "igp", "i");
   14386           0 :                 json_object_string_add(json_ocode, "egp", "e");
   14387           0 :                 json_object_string_add(json_ocode, "incomplete", "?");
   14388             :         }
   14389             : 
   14390           0 :         if (!peer || !peer->afc[afi][safi]) {
   14391           0 :                 if (use_json) {
   14392           0 :                         json_object_string_add(
   14393             :                                 json, "warning",
   14394             :                                 "No such neighbor or address family");
   14395           0 :                         vty_out(vty, "%s\n", json_object_to_json_string(json));
   14396           0 :                         json_object_free(json);
   14397           0 :                         json_object_free(json_ar);
   14398           0 :                         json_object_free(json_scode);
   14399           0 :                         json_object_free(json_ocode);
   14400             :                 } else
   14401           0 :                         vty_out(vty, "%% No such neighbor or address family\n");
   14402             : 
   14403           0 :                 return CMD_WARNING;
   14404             :         }
   14405             : 
   14406           0 :         if ((type == bgp_show_adj_route_received
   14407           0 :              || type == bgp_show_adj_route_filtered)
   14408           0 :             && !CHECK_FLAG(peer->af_flags[afi][safi],
   14409             :                            PEER_FLAG_SOFT_RECONFIG)) {
   14410           0 :                 if (use_json) {
   14411           0 :                         json_object_string_add(
   14412             :                                 json, "warning",
   14413             :                                 "Inbound soft reconfiguration not enabled");
   14414           0 :                         vty_out(vty, "%s\n", json_object_to_json_string(json));
   14415           0 :                         json_object_free(json);
   14416           0 :                         json_object_free(json_ar);
   14417           0 :                         json_object_free(json_scode);
   14418           0 :                         json_object_free(json_ocode);
   14419             :                 } else
   14420           0 :                         vty_out(vty,
   14421             :                                 "%% Inbound soft reconfiguration not enabled\n");
   14422             : 
   14423           0 :                 return CMD_WARNING;
   14424             :         }
   14425             : 
   14426           0 :         bgp = peer->bgp;
   14427             : 
   14428             :         /* labeled-unicast routes live in the unicast table */
   14429           0 :         if (safi == SAFI_LABELED_UNICAST)
   14430           0 :                 table = bgp->rib[afi][SAFI_UNICAST];
   14431             :         else
   14432           0 :                 table = bgp->rib[afi][safi];
   14433             : 
   14434           0 :         if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
   14435           0 :             || (safi == SAFI_EVPN)) {
   14436             : 
   14437           0 :                 struct bgp_dest *dest;
   14438             : 
   14439           0 :                 for (dest = bgp_table_top(table); dest;
   14440           0 :                      dest = bgp_route_next(dest)) {
   14441           0 :                         table = bgp_dest_get_bgp_table_info(dest);
   14442           0 :                         if (!table)
   14443           0 :                                 continue;
   14444             : 
   14445           0 :                         output_count_per_rd = 0;
   14446           0 :                         filtered_count_per_rd = 0;
   14447             : 
   14448           0 :                         if (use_json)
   14449           0 :                                 json_routes = json_object_new_object();
   14450             : 
   14451           0 :                         const struct prefix_rd *prd;
   14452           0 :                         prd = (const struct prefix_rd *)bgp_dest_get_prefix(
   14453             :                                 dest);
   14454             : 
   14455           0 :                         prefix_rd2str(prd, rd_str, sizeof(rd_str));
   14456             : 
   14457           0 :                         show_adj_route(
   14458             :                                 vty, peer, table, afi, safi, type, rmap_name,
   14459             :                                 json, json_routes, json_scode, json_ocode,
   14460             :                                 show_flags, &header1, &header2, rd_str, match,
   14461             :                                 &output_count_per_rd, &filtered_count_per_rd);
   14462             : 
   14463             :                         /* Don't include an empty RD in the output! */
   14464           0 :                         if (json_routes && (output_count_per_rd > 0))
   14465           0 :                                 json_object_object_add(json_ar, rd_str,
   14466             :                                                        json_routes);
   14467             : 
   14468           0 :                         output_count += output_count_per_rd;
   14469           0 :                         filtered_count += filtered_count_per_rd;
   14470             :                 }
   14471             :         } else
   14472           0 :                 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
   14473             :                                json, json_ar, json_scode, json_ocode,
   14474             :                                show_flags, &header1, &header2, rd_str, match,
   14475             :                                &output_count, &filtered_count);
   14476             : 
   14477           0 :         if (use_json) {
   14478           0 :                 if (type == bgp_show_adj_route_advertised)
   14479           0 :                         json_object_object_add(json, "advertisedRoutes",
   14480             :                                                json_ar);
   14481             :                 else
   14482           0 :                         json_object_object_add(json, "receivedRoutes", json_ar);
   14483           0 :                 json_object_int_add(json, "totalPrefixCounter", output_count);
   14484           0 :                 json_object_int_add(json, "filteredPrefixCounter",
   14485             :                                     filtered_count);
   14486             : 
   14487             :                 /*
   14488             :                  * These fields only give up ownership to `json` when `header1`
   14489             :                  * is used (set to zero). See code in `show_adj_route` and
   14490             :                  * `show_adj_route_header`.
   14491             :                  */
   14492           0 :                 if (header1 == 1) {
   14493           0 :                         json_object_free(json_scode);
   14494           0 :                         json_object_free(json_ocode);
   14495             :                 }
   14496             : 
   14497           0 :                 vty_json(vty, json);
   14498           0 :         } else if (output_count > 0) {
   14499           0 :                 if (!match && filtered_count > 0)
   14500           0 :                         vty_out(vty,
   14501             :                                 "\nTotal number of prefixes %ld (%ld filtered)\n",
   14502             :                                 output_count, filtered_count);
   14503             :                 else
   14504           0 :                         vty_out(vty, "\nTotal number of prefixes %ld\n",
   14505             :                                 output_count);
   14506             :         }
   14507             : 
   14508             :         return CMD_SUCCESS;
   14509             : }
   14510             : 
   14511           0 : DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
   14512             :        show_ip_bgp_instance_neighbor_bestpath_route_cmd,
   14513             :        "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR " [" BGP_SAFI_WITH_LABEL_CMD_STR "]] neighbors <A.B.C.D|X:X::X:X|WORD> bestpath-routes [detail$detail] [json$uj | wide$wide]",
   14514             :        SHOW_STR
   14515             :        IP_STR
   14516             :        BGP_STR
   14517             :        BGP_INSTANCE_HELP_STR
   14518             :        BGP_AFI_HELP_STR
   14519             :        BGP_SAFI_WITH_LABEL_HELP_STR
   14520             :        "Detailed information on TCP and BGP neighbor connections\n"
   14521             :        "Neighbor to display information about\n"
   14522             :        "Neighbor to display information about\n"
   14523             :        "Neighbor on BGP configured interface\n"
   14524             :        "Display the routes selected by best path\n"
   14525             :        "Display detailed version of routes\n"
   14526             :        JSON_STR
   14527             :        "Increase table width for longer prefixes\n")
   14528             : {
   14529           0 :         afi_t afi = AFI_IP6;
   14530           0 :         safi_t safi = SAFI_UNICAST;
   14531           0 :         char *rmap_name = NULL;
   14532           0 :         char *peerstr = NULL;
   14533           0 :         struct bgp *bgp = NULL;
   14534           0 :         struct peer *peer;
   14535           0 :         enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
   14536           0 :         int idx = 0;
   14537           0 :         uint16_t show_flags = 0;
   14538             : 
   14539           0 :         if (detail)
   14540           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
   14541             : 
   14542           0 :         if (uj)
   14543           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
   14544             : 
   14545           0 :         if (wide)
   14546           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
   14547             : 
   14548           0 :         bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
   14549             :                                             &bgp, uj);
   14550             : 
   14551           0 :         if (!idx)
   14552             :                 return CMD_WARNING;
   14553             : 
   14554           0 :         argv_find(argv, argc, "neighbors", &idx);
   14555           0 :         peerstr = argv[++idx]->arg;
   14556             : 
   14557           0 :         peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
   14558           0 :         if (!peer)
   14559             :                 return CMD_WARNING;
   14560             : 
   14561           0 :         return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, NULL,
   14562             :                                show_flags);
   14563             : }
   14564             : 
   14565           0 : DEFPY(show_ip_bgp_instance_neighbor_advertised_route,
   14566             :       show_ip_bgp_instance_neighbor_advertised_route_cmd,
   14567             :       "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR " [" BGP_SAFI_WITH_LABEL_CMD_STR "]] [all$all] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map RMAP_NAME$route_map] [<A.B.C.D/M|X:X::X:X/M>$prefix | detail$detail] [json$uj | wide$wide]",
   14568             :       SHOW_STR
   14569             :       IP_STR
   14570             :       BGP_STR
   14571             :       BGP_INSTANCE_HELP_STR
   14572             :       BGP_AFI_HELP_STR
   14573             :       BGP_SAFI_WITH_LABEL_HELP_STR
   14574             :       "Display the entries for all address families\n"
   14575             :       "Detailed information on TCP and BGP neighbor connections\n"
   14576             :       "Neighbor to display information about\n"
   14577             :       "Neighbor to display information about\n"
   14578             :       "Neighbor on BGP configured interface\n"
   14579             :       "Display the routes advertised to a BGP neighbor\n"
   14580             :       "Display the received routes from neighbor\n"
   14581             :       "Display the filtered routes received from neighbor\n"
   14582             :       "Route-map to modify the attributes\n"
   14583             :       "Name of the route map\n"
   14584             :       "IPv4 prefix\n"
   14585             :       "IPv6 prefix\n"
   14586             :       "Display detailed version of routes\n"
   14587             :       JSON_STR
   14588             :       "Increase table width for longer prefixes\n")
   14589             : {
   14590           0 :         afi_t afi = AFI_IP6;
   14591           0 :         safi_t safi = SAFI_UNICAST;
   14592           0 :         char *peerstr = NULL;
   14593           0 :         struct bgp *bgp = NULL;
   14594           0 :         struct peer *peer;
   14595           0 :         enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
   14596           0 :         int idx = 0;
   14597           0 :         bool first = true;
   14598           0 :         uint16_t show_flags = 0;
   14599           0 :         struct listnode *node;
   14600           0 :         struct bgp *abgp;
   14601             : 
   14602           0 :         if (detail || prefix_str)
   14603           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
   14604             : 
   14605           0 :         if (uj) {
   14606           0 :                 argc--;
   14607           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
   14608             :         }
   14609             : 
   14610           0 :         if (all) {
   14611           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
   14612           0 :                 if (argv_find(argv, argc, "ipv4", &idx))
   14613           0 :                         SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
   14614             : 
   14615           0 :                 if (argv_find(argv, argc, "ipv6", &idx))
   14616           0 :                         SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
   14617             :         }
   14618             : 
   14619           0 :         if (wide)
   14620           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
   14621             : 
   14622           0 :         bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
   14623             :                                             &bgp, uj);
   14624           0 :         if (!idx)
   14625             :                 return CMD_WARNING;
   14626             : 
   14627             :         /* neighbors <A.B.C.D|X:X::X:X|WORD> */
   14628           0 :         argv_find(argv, argc, "neighbors", &idx);
   14629           0 :         peerstr = argv[++idx]->arg;
   14630             : 
   14631           0 :         peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
   14632           0 :         if (!peer)
   14633             :                 return CMD_WARNING;
   14634             : 
   14635           0 :         if (argv_find(argv, argc, "advertised-routes", &idx))
   14636             :                 type = bgp_show_adj_route_advertised;
   14637           0 :         else if (argv_find(argv, argc, "received-routes", &idx))
   14638             :                 type = bgp_show_adj_route_received;
   14639           0 :         else if (argv_find(argv, argc, "filtered-routes", &idx))
   14640           0 :                 type = bgp_show_adj_route_filtered;
   14641             : 
   14642           0 :         if (!all)
   14643           0 :                 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
   14644             :                                        prefix_str ? prefix : NULL, show_flags);
   14645           0 :         if (uj)
   14646           0 :                 vty_out(vty, "{\n");
   14647             : 
   14648           0 :         if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
   14649             :             || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
   14650           0 :                 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
   14651           0 :                                                                   : AFI_IP6;
   14652           0 :                 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
   14653           0 :                         FOREACH_SAFI (safi) {
   14654           0 :                                 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
   14655           0 :                                         continue;
   14656             : 
   14657           0 :                                 if (uj) {
   14658           0 :                                         if (first)
   14659             :                                                 first = false;
   14660             :                                         else
   14661           0 :                                                 vty_out(vty, ",\n");
   14662           0 :                                         vty_out(vty, "\"%s\":",
   14663             :                                                 get_afi_safi_str(afi, safi,
   14664             :                                                                  true));
   14665             :                                 } else
   14666           0 :                                         vty_out(vty,
   14667             :                                                 "\nFor address family: %s\n",
   14668             :                                                 get_afi_safi_str(afi, safi,
   14669             :                                                                  false));
   14670             : 
   14671           0 :                                 peer_adj_routes(vty, peer, afi, safi, type,
   14672             :                                                 route_map, prefix, show_flags);
   14673             :                         }
   14674             :                 }
   14675             :         } else {
   14676           0 :                 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
   14677           0 :                         FOREACH_AFI_SAFI (afi, safi) {
   14678           0 :                                 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
   14679           0 :                                         continue;
   14680             : 
   14681           0 :                                 if (uj) {
   14682           0 :                                         if (first)
   14683             :                                                 first = false;
   14684             :                                         else
   14685           0 :                                                 vty_out(vty, ",\n");
   14686           0 :                                         vty_out(vty, "\"%s\":",
   14687             :                                                 get_afi_safi_str(afi, safi,
   14688             :                                                                  true));
   14689             :                                 } else
   14690           0 :                                         vty_out(vty,
   14691             :                                                 "\nFor address family: %s\n",
   14692             :                                                 get_afi_safi_str(afi, safi,
   14693             :                                                                  false));
   14694             : 
   14695           0 :                                 peer_adj_routes(vty, peer, afi, safi, type,
   14696             :                                                 route_map, prefix, show_flags);
   14697             :                         }
   14698             :                 }
   14699             :         }
   14700           0 :         if (uj)
   14701           0 :                 vty_out(vty, "}\n");
   14702             : 
   14703             :         return CMD_SUCCESS;
   14704             : }
   14705             : 
   14706           0 : DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
   14707             :        show_ip_bgp_neighbor_received_prefix_filter_cmd,
   14708             :        "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
   14709             :        SHOW_STR
   14710             :        IP_STR
   14711             :        BGP_STR
   14712             :        BGP_INSTANCE_HELP_STR
   14713             :        BGP_AF_STR
   14714             :        BGP_AF_STR
   14715             :        BGP_AF_MODIFIER_STR
   14716             :        "Detailed information on TCP and BGP neighbor connections\n"
   14717             :        "Neighbor to display information about\n"
   14718             :        "Neighbor to display information about\n"
   14719             :        "Neighbor on BGP configured interface\n"
   14720             :        "Display information received from a BGP neighbor\n"
   14721             :        "Display the prefixlist filter\n"
   14722             :        JSON_STR)
   14723             : {
   14724           0 :         afi_t afi = AFI_IP6;
   14725           0 :         safi_t safi = SAFI_UNICAST;
   14726           0 :         char *peerstr = NULL;
   14727           0 :         char name[BUFSIZ];
   14728           0 :         struct peer *peer;
   14729           0 :         int count;
   14730           0 :         int idx = 0;
   14731           0 :         struct bgp *bgp = NULL;
   14732           0 :         bool uj = use_json(argc, argv);
   14733             : 
   14734           0 :         if (uj)
   14735           0 :                 argc--;
   14736             : 
   14737           0 :         bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
   14738             :                                             &bgp, uj);
   14739           0 :         if (!idx)
   14740             :                 return CMD_WARNING;
   14741             : 
   14742             :         /* neighbors <A.B.C.D|X:X::X:X|WORD> */
   14743           0 :         argv_find(argv, argc, "neighbors", &idx);
   14744           0 :         peerstr = argv[++idx]->arg;
   14745             : 
   14746           0 :         peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
   14747           0 :         if (!peer)
   14748             :                 return CMD_WARNING;
   14749             : 
   14750           0 :         snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
   14751           0 :         count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
   14752           0 :         if (count) {
   14753           0 :                 if (!uj)
   14754           0 :                         vty_out(vty, "Address Family: %s\n",
   14755             :                                 get_afi_safi_str(afi, safi, false));
   14756           0 :                 prefix_bgp_show_prefix_list(vty, afi, name, uj);
   14757             :         } else {
   14758           0 :                 if (uj)
   14759           0 :                         vty_out(vty, "{}\n");
   14760             :                 else
   14761           0 :                         vty_out(vty, "No functional output\n");
   14762             :         }
   14763             : 
   14764             :         return CMD_SUCCESS;
   14765             : }
   14766             : 
   14767           0 : static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
   14768             :                                    afi_t afi, safi_t safi,
   14769             :                                    enum bgp_show_type type, bool use_json)
   14770             : {
   14771           0 :         uint16_t show_flags = 0;
   14772             : 
   14773           0 :         if (use_json)
   14774           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
   14775             : 
   14776           0 :         if (!peer || !peer->afc[afi][safi]) {
   14777           0 :                 if (use_json) {
   14778           0 :                         json_object *json_no = NULL;
   14779           0 :                         json_no = json_object_new_object();
   14780           0 :                         json_object_string_add(
   14781             :                                 json_no, "warning",
   14782             :                                 "No such neighbor or address family");
   14783           0 :                         vty_out(vty, "%s\n",
   14784             :                                 json_object_to_json_string(json_no));
   14785           0 :                         json_object_free(json_no);
   14786             :                 } else
   14787           0 :                         vty_out(vty, "%% No such neighbor or address family\n");
   14788           0 :                 return CMD_WARNING;
   14789             :         }
   14790             : 
   14791             :         /* labeled-unicast routes live in the unicast table */
   14792           0 :         if (safi == SAFI_LABELED_UNICAST)
   14793           0 :                 safi = SAFI_UNICAST;
   14794             : 
   14795           0 :         return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
   14796             :                         RPKI_NOT_BEING_USED);
   14797             : }
   14798             : 
   14799           0 : DEFUN (show_ip_bgp_flowspec_routes_detailed,
   14800             :        show_ip_bgp_flowspec_routes_detailed_cmd,
   14801             :        "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
   14802             :        SHOW_STR
   14803             :        IP_STR
   14804             :        BGP_STR
   14805             :        BGP_INSTANCE_HELP_STR
   14806             :        BGP_AFI_HELP_STR
   14807             :        "SAFI Flowspec\n"
   14808             :        "Detailed information on flowspec entries\n"
   14809             :        JSON_STR)
   14810             : {
   14811           0 :         afi_t afi = AFI_IP6;
   14812           0 :         safi_t safi = SAFI_UNICAST;
   14813           0 :         struct bgp *bgp = NULL;
   14814           0 :         int idx = 0;
   14815           0 :         bool uj = use_json(argc, argv);
   14816           0 :         uint16_t show_flags = BGP_SHOW_OPT_ROUTES_DETAIL;
   14817             : 
   14818           0 :         if (uj) {
   14819           0 :                 argc--;
   14820           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
   14821             :         }
   14822             : 
   14823           0 :         bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
   14824             :                                             &bgp, uj);
   14825           0 :         if (!idx)
   14826             :                 return CMD_WARNING;
   14827             : 
   14828           0 :         return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
   14829             :                         show_flags, RPKI_NOT_BEING_USED);
   14830             : }
   14831             : 
   14832           0 : DEFUN (show_ip_bgp_neighbor_routes,
   14833             :        show_ip_bgp_neighbor_routes_cmd,
   14834             :        "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
   14835             :        SHOW_STR
   14836             :        IP_STR
   14837             :        BGP_STR
   14838             :        BGP_INSTANCE_HELP_STR
   14839             :        BGP_AFI_HELP_STR
   14840             :        BGP_SAFI_WITH_LABEL_HELP_STR
   14841             :        "Detailed information on TCP and BGP neighbor connections\n"
   14842             :        "Neighbor to display information about\n"
   14843             :        "Neighbor to display information about\n"
   14844             :        "Neighbor on BGP configured interface\n"
   14845             :        "Display flap statistics of the routes learned from neighbor\n"
   14846             :        "Display the dampened routes received from neighbor\n"
   14847             :        "Display routes learned from neighbor\n"
   14848             :        JSON_STR)
   14849             : {
   14850           0 :         char *peerstr = NULL;
   14851           0 :         struct bgp *bgp = NULL;
   14852           0 :         afi_t afi = AFI_IP6;
   14853           0 :         safi_t safi = SAFI_UNICAST;
   14854           0 :         struct peer *peer;
   14855           0 :         enum bgp_show_type sh_type = bgp_show_type_neighbor;
   14856           0 :         int idx = 0;
   14857           0 :         bool uj = use_json(argc, argv);
   14858             : 
   14859           0 :         if (uj)
   14860           0 :                 argc--;
   14861             : 
   14862           0 :         bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
   14863             :                                             &bgp, uj);
   14864           0 :         if (!idx)
   14865             :                 return CMD_WARNING;
   14866             : 
   14867             :         /* neighbors <A.B.C.D|X:X::X:X|WORD> */
   14868           0 :         argv_find(argv, argc, "neighbors", &idx);
   14869           0 :         peerstr = argv[++idx]->arg;
   14870             : 
   14871           0 :         peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
   14872           0 :         if (!peer)
   14873             :                 return CMD_WARNING;
   14874             : 
   14875           0 :         if (argv_find(argv, argc, "flap-statistics", &idx))
   14876             :                 sh_type = bgp_show_type_flap_neighbor;
   14877           0 :         else if (argv_find(argv, argc, "dampened-routes", &idx))
   14878             :                 sh_type = bgp_show_type_damp_neighbor;
   14879           0 :         else if (argv_find(argv, argc, "routes", &idx))
   14880             :                 sh_type = bgp_show_type_neighbor;
   14881             : 
   14882           0 :         return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
   14883             : }
   14884             : 
   14885             : struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
   14886             : 
   14887             : struct bgp_distance {
   14888             :         /* Distance value for the IP source prefix. */
   14889             :         uint8_t distance;
   14890             : 
   14891             :         /* Name of the access-list to be matched. */
   14892             :         char *access_list;
   14893             : };
   14894             : 
   14895           0 : DEFUN (show_bgp_afi_vpn_rd_route,
   14896             :        show_bgp_afi_vpn_rd_route_cmd,
   14897             :        "show bgp "BGP_AFI_CMD_STR" vpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> <A.B.C.D/M|X:X::X:X/M> [json]",
   14898             :        SHOW_STR
   14899             :        BGP_STR
   14900             :        BGP_AFI_HELP_STR
   14901             :        BGP_AF_MODIFIER_STR
   14902             :        "Display information for a route distinguisher\n"
   14903             :        "Route Distinguisher\n"
   14904             :        "All Route Distinguishers\n"
   14905             :        "Network in the BGP routing table to display\n"
   14906             :        "Network in the BGP routing table to display\n"
   14907             :        JSON_STR)
   14908             : {
   14909           0 :         int ret;
   14910           0 :         struct prefix_rd prd;
   14911           0 :         afi_t afi = AFI_MAX;
   14912           0 :         int idx = 0;
   14913             : 
   14914           0 :         if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
   14915           0 :                 vty_out(vty, "%% Malformed Address Family\n");
   14916           0 :                 return CMD_WARNING;
   14917             :         }
   14918             : 
   14919           0 :         if (!strcmp(argv[5]->arg, "all"))
   14920           0 :                 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
   14921             :                                       SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
   14922             :                                       RPKI_NOT_BEING_USED,
   14923           0 :                                       use_json(argc, argv));
   14924             : 
   14925           0 :         ret = str2prefix_rd(argv[5]->arg, &prd);
   14926           0 :         if (!ret) {
   14927           0 :                 vty_out(vty, "%% Malformed Route Distinguisher\n");
   14928           0 :                 return CMD_WARNING;
   14929             :         }
   14930             : 
   14931           0 :         return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
   14932             :                               0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
   14933           0 :                               use_json(argc, argv));
   14934             : }
   14935             : 
   14936           0 : static struct bgp_distance *bgp_distance_new(void)
   14937             : {
   14938           0 :         return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
   14939             : }
   14940             : 
   14941           0 : static void bgp_distance_free(struct bgp_distance *bdistance)
   14942             : {
   14943           0 :         XFREE(MTYPE_BGP_DISTANCE, bdistance);
   14944             : }
   14945             : 
   14946           0 : static int bgp_distance_set(struct vty *vty, const char *distance_str,
   14947             :                             const char *ip_str, const char *access_list_str)
   14948             : {
   14949           0 :         int ret;
   14950           0 :         afi_t afi;
   14951           0 :         safi_t safi;
   14952           0 :         struct prefix p;
   14953           0 :         uint8_t distance;
   14954           0 :         struct bgp_dest *dest;
   14955           0 :         struct bgp_distance *bdistance;
   14956             : 
   14957           0 :         afi = bgp_node_afi(vty);
   14958           0 :         safi = bgp_node_safi(vty);
   14959             : 
   14960           0 :         ret = str2prefix(ip_str, &p);
   14961           0 :         if (ret == 0) {
   14962           0 :                 vty_out(vty, "Malformed prefix\n");
   14963           0 :                 return CMD_WARNING_CONFIG_FAILED;
   14964             :         }
   14965             : 
   14966           0 :         distance = atoi(distance_str);
   14967             : 
   14968             :         /* Get BGP distance node. */
   14969           0 :         dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
   14970           0 :         bdistance = bgp_dest_get_bgp_distance_info(dest);
   14971           0 :         if (bdistance)
   14972           0 :                 bgp_dest_unlock_node(dest);
   14973             :         else {
   14974           0 :                 bdistance = bgp_distance_new();
   14975           0 :                 bgp_dest_set_bgp_distance_info(dest, bdistance);
   14976             :         }
   14977             : 
   14978             :         /* Set distance value. */
   14979           0 :         bdistance->distance = distance;
   14980             : 
   14981             :         /* Reset access-list configuration. */
   14982           0 :         XFREE(MTYPE_AS_LIST, bdistance->access_list);
   14983           0 :         if (access_list_str)
   14984           0 :                 bdistance->access_list =
   14985           0 :                         XSTRDUP(MTYPE_AS_LIST, access_list_str);
   14986             : 
   14987             :         return CMD_SUCCESS;
   14988             : }
   14989             : 
   14990           0 : static int bgp_distance_unset(struct vty *vty, const char *distance_str,
   14991             :                               const char *ip_str, const char *access_list_str)
   14992             : {
   14993           0 :         int ret;
   14994           0 :         afi_t afi;
   14995           0 :         safi_t safi;
   14996           0 :         struct prefix p;
   14997           0 :         int distance;
   14998           0 :         struct bgp_dest *dest;
   14999           0 :         struct bgp_distance *bdistance;
   15000             : 
   15001           0 :         afi = bgp_node_afi(vty);
   15002           0 :         safi = bgp_node_safi(vty);
   15003             : 
   15004           0 :         ret = str2prefix(ip_str, &p);
   15005           0 :         if (ret == 0) {
   15006           0 :                 vty_out(vty, "Malformed prefix\n");
   15007           0 :                 return CMD_WARNING_CONFIG_FAILED;
   15008             :         }
   15009             : 
   15010           0 :         dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
   15011           0 :         if (!dest) {
   15012           0 :                 vty_out(vty, "Can't find specified prefix\n");
   15013           0 :                 return CMD_WARNING_CONFIG_FAILED;
   15014             :         }
   15015             : 
   15016           0 :         bdistance = bgp_dest_get_bgp_distance_info(dest);
   15017           0 :         distance = atoi(distance_str);
   15018             : 
   15019           0 :         if (bdistance->distance != distance) {
   15020           0 :                 vty_out(vty, "Distance does not match configured\n");
   15021           0 :                 bgp_dest_unlock_node(dest);
   15022           0 :                 return CMD_WARNING_CONFIG_FAILED;
   15023             :         }
   15024             : 
   15025           0 :         XFREE(MTYPE_AS_LIST, bdistance->access_list);
   15026           0 :         bgp_distance_free(bdistance);
   15027             : 
   15028           0 :         bgp_dest_set_bgp_path_info(dest, NULL);
   15029           0 :         bgp_dest_unlock_node(dest);
   15030           0 :         bgp_dest_unlock_node(dest);
   15031             : 
   15032           0 :         return CMD_SUCCESS;
   15033             : }
   15034             : 
   15035             : /* Apply BGP information to distance method. */
   15036           8 : uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
   15037             :                            afi_t afi, safi_t safi, struct bgp *bgp)
   15038             : {
   15039           8 :         struct bgp_dest *dest;
   15040           8 :         struct prefix q = {0};
   15041           8 :         struct peer *peer;
   15042           8 :         struct bgp_distance *bdistance;
   15043           8 :         struct access_list *alist;
   15044           8 :         struct bgp_static *bgp_static;
   15045           8 :         struct bgp_path_info *bpi_ultimate;
   15046             : 
   15047           8 :         if (!bgp)
   15048             :                 return 0;
   15049             : 
   15050           8 :         peer = pinfo->peer;
   15051             : 
   15052           8 :         if (pinfo->attr->distance)
   15053             :                 return pinfo->attr->distance;
   15054             : 
   15055             :         /* get peer origin to calculate appropriate distance */
   15056           8 :         if (pinfo->sub_type == BGP_ROUTE_IMPORTED) {
   15057           0 :                 bpi_ultimate = bgp_get_imported_bpi_ultimate(pinfo);
   15058           0 :                 peer = bpi_ultimate->peer;
   15059             :         }
   15060             : 
   15061             :         /* Check source address.
   15062             :          * Note: for aggregate route, peer can have unspec af type.
   15063             :          */
   15064           8 :         if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
   15065           8 :             && !sockunion2hostprefix(&peer->su, &q))
   15066             :                 return 0;
   15067             : 
   15068           8 :         dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
   15069           8 :         if (dest) {
   15070           0 :                 bdistance = bgp_dest_get_bgp_distance_info(dest);
   15071           0 :                 bgp_dest_unlock_node(dest);
   15072             : 
   15073           0 :                 if (bdistance->access_list) {
   15074           0 :                         alist = access_list_lookup(afi, bdistance->access_list);
   15075           0 :                         if (alist
   15076           0 :                             && access_list_apply(alist, p) == FILTER_PERMIT)
   15077           0 :                                 return bdistance->distance;
   15078             :                 } else
   15079           0 :                         return bdistance->distance;
   15080             :         }
   15081             : 
   15082             :         /* Backdoor check. */
   15083           8 :         dest = bgp_node_lookup(bgp->route[afi][safi], p);
   15084           8 :         if (dest) {
   15085           0 :                 bgp_static = bgp_dest_get_bgp_static_info(dest);
   15086           0 :                 bgp_dest_unlock_node(dest);
   15087             : 
   15088           0 :                 if (bgp_static->backdoor) {
   15089           0 :                         if (bgp->distance_local[afi][safi])
   15090             :                                 return bgp->distance_local[afi][safi];
   15091             :                         else
   15092             :                                 return ZEBRA_IBGP_DISTANCE_DEFAULT;
   15093             :                 }
   15094             :         }
   15095             : 
   15096           8 :         if (peer->sort == BGP_PEER_EBGP) {
   15097           8 :                 if (bgp->distance_ebgp[afi][safi])
   15098             :                         return bgp->distance_ebgp[afi][safi];
   15099           8 :                 return ZEBRA_EBGP_DISTANCE_DEFAULT;
   15100           0 :         } else if (peer->sort == BGP_PEER_IBGP) {
   15101           0 :                 if (bgp->distance_ibgp[afi][safi])
   15102             :                         return bgp->distance_ibgp[afi][safi];
   15103             :                 return ZEBRA_IBGP_DISTANCE_DEFAULT;
   15104             :         } else {
   15105           0 :                 if (bgp->distance_local[afi][safi])
   15106             :                         return bgp->distance_local[afi][safi];
   15107             :                 return ZEBRA_IBGP_DISTANCE_DEFAULT;
   15108             :         }
   15109             : }
   15110             : 
   15111             : /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
   15112             :  * we should tell ZEBRA update the routes for a specific
   15113             :  * AFI/SAFI to reflect changes in RIB.
   15114             :  */
   15115           0 : static void bgp_announce_routes_distance_update(struct bgp *bgp,
   15116             :                                                 afi_t update_afi,
   15117             :                                                 safi_t update_safi)
   15118             : {
   15119           0 :         afi_t afi;
   15120           0 :         safi_t safi;
   15121             : 
   15122           0 :         FOREACH_AFI_SAFI (afi, safi) {
   15123           0 :                 if (!bgp_fibupd_safi(safi))
   15124           0 :                         continue;
   15125             : 
   15126           0 :                 if (afi != update_afi && safi != update_safi)
   15127           0 :                         continue;
   15128             : 
   15129           0 :                 if (BGP_DEBUG(zebra, ZEBRA))
   15130           0 :                         zlog_debug(
   15131             :                                 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
   15132             :                                 __func__, afi, safi);
   15133           0 :                 bgp_zebra_announce_table(bgp, afi, safi);
   15134             :         }
   15135           0 : }
   15136             : 
   15137           0 : DEFUN (bgp_distance,
   15138             :        bgp_distance_cmd,
   15139             :        "distance bgp (1-255) (1-255) (1-255)",
   15140             :        "Define an administrative distance\n"
   15141             :        "BGP distance\n"
   15142             :        "Distance for routes external to the AS\n"
   15143             :        "Distance for routes internal to the AS\n"
   15144             :        "Distance for local routes\n")
   15145             : {
   15146           0 :         VTY_DECLVAR_CONTEXT(bgp, bgp);
   15147           0 :         int idx_number = 2;
   15148           0 :         int idx_number_2 = 3;
   15149           0 :         int idx_number_3 = 4;
   15150           0 :         int distance_ebgp = atoi(argv[idx_number]->arg);
   15151           0 :         int distance_ibgp = atoi(argv[idx_number_2]->arg);
   15152           0 :         int distance_local = atoi(argv[idx_number_3]->arg);
   15153           0 :         afi_t afi;
   15154           0 :         safi_t safi;
   15155             : 
   15156           0 :         afi = bgp_node_afi(vty);
   15157           0 :         safi = bgp_node_safi(vty);
   15158             : 
   15159           0 :         if (bgp->distance_ebgp[afi][safi] != distance_ebgp
   15160           0 :             || bgp->distance_ibgp[afi][safi] != distance_ibgp
   15161           0 :             || bgp->distance_local[afi][safi] != distance_local) {
   15162           0 :                 bgp->distance_ebgp[afi][safi] = distance_ebgp;
   15163           0 :                 bgp->distance_ibgp[afi][safi] = distance_ibgp;
   15164           0 :                 bgp->distance_local[afi][safi] = distance_local;
   15165           0 :                 bgp_announce_routes_distance_update(bgp, afi, safi);
   15166             :         }
   15167             :         return CMD_SUCCESS;
   15168             : }
   15169             : 
   15170           0 : DEFUN (no_bgp_distance,
   15171             :        no_bgp_distance_cmd,
   15172             :        "no distance bgp [(1-255) (1-255) (1-255)]",
   15173             :        NO_STR
   15174             :        "Define an administrative distance\n"
   15175             :        "BGP distance\n"
   15176             :        "Distance for routes external to the AS\n"
   15177             :        "Distance for routes internal to the AS\n"
   15178             :        "Distance for local routes\n")
   15179             : {
   15180           0 :         VTY_DECLVAR_CONTEXT(bgp, bgp);
   15181           0 :         afi_t afi;
   15182           0 :         safi_t safi;
   15183             : 
   15184           0 :         afi = bgp_node_afi(vty);
   15185           0 :         safi = bgp_node_safi(vty);
   15186             : 
   15187           0 :         if (bgp->distance_ebgp[afi][safi] != 0
   15188           0 :             || bgp->distance_ibgp[afi][safi] != 0
   15189           0 :             || bgp->distance_local[afi][safi] != 0) {
   15190           0 :                 bgp->distance_ebgp[afi][safi] = 0;
   15191           0 :                 bgp->distance_ibgp[afi][safi] = 0;
   15192           0 :                 bgp->distance_local[afi][safi] = 0;
   15193           0 :                 bgp_announce_routes_distance_update(bgp, afi, safi);
   15194             :         }
   15195             :         return CMD_SUCCESS;
   15196             : }
   15197             : 
   15198             : 
   15199           0 : DEFUN (bgp_distance_source,
   15200             :        bgp_distance_source_cmd,
   15201             :        "distance (1-255) A.B.C.D/M",
   15202             :        "Define an administrative distance\n"
   15203             :        "Administrative distance\n"
   15204             :        "IP source prefix\n")
   15205             : {
   15206           0 :         int idx_number = 1;
   15207           0 :         int idx_ipv4_prefixlen = 2;
   15208           0 :         bgp_distance_set(vty, argv[idx_number]->arg,
   15209           0 :                          argv[idx_ipv4_prefixlen]->arg, NULL);
   15210           0 :         return CMD_SUCCESS;
   15211             : }
   15212             : 
   15213           0 : DEFUN (no_bgp_distance_source,
   15214             :        no_bgp_distance_source_cmd,
   15215             :        "no distance (1-255) A.B.C.D/M",
   15216             :        NO_STR
   15217             :        "Define an administrative distance\n"
   15218             :        "Administrative distance\n"
   15219             :        "IP source prefix\n")
   15220             : {
   15221           0 :         int idx_number = 2;
   15222           0 :         int idx_ipv4_prefixlen = 3;
   15223           0 :         bgp_distance_unset(vty, argv[idx_number]->arg,
   15224           0 :                            argv[idx_ipv4_prefixlen]->arg, NULL);
   15225           0 :         return CMD_SUCCESS;
   15226             : }
   15227             : 
   15228           0 : DEFUN (bgp_distance_source_access_list,
   15229             :        bgp_distance_source_access_list_cmd,
   15230             :        "distance (1-255) A.B.C.D/M WORD",
   15231             :        "Define an administrative distance\n"
   15232             :        "Administrative distance\n"
   15233             :        "IP source prefix\n"
   15234             :        "Access list name\n")
   15235             : {
   15236           0 :         int idx_number = 1;
   15237           0 :         int idx_ipv4_prefixlen = 2;
   15238           0 :         int idx_word = 3;
   15239           0 :         bgp_distance_set(vty, argv[idx_number]->arg,
   15240           0 :                          argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
   15241           0 :         return CMD_SUCCESS;
   15242             : }
   15243             : 
   15244           0 : DEFUN (no_bgp_distance_source_access_list,
   15245             :        no_bgp_distance_source_access_list_cmd,
   15246             :        "no distance (1-255) A.B.C.D/M WORD",
   15247             :        NO_STR
   15248             :        "Define an administrative distance\n"
   15249             :        "Administrative distance\n"
   15250             :        "IP source prefix\n"
   15251             :        "Access list name\n")
   15252             : {
   15253           0 :         int idx_number = 2;
   15254           0 :         int idx_ipv4_prefixlen = 3;
   15255           0 :         int idx_word = 4;
   15256           0 :         bgp_distance_unset(vty, argv[idx_number]->arg,
   15257           0 :                            argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
   15258           0 :         return CMD_SUCCESS;
   15259             : }
   15260             : 
   15261           0 : DEFUN (ipv6_bgp_distance_source,
   15262             :        ipv6_bgp_distance_source_cmd,
   15263             :        "distance (1-255) X:X::X:X/M",
   15264             :        "Define an administrative distance\n"
   15265             :        "Administrative distance\n"
   15266             :        "IP source prefix\n")
   15267             : {
   15268           0 :         bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
   15269           0 :         return CMD_SUCCESS;
   15270             : }
   15271             : 
   15272           0 : DEFUN (no_ipv6_bgp_distance_source,
   15273             :        no_ipv6_bgp_distance_source_cmd,
   15274             :        "no distance (1-255) X:X::X:X/M",
   15275             :        NO_STR
   15276             :        "Define an administrative distance\n"
   15277             :        "Administrative distance\n"
   15278             :        "IP source prefix\n")
   15279             : {
   15280           0 :         bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
   15281           0 :         return CMD_SUCCESS;
   15282             : }
   15283             : 
   15284           0 : DEFUN (ipv6_bgp_distance_source_access_list,
   15285             :        ipv6_bgp_distance_source_access_list_cmd,
   15286             :        "distance (1-255) X:X::X:X/M WORD",
   15287             :        "Define an administrative distance\n"
   15288             :        "Administrative distance\n"
   15289             :        "IP source prefix\n"
   15290             :        "Access list name\n")
   15291             : {
   15292           0 :         bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
   15293           0 :         return CMD_SUCCESS;
   15294             : }
   15295             : 
   15296           0 : DEFUN (no_ipv6_bgp_distance_source_access_list,
   15297             :        no_ipv6_bgp_distance_source_access_list_cmd,
   15298             :        "no distance (1-255) X:X::X:X/M WORD",
   15299             :        NO_STR
   15300             :        "Define an administrative distance\n"
   15301             :        "Administrative distance\n"
   15302             :        "IP source prefix\n"
   15303             :        "Access list name\n")
   15304             : {
   15305           0 :         bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
   15306           0 :         return CMD_SUCCESS;
   15307             : }
   15308             : 
   15309           0 : DEFUN (bgp_damp_set,
   15310             :        bgp_damp_set_cmd,
   15311             :        "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
   15312             :        "BGP Specific commands\n"
   15313             :        "Enable route-flap dampening\n"
   15314             :        "Half-life time for the penalty\n"
   15315             :        "Value to start reusing a route\n"
   15316             :        "Value to start suppressing a route\n"
   15317             :        "Maximum duration to suppress a stable route\n")
   15318             : {
   15319           0 :         VTY_DECLVAR_CONTEXT(bgp, bgp);
   15320           0 :         int idx_half_life = 2;
   15321           0 :         int idx_reuse = 3;
   15322           0 :         int idx_suppress = 4;
   15323           0 :         int idx_max_suppress = 5;
   15324           0 :         int half = DEFAULT_HALF_LIFE * 60;
   15325           0 :         int reuse = DEFAULT_REUSE;
   15326           0 :         int suppress = DEFAULT_SUPPRESS;
   15327           0 :         int max = 4 * half;
   15328             : 
   15329           0 :         if (argc == 6) {
   15330           0 :                 half = atoi(argv[idx_half_life]->arg) * 60;
   15331           0 :                 reuse = atoi(argv[idx_reuse]->arg);
   15332           0 :                 suppress = atoi(argv[idx_suppress]->arg);
   15333           0 :                 max = atoi(argv[idx_max_suppress]->arg) * 60;
   15334           0 :         } else if (argc == 3) {
   15335           0 :                 half = atoi(argv[idx_half_life]->arg) * 60;
   15336           0 :                 max = 4 * half;
   15337             :         }
   15338             : 
   15339             :         /*
   15340             :          * These can't be 0 but our SA doesn't understand the
   15341             :          * way our cli is constructed
   15342             :          */
   15343           0 :         assert(reuse);
   15344           0 :         assert(half);
   15345           0 :         if (suppress < reuse) {
   15346           0 :                 vty_out(vty,
   15347             :                         "Suppress value cannot be less than reuse value \n");
   15348           0 :                 return 0;
   15349             :         }
   15350             : 
   15351           0 :         return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
   15352             :                                reuse, suppress, max);
   15353             : }
   15354             : 
   15355           0 : DEFUN (bgp_damp_unset,
   15356             :        bgp_damp_unset_cmd,
   15357             :        "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
   15358             :        NO_STR
   15359             :        "BGP Specific commands\n"
   15360             :        "Enable route-flap dampening\n"
   15361             :        "Half-life time for the penalty\n"
   15362             :        "Value to start reusing a route\n"
   15363             :        "Value to start suppressing a route\n"
   15364             :        "Maximum duration to suppress a stable route\n")
   15365             : {
   15366           0 :         VTY_DECLVAR_CONTEXT(bgp, bgp);
   15367           0 :         return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
   15368             : }
   15369             : 
   15370             : /* Display specified route of BGP table. */
   15371           0 : static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
   15372             :                                 const char *ip_str, afi_t afi, safi_t safi,
   15373             :                                 struct prefix_rd *prd, int prefix_check)
   15374             : {
   15375           0 :         int ret;
   15376           0 :         struct prefix match;
   15377           0 :         struct bgp_dest *dest;
   15378           0 :         struct bgp_dest *rm;
   15379           0 :         struct bgp_path_info *pi;
   15380           0 :         struct bgp_path_info *pi_temp;
   15381           0 :         struct bgp *bgp;
   15382           0 :         struct bgp_table *table;
   15383             : 
   15384             :         /* BGP structure lookup. */
   15385           0 :         if (view_name) {
   15386           0 :                 bgp = bgp_lookup_by_name(view_name);
   15387           0 :                 if (bgp == NULL) {
   15388           0 :                         vty_out(vty, "%% Can't find BGP instance %s\n",
   15389             :                                 view_name);
   15390           0 :                         return CMD_WARNING;
   15391             :                 }
   15392             :         } else {
   15393           0 :                 bgp = bgp_get_default();
   15394           0 :                 if (bgp == NULL) {
   15395           0 :                         vty_out(vty, "%% No BGP process is configured\n");
   15396           0 :                         return CMD_WARNING;
   15397             :                 }
   15398             :         }
   15399             : 
   15400             :         /* Check IP address argument. */
   15401           0 :         ret = str2prefix(ip_str, &match);
   15402           0 :         if (!ret) {
   15403           0 :                 vty_out(vty, "%% address is malformed\n");
   15404           0 :                 return CMD_WARNING;
   15405             :         }
   15406             : 
   15407           0 :         match.family = afi2family(afi);
   15408             : 
   15409           0 :         if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
   15410           0 :             || (safi == SAFI_EVPN)) {
   15411           0 :                 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
   15412           0 :                      dest = bgp_route_next(dest)) {
   15413           0 :                         const struct prefix *dest_p = bgp_dest_get_prefix(dest);
   15414             : 
   15415           0 :                         if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
   15416           0 :                                 continue;
   15417           0 :                         table = bgp_dest_get_bgp_table_info(dest);
   15418           0 :                         if (!table)
   15419           0 :                                 continue;
   15420           0 :                         rm = bgp_node_match(table, &match);
   15421           0 :                         if (rm == NULL)
   15422           0 :                                 continue;
   15423             : 
   15424           0 :                         const struct prefix *rm_p = bgp_dest_get_prefix(dest);
   15425             : 
   15426           0 :                         if (!prefix_check
   15427           0 :                             || rm_p->prefixlen == match.prefixlen) {
   15428           0 :                                 pi = bgp_dest_get_bgp_path_info(rm);
   15429           0 :                                 while (pi) {
   15430           0 :                                         if (pi->extra && pi->extra->damp_info) {
   15431           0 :                                                 pi_temp = pi->next;
   15432           0 :                                                 bgp_damp_info_free(
   15433             :                                                         pi->extra->damp_info,
   15434             :                                                         1, afi, safi);
   15435           0 :                                                 pi = pi_temp;
   15436             :                                         } else
   15437           0 :                                                 pi = pi->next;
   15438             :                                 }
   15439             :                         }
   15440             : 
   15441           0 :                         bgp_dest_unlock_node(rm);
   15442             :                 }
   15443             :         } else {
   15444           0 :                 dest = bgp_node_match(bgp->rib[afi][safi], &match);
   15445           0 :                 if (dest != NULL) {
   15446           0 :                         const struct prefix *dest_p = bgp_dest_get_prefix(dest);
   15447             : 
   15448           0 :                         if (!prefix_check
   15449           0 :                             || dest_p->prefixlen == match.prefixlen) {
   15450           0 :                                 pi = bgp_dest_get_bgp_path_info(dest);
   15451           0 :                                 while (pi) {
   15452           0 :                                         if (pi->extra && pi->extra->damp_info) {
   15453           0 :                                                 pi_temp = pi->next;
   15454           0 :                                                 bgp_damp_info_free(
   15455             :                                                         pi->extra->damp_info,
   15456             :                                                         1, afi, safi);
   15457           0 :                                                 pi = pi_temp;
   15458             :                                         } else
   15459           0 :                                                 pi = pi->next;
   15460             :                                 }
   15461             :                         }
   15462             : 
   15463           0 :                         bgp_dest_unlock_node(dest);
   15464             :                 }
   15465             :         }
   15466             : 
   15467             :         return CMD_SUCCESS;
   15468             : }
   15469             : 
   15470           0 : DEFUN (clear_ip_bgp_dampening,
   15471             :        clear_ip_bgp_dampening_cmd,
   15472             :        "clear ip bgp dampening",
   15473             :        CLEAR_STR
   15474             :        IP_STR
   15475             :        BGP_STR
   15476             :        "Clear route flap dampening information\n")
   15477             : {
   15478           0 :         bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
   15479           0 :         return CMD_SUCCESS;
   15480             : }
   15481             : 
   15482           0 : DEFUN (clear_ip_bgp_dampening_prefix,
   15483             :        clear_ip_bgp_dampening_prefix_cmd,
   15484             :        "clear ip bgp dampening A.B.C.D/M",
   15485             :        CLEAR_STR
   15486             :        IP_STR
   15487             :        BGP_STR
   15488             :        "Clear route flap dampening information\n"
   15489             :        "IPv4 prefix\n")
   15490             : {
   15491           0 :         int idx_ipv4_prefixlen = 4;
   15492           0 :         return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
   15493             :                                     AFI_IP, SAFI_UNICAST, NULL, 1);
   15494             : }
   15495             : 
   15496           0 : DEFUN (clear_ip_bgp_dampening_address,
   15497             :        clear_ip_bgp_dampening_address_cmd,
   15498             :        "clear ip bgp dampening A.B.C.D",
   15499             :        CLEAR_STR
   15500             :        IP_STR
   15501             :        BGP_STR
   15502             :        "Clear route flap dampening information\n"
   15503             :        "Network to clear damping information\n")
   15504             : {
   15505           0 :         int idx_ipv4 = 4;
   15506           0 :         return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
   15507             :                                     SAFI_UNICAST, NULL, 0);
   15508             : }
   15509             : 
   15510           0 : DEFUN (clear_ip_bgp_dampening_address_mask,
   15511             :        clear_ip_bgp_dampening_address_mask_cmd,
   15512             :        "clear ip bgp dampening A.B.C.D A.B.C.D",
   15513             :        CLEAR_STR
   15514             :        IP_STR
   15515             :        BGP_STR
   15516             :        "Clear route flap dampening information\n"
   15517             :        "Network to clear damping information\n"
   15518             :        "Network mask\n")
   15519             : {
   15520           0 :         int idx_ipv4 = 4;
   15521           0 :         int idx_ipv4_2 = 5;
   15522           0 :         int ret;
   15523           0 :         char prefix_str[BUFSIZ];
   15524             : 
   15525           0 :         ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
   15526             :                                      prefix_str, sizeof(prefix_str));
   15527           0 :         if (!ret) {
   15528           0 :                 vty_out(vty, "%% Inconsistent address and mask\n");
   15529           0 :                 return CMD_WARNING;
   15530             :         }
   15531             : 
   15532           0 :         return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
   15533             :                                     NULL, 0);
   15534             : }
   15535             : 
   15536           0 : static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
   15537             : {
   15538           0 :        struct vty *vty = arg;
   15539           0 :        struct peer *peer = bucket->data;
   15540             : 
   15541           0 :        vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
   15542           0 : }
   15543             : 
   15544           0 : DEFUN (show_bgp_listeners,
   15545             :        show_bgp_listeners_cmd,
   15546             :        "show bgp listeners",
   15547             :        SHOW_STR
   15548             :        BGP_STR
   15549             :        "Display Listen Sockets and who created them\n")
   15550             : {
   15551           0 :         bgp_dump_listener_info(vty);
   15552             : 
   15553           0 :         return CMD_SUCCESS;
   15554             : }
   15555             : 
   15556           0 : DEFUN (show_bgp_peerhash,
   15557             :        show_bgp_peerhash_cmd,
   15558             :        "show bgp peerhash",
   15559             :        SHOW_STR
   15560             :        BGP_STR
   15561             :        "Display information about the BGP peerhash\n")
   15562             : {
   15563           0 :        struct list *instances = bm->bgp;
   15564           0 :        struct listnode *node;
   15565           0 :        struct bgp *bgp;
   15566             : 
   15567           0 :        for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
   15568           0 :                vty_out(vty, "BGP: %s\n", bgp->name);
   15569           0 :                hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
   15570             :                             vty);
   15571             :        }
   15572             : 
   15573           0 :        return CMD_SUCCESS;
   15574             : }
   15575             : 
   15576             : /* also used for encap safi */
   15577           0 : static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
   15578             :                                          afi_t afi, safi_t safi)
   15579             : {
   15580           0 :         struct bgp_dest *pdest;
   15581           0 :         struct bgp_dest *dest;
   15582           0 :         struct bgp_table *table;
   15583           0 :         const struct prefix *p;
   15584           0 :         const struct prefix_rd *prd;
   15585           0 :         struct bgp_static *bgp_static;
   15586           0 :         mpls_label_t label;
   15587             : 
   15588             :         /* Network configuration. */
   15589           0 :         for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
   15590           0 :              pdest = bgp_route_next(pdest)) {
   15591           0 :                 table = bgp_dest_get_bgp_table_info(pdest);
   15592           0 :                 if (!table)
   15593           0 :                         continue;
   15594             : 
   15595           0 :                 for (dest = bgp_table_top(table); dest;
   15596           0 :                      dest = bgp_route_next(dest)) {
   15597           0 :                         bgp_static = bgp_dest_get_bgp_static_info(dest);
   15598           0 :                         if (bgp_static == NULL)
   15599           0 :                                 continue;
   15600             : 
   15601           0 :                         p = bgp_dest_get_prefix(dest);
   15602           0 :                         prd = (const struct prefix_rd *)bgp_dest_get_prefix(
   15603             :                                 pdest);
   15604             : 
   15605             :                         /* "network" configuration display.  */
   15606           0 :                         label = decode_label(&bgp_static->label);
   15607             : 
   15608           0 :                         vty_out(vty, "  network %pFX rd %pRD", p, prd);
   15609           0 :                         if (safi == SAFI_MPLS_VPN)
   15610           0 :                                 vty_out(vty, " label %u", label);
   15611             : 
   15612           0 :                         if (bgp_static->rmap.name)
   15613           0 :                                 vty_out(vty, " route-map %s",
   15614             :                                         bgp_static->rmap.name);
   15615             : 
   15616           0 :                         if (bgp_static->backdoor)
   15617           0 :                                 vty_out(vty, " backdoor");
   15618             : 
   15619           0 :                         vty_out(vty, "\n");
   15620             :                 }
   15621             :         }
   15622           0 : }
   15623             : 
   15624           0 : static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
   15625             :                                           afi_t afi, safi_t safi)
   15626             : {
   15627           0 :         struct bgp_dest *pdest;
   15628           0 :         struct bgp_dest *dest;
   15629           0 :         struct bgp_table *table;
   15630           0 :         const struct prefix *p;
   15631           0 :         const struct prefix_rd *prd;
   15632           0 :         struct bgp_static *bgp_static;
   15633           0 :         char buf[PREFIX_STRLEN * 2];
   15634           0 :         char buf2[SU_ADDRSTRLEN];
   15635           0 :         char esi_buf[ESI_STR_LEN];
   15636             : 
   15637             :         /* Network configuration. */
   15638           0 :         for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
   15639           0 :              pdest = bgp_route_next(pdest)) {
   15640           0 :                 table = bgp_dest_get_bgp_table_info(pdest);
   15641           0 :                 if (!table)
   15642           0 :                         continue;
   15643             : 
   15644           0 :                 for (dest = bgp_table_top(table); dest;
   15645           0 :                      dest = bgp_route_next(dest)) {
   15646           0 :                         bgp_static = bgp_dest_get_bgp_static_info(dest);
   15647           0 :                         if (bgp_static == NULL)
   15648           0 :                                 continue;
   15649             : 
   15650           0 :                         char *macrouter = NULL;
   15651             : 
   15652           0 :                         if (bgp_static->router_mac)
   15653           0 :                                 macrouter = prefix_mac2str(
   15654             :                                         bgp_static->router_mac, NULL, 0);
   15655           0 :                         if (bgp_static->eth_s_id)
   15656           0 :                                 esi_to_str(bgp_static->eth_s_id,
   15657             :                                                 esi_buf, sizeof(esi_buf));
   15658           0 :                         p = bgp_dest_get_prefix(dest);
   15659           0 :                         prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
   15660             : 
   15661             :                         /* "network" configuration display.  */
   15662           0 :                         if (p->u.prefix_evpn.route_type == 5) {
   15663           0 :                                 char local_buf[PREFIX_STRLEN];
   15664             : 
   15665           0 :                                 uint8_t family = is_evpn_prefix_ipaddr_v4((
   15666             :                                                          struct prefix_evpn *)p)
   15667             :                                                          ? AF_INET
   15668             :                                                          : AF_INET6;
   15669           0 :                                 inet_ntop(family,
   15670           0 :                                           &p->u.prefix_evpn.prefix_addr.ip.ip
   15671             :                                                    .addr,
   15672             :                                           local_buf, sizeof(local_buf));
   15673           0 :                                 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
   15674             :                                          p->u.prefix_evpn.prefix_addr
   15675           0 :                                                  .ip_prefix_length);
   15676             :                         } else {
   15677           0 :                                 prefix2str(p, buf, sizeof(buf));
   15678             :                         }
   15679             : 
   15680           0 :                         if (bgp_static->gatewayIp.family == AF_INET
   15681           0 :                             || bgp_static->gatewayIp.family == AF_INET6)
   15682           0 :                                 inet_ntop(bgp_static->gatewayIp.family,
   15683           0 :                                           &bgp_static->gatewayIp.u.prefix, buf2,
   15684             :                                           sizeof(buf2));
   15685           0 :                         vty_out(vty,
   15686             :                                 "  network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n",
   15687           0 :                                 buf, prd, p->u.prefix_evpn.prefix_addr.eth_tag,
   15688             :                                 decode_label(&bgp_static->label), esi_buf, buf2,
   15689             :                                 macrouter);
   15690             : 
   15691           0 :                         XFREE(MTYPE_TMP, macrouter);
   15692             :                 }
   15693             :         }
   15694           0 : }
   15695             : 
   15696             : /* Configuration of static route announcement and aggregate
   15697             :    information. */
   15698           0 : void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
   15699             :                               safi_t safi)
   15700             : {
   15701           0 :         struct bgp_dest *dest;
   15702           0 :         const struct prefix *p;
   15703           0 :         struct bgp_static *bgp_static;
   15704           0 :         struct bgp_aggregate *bgp_aggregate;
   15705             : 
   15706           0 :         if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
   15707           0 :                 bgp_config_write_network_vpn(vty, bgp, afi, safi);
   15708           0 :                 return;
   15709             :         }
   15710             : 
   15711           0 :         if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
   15712           0 :                 bgp_config_write_network_evpn(vty, bgp, afi, safi);
   15713           0 :                 return;
   15714             :         }
   15715             : 
   15716             :         /* Network configuration. */
   15717           0 :         for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
   15718           0 :              dest = bgp_route_next(dest)) {
   15719           0 :                 bgp_static = bgp_dest_get_bgp_static_info(dest);
   15720           0 :                 if (bgp_static == NULL)
   15721           0 :                         continue;
   15722             : 
   15723           0 :                 p = bgp_dest_get_prefix(dest);
   15724             : 
   15725           0 :                 vty_out(vty, "  network %pFX", p);
   15726             : 
   15727           0 :                 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
   15728           0 :                         vty_out(vty, " label-index %u",
   15729             :                                 bgp_static->label_index);
   15730             : 
   15731           0 :                 if (bgp_static->rmap.name)
   15732           0 :                         vty_out(vty, " route-map %s", bgp_static->rmap.name);
   15733             : 
   15734           0 :                 if (bgp_static->backdoor)
   15735           0 :                         vty_out(vty, " backdoor");
   15736             : 
   15737           0 :                 vty_out(vty, "\n");
   15738             :         }
   15739             : 
   15740             :         /* Aggregate-address configuration. */
   15741           0 :         for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
   15742           0 :              dest = bgp_route_next(dest)) {
   15743           0 :                 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
   15744           0 :                 if (bgp_aggregate == NULL)
   15745           0 :                         continue;
   15746             : 
   15747           0 :                 p = bgp_dest_get_prefix(dest);
   15748             : 
   15749           0 :                 vty_out(vty, "  aggregate-address %pFX", p);
   15750             : 
   15751           0 :                 if (bgp_aggregate->as_set)
   15752           0 :                         vty_out(vty, " as-set");
   15753             : 
   15754           0 :                 if (bgp_aggregate->summary_only)
   15755           0 :                         vty_out(vty, " summary-only");
   15756             : 
   15757           0 :                 if (bgp_aggregate->rmap.name)
   15758           0 :                         vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
   15759             : 
   15760           0 :                 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
   15761           0 :                         vty_out(vty, " origin %s",
   15762             :                                 bgp_origin2str(bgp_aggregate->origin));
   15763             : 
   15764           0 :                 if (bgp_aggregate->match_med)
   15765           0 :                         vty_out(vty, " matching-MED-only");
   15766             : 
   15767           0 :                 if (bgp_aggregate->suppress_map_name)
   15768           0 :                         vty_out(vty, " suppress-map %s",
   15769             :                                 bgp_aggregate->suppress_map_name);
   15770             : 
   15771           0 :                 vty_out(vty, "\n");
   15772             :         }
   15773             : }
   15774             : 
   15775           0 : void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
   15776             :                                safi_t safi)
   15777             : {
   15778           0 :         struct bgp_dest *dest;
   15779           0 :         struct bgp_distance *bdistance;
   15780             : 
   15781             :         /* Distance configuration. */
   15782           0 :         if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
   15783           0 :             && bgp->distance_local[afi][safi]
   15784           0 :             && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
   15785           0 :                 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
   15786           0 :                 || bgp->distance_local[afi][safi]
   15787             :                            != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
   15788           0 :                 vty_out(vty, "  distance bgp %d %d %d\n",
   15789             :                         bgp->distance_ebgp[afi][safi],
   15790             :                         bgp->distance_ibgp[afi][safi],
   15791             :                         bgp->distance_local[afi][safi]);
   15792             :         }
   15793             : 
   15794           0 :         for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
   15795           0 :              dest = bgp_route_next(dest)) {
   15796           0 :                 bdistance = bgp_dest_get_bgp_distance_info(dest);
   15797           0 :                 if (bdistance != NULL)
   15798           0 :                         vty_out(vty, "  distance %d %pBD %s\n",
   15799           0 :                                 bdistance->distance, dest,
   15800           0 :                                 bdistance->access_list ? bdistance->access_list
   15801             :                                                        : "");
   15802             :         }
   15803           0 : }
   15804             : 
   15805             : /* Allocate routing table structure and install commands. */
   15806           3 : void bgp_route_init(void)
   15807             : {
   15808           3 :         afi_t afi;
   15809           3 :         safi_t safi;
   15810             : 
   15811             :         /* Init BGP distance table. */
   15812          75 :         FOREACH_AFI_SAFI (afi, safi)
   15813          63 :                 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
   15814             : 
   15815             :         /* IPv4 BGP commands. */
   15816           3 :         install_element(BGP_NODE, &bgp_table_map_cmd);
   15817           3 :         install_element(BGP_NODE, &bgp_network_cmd);
   15818           3 :         install_element(BGP_NODE, &no_bgp_table_map_cmd);
   15819             : 
   15820           3 :         install_element(BGP_NODE, &aggregate_addressv4_cmd);
   15821             : 
   15822             :         /* IPv4 unicast configuration.  */
   15823           3 :         install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
   15824           3 :         install_element(BGP_IPV4_NODE, &bgp_network_cmd);
   15825           3 :         install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
   15826             : 
   15827           3 :         install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
   15828             : 
   15829             :         /* IPv4 multicast configuration.  */
   15830           3 :         install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
   15831           3 :         install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
   15832           3 :         install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
   15833           3 :         install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
   15834             : 
   15835             :         /* IPv4 labeled-unicast configuration.  */
   15836           3 :         install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
   15837           3 :         install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
   15838             : 
   15839           3 :         install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
   15840           3 :         install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
   15841           3 :         install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
   15842           3 :         install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
   15843           3 :         install_element(VIEW_NODE, &show_ip_bgp_cmd);
   15844           3 :         install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
   15845           3 :         install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
   15846           3 :         install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
   15847             : 
   15848           3 :         install_element(VIEW_NODE,
   15849             :                         &show_ip_bgp_instance_neighbor_advertised_route_cmd);
   15850           3 :         install_element(VIEW_NODE,
   15851             :                         &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
   15852           3 :         install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
   15853           3 :         install_element(VIEW_NODE,
   15854             :                         &show_ip_bgp_neighbor_received_prefix_filter_cmd);
   15855             : #ifdef KEEP_OLD_VPN_COMMANDS
   15856             :         install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
   15857             : #endif /* KEEP_OLD_VPN_COMMANDS */
   15858           3 :         install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
   15859           3 :         install_element(VIEW_NODE,
   15860             :                         &show_bgp_l2vpn_evpn_route_prefix_cmd);
   15861             : 
   15862             :         /* BGP dampening clear commands */
   15863           3 :         install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
   15864           3 :         install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
   15865             : 
   15866           3 :         install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
   15867           3 :         install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
   15868             : 
   15869             :         /* prefix count */
   15870           3 :         install_element(ENABLE_NODE,
   15871             :                         &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
   15872             : #ifdef KEEP_OLD_VPN_COMMANDS
   15873             :         install_element(ENABLE_NODE,
   15874             :                         &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
   15875             : #endif /* KEEP_OLD_VPN_COMMANDS */
   15876             : 
   15877             :         /* New config IPv6 BGP commands.  */
   15878           3 :         install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
   15879           3 :         install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
   15880           3 :         install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
   15881             : 
   15882           3 :         install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
   15883             : 
   15884           3 :         install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
   15885             : 
   15886             :         /* IPv6 labeled unicast address family. */
   15887           3 :         install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
   15888           3 :         install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
   15889             : 
   15890           3 :         install_element(BGP_NODE, &bgp_distance_cmd);
   15891           3 :         install_element(BGP_NODE, &no_bgp_distance_cmd);
   15892           3 :         install_element(BGP_NODE, &bgp_distance_source_cmd);
   15893           3 :         install_element(BGP_NODE, &no_bgp_distance_source_cmd);
   15894           3 :         install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
   15895           3 :         install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
   15896           3 :         install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
   15897           3 :         install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
   15898           3 :         install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
   15899           3 :         install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
   15900           3 :         install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
   15901           3 :         install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
   15902           3 :         install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
   15903           3 :         install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
   15904           3 :         install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
   15905           3 :         install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
   15906           3 :         install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
   15907           3 :         install_element(BGP_IPV4M_NODE,
   15908             :                         &no_bgp_distance_source_access_list_cmd);
   15909           3 :         install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
   15910           3 :         install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
   15911           3 :         install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
   15912           3 :         install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
   15913           3 :         install_element(BGP_IPV6_NODE,
   15914             :                         &ipv6_bgp_distance_source_access_list_cmd);
   15915           3 :         install_element(BGP_IPV6_NODE,
   15916             :                         &no_ipv6_bgp_distance_source_access_list_cmd);
   15917           3 :         install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
   15918           3 :         install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
   15919           3 :         install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
   15920           3 :         install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
   15921           3 :         install_element(BGP_IPV6M_NODE,
   15922             :                         &ipv6_bgp_distance_source_access_list_cmd);
   15923           3 :         install_element(BGP_IPV6M_NODE,
   15924             :                         &no_ipv6_bgp_distance_source_access_list_cmd);
   15925             : 
   15926             :         /* BGP dampening */
   15927           3 :         install_element(BGP_NODE, &bgp_damp_set_cmd);
   15928           3 :         install_element(BGP_NODE, &bgp_damp_unset_cmd);
   15929           3 :         install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
   15930           3 :         install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
   15931           3 :         install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
   15932           3 :         install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
   15933           3 :         install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
   15934           3 :         install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
   15935           3 :         install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
   15936           3 :         install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
   15937           3 :         install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
   15938           3 :         install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
   15939           3 :         install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
   15940           3 :         install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
   15941             : 
   15942             :         /* Large Communities */
   15943           3 :         install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
   15944           3 :         install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
   15945             : 
   15946             :         /* show bgp ipv4 flowspec detailed */
   15947           3 :         install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
   15948             : 
   15949           3 :         install_element(VIEW_NODE, &show_bgp_listeners_cmd);
   15950           3 :         install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
   15951           3 : }
   15952             : 
   15953           3 : void bgp_route_finish(void)
   15954             : {
   15955           3 :         afi_t afi;
   15956           3 :         safi_t safi;
   15957             : 
   15958          75 :         FOREACH_AFI_SAFI (afi, safi) {
   15959          63 :                 bgp_table_unlock(bgp_distance_table[afi][safi]);
   15960          63 :                 bgp_distance_table[afi][safi] = NULL;
   15961             :         }
   15962           3 : }

Generated by: LCOV version v1.16-topotato