back to topotato report
topotato coverage report
Current view: top level - bgpd - bgp_nexthop.c (source / functions) Hit Total Coverage
Test: test_bgp_aspath_zero.py::BGPAggregatorZero Lines: 188 774 24.3 %
Date: 2023-02-24 18:36:48 Functions: 20 51 39.2 %

          Line data    Source code
       1             : /* BGP nexthop scan
       2             :  * Copyright (C) 2000 Kunihiro Ishiguro
       3             :  *
       4             :  * This file is part of GNU Zebra.
       5             :  *
       6             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by the
       8             :  * Free Software Foundation; either version 2, or (at your option) any
       9             :  * later version.
      10             :  *
      11             :  * GNU Zebra is distributed in the hope that it will be useful, but
      12             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along
      17             :  * with this program; see the file COPYING; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #include <zebra.h>
      22             : 
      23             : #include "command.h"
      24             : #include "thread.h"
      25             : #include "prefix.h"
      26             : #include "lib/json.h"
      27             : #include "zclient.h"
      28             : #include "stream.h"
      29             : #include "network.h"
      30             : #include "log.h"
      31             : #include "memory.h"
      32             : #include "hash.h"
      33             : #include "jhash.h"
      34             : #include "nexthop.h"
      35             : #include "queue.h"
      36             : #include "filter.h"
      37             : #include "printfrr.h"
      38             : 
      39             : #include "bgpd/bgpd.h"
      40             : #include "bgpd/bgp_route.h"
      41             : #include "bgpd/bgp_attr.h"
      42             : #include "bgpd/bgp_nexthop.h"
      43             : #include "bgpd/bgp_nht.h"
      44             : #include "bgpd/bgp_debug.h"
      45             : #include "bgpd/bgp_damp.h"
      46             : #include "bgpd/bgp_fsm.h"
      47             : #include "bgpd/bgp_vty.h"
      48             : #include "bgpd/bgp_rd.h"
      49             : 
      50           6 : DEFINE_MTYPE_STATIC(BGPD, MARTIAN_STRING, "BGP Martian Addr Intf String");
      51             : 
      52           8 : int bgp_nexthop_cache_compare(const struct bgp_nexthop_cache *a,
      53             :                               const struct bgp_nexthop_cache *b)
      54             : {
      55           8 :         if (a->srte_color < b->srte_color)
      56             :                 return -1;
      57           8 :         if (a->srte_color > b->srte_color)
      58             :                 return 1;
      59             : 
      60           8 :         if (a->ifindex < b->ifindex)
      61             :                 return -1;
      62           8 :         if (a->ifindex > b->ifindex)
      63             :                 return 1;
      64             : 
      65           8 :         return prefix_cmp(&a->prefix, &b->prefix);
      66             : }
      67             : 
      68           2 : void bnc_nexthop_free(struct bgp_nexthop_cache *bnc)
      69             : {
      70           1 :         nexthops_free(bnc->nexthop);
      71           1 : }
      72             : 
      73           1 : struct bgp_nexthop_cache *bnc_new(struct bgp_nexthop_cache_head *tree,
      74             :                                   struct prefix *prefix, uint32_t srte_color,
      75             :                                   ifindex_t ifindex)
      76             : {
      77           1 :         struct bgp_nexthop_cache *bnc;
      78             : 
      79           1 :         bnc = XCALLOC(MTYPE_BGP_NEXTHOP_CACHE,
      80             :                       sizeof(struct bgp_nexthop_cache));
      81           1 :         bnc->prefix = *prefix;
      82           1 :         bnc->ifindex = ifindex;
      83           1 :         bnc->srte_color = srte_color;
      84           1 :         bnc->tree = tree;
      85           1 :         LIST_INIT(&(bnc->paths));
      86           1 :         bgp_nexthop_cache_add(tree, bnc);
      87             : 
      88           1 :         return bnc;
      89             : }
      90             : 
      91           1 : bool bnc_existing_for_prefix(struct bgp_nexthop_cache *bnc)
      92             : {
      93           1 :         struct bgp_nexthop_cache *bnc_tmp;
      94             : 
      95           4 :         frr_each (bgp_nexthop_cache, bnc->tree, bnc_tmp) {
      96           1 :                 if (bnc_tmp == bnc)
      97           1 :                         continue;
      98           0 :                 if (prefix_cmp(&bnc->prefix, &bnc_tmp->prefix) == 0)
      99             :                         return true;
     100             :         }
     101             :         return false;
     102             : }
     103             : 
     104           1 : void bnc_free(struct bgp_nexthop_cache *bnc)
     105             : {
     106           1 :         bnc_nexthop_free(bnc);
     107           1 :         bgp_nexthop_cache_del(bnc->tree, bnc);
     108           1 :         XFREE(MTYPE_BGP_NEXTHOP_CACHE, bnc);
     109           1 : }
     110             : 
     111          10 : struct bgp_nexthop_cache *bnc_find(struct bgp_nexthop_cache_head *tree,
     112             :                                    struct prefix *prefix, uint32_t srte_color,
     113             :                                    ifindex_t ifindex)
     114             : {
     115          10 :         struct bgp_nexthop_cache bnc = {};
     116             : 
     117          10 :         if (!tree)
     118             :                 return NULL;
     119             : 
     120          10 :         bnc.prefix = *prefix;
     121          10 :         bnc.srte_color = srte_color;
     122          10 :         bnc.ifindex = ifindex;
     123          10 :         return bgp_nexthop_cache_find(tree, &bnc);
     124             : }
     125             : 
     126             : /* Reset and free all BGP nexthop cache. */
     127           0 : static void bgp_nexthop_cache_reset(struct bgp_nexthop_cache_head *tree)
     128             : {
     129           0 :         struct bgp_nexthop_cache *bnc;
     130             : 
     131           0 :         while (bgp_nexthop_cache_count(tree) > 0) {
     132           0 :                 bnc = bgp_nexthop_cache_first(tree);
     133             : 
     134           0 :                 while (!LIST_EMPTY(&(bnc->paths))) {
     135           0 :                         struct bgp_path_info *path = LIST_FIRST(&(bnc->paths));
     136             : 
     137           0 :                         path_nh_map(path, bnc, false);
     138             :                 }
     139             : 
     140           0 :                 bnc_free(bnc);
     141             :         }
     142           0 : }
     143             : 
     144           0 : static void *bgp_tip_hash_alloc(void *p)
     145             : {
     146           0 :         const struct in_addr *val = (const struct in_addr *)p;
     147           0 :         struct tip_addr *addr;
     148             : 
     149           0 :         addr = XMALLOC(MTYPE_TIP_ADDR, sizeof(struct tip_addr));
     150           0 :         addr->refcnt = 0;
     151           0 :         addr->addr.s_addr = val->s_addr;
     152             : 
     153           0 :         return addr;
     154             : }
     155             : 
     156           0 : static void bgp_tip_hash_free(void *addr)
     157             : {
     158           0 :         XFREE(MTYPE_TIP_ADDR, addr);
     159           0 : }
     160             : 
     161           0 : static unsigned int bgp_tip_hash_key_make(const void *p)
     162             : {
     163           0 :         const struct tip_addr *addr = p;
     164             : 
     165           0 :         return jhash_1word(addr->addr.s_addr, 0);
     166             : }
     167             : 
     168           0 : static bool bgp_tip_hash_cmp(const void *p1, const void *p2)
     169             : {
     170           0 :         const struct tip_addr *addr1 = p1;
     171           0 :         const struct tip_addr *addr2 = p2;
     172             : 
     173           0 :         return addr1->addr.s_addr == addr2->addr.s_addr;
     174             : }
     175             : 
     176           1 : void bgp_tip_hash_init(struct bgp *bgp)
     177             : {
     178           1 :         bgp->tip_hash = hash_create(bgp_tip_hash_key_make, bgp_tip_hash_cmp,
     179             :                                     "BGP TIP hash");
     180           1 : }
     181             : 
     182           0 : void bgp_tip_hash_destroy(struct bgp *bgp)
     183             : {
     184           0 :         if (bgp->tip_hash == NULL)
     185             :                 return;
     186           0 :         hash_clean(bgp->tip_hash, bgp_tip_hash_free);
     187           0 :         hash_free(bgp->tip_hash);
     188           0 :         bgp->tip_hash = NULL;
     189             : }
     190             : 
     191             : /* Add/Update Tunnel-IP entry of bgp martian next-hop table.
     192             :  *
     193             :  * Returns true only if we add a _new_ TIP so the caller knows that an
     194             :  * actionable change has occurred. If we find an existing TIP then we
     195             :  * only need to update the refcnt, since the collection of known TIPs
     196             :  * has not changed.
     197             :  */
     198           0 : bool bgp_tip_add(struct bgp *bgp, struct in_addr *tip)
     199             : {
     200           0 :         struct tip_addr tmp;
     201           0 :         struct tip_addr *addr;
     202           0 :         bool tip_added = false;
     203             : 
     204           0 :         tmp.addr = *tip;
     205             : 
     206           0 :         addr = hash_lookup(bgp->tip_hash, &tmp);
     207           0 :         if (!addr) {
     208           0 :                 addr = hash_get(bgp->tip_hash, &tmp, bgp_tip_hash_alloc);
     209           0 :                 tip_added = true;
     210             :         }
     211             : 
     212           0 :         addr->refcnt++;
     213             : 
     214           0 :         return tip_added;
     215             : }
     216             : 
     217           0 : void bgp_tip_del(struct bgp *bgp, struct in_addr *tip)
     218             : {
     219           0 :         struct tip_addr tmp;
     220           0 :         struct tip_addr *addr;
     221             : 
     222           0 :         tmp.addr = *tip;
     223             : 
     224           0 :         addr = hash_lookup(bgp->tip_hash, &tmp);
     225             :         /* may have been deleted earlier by bgp_interface_down() */
     226           0 :         if (addr == NULL)
     227           0 :                 return;
     228             : 
     229           0 :         addr->refcnt--;
     230             : 
     231           0 :         if (addr->refcnt == 0) {
     232           0 :                 hash_release(bgp->tip_hash, addr);
     233           0 :                 XFREE(MTYPE_TIP_ADDR, addr);
     234             :         }
     235             : }
     236             : 
     237             : /* BGP own address structure */
     238             : struct bgp_addr {
     239             :         struct prefix p;
     240             :         struct list *ifp_name_list;
     241             : };
     242             : 
     243           0 : static void show_address_entry(struct hash_bucket *bucket, void *args)
     244             : {
     245           0 :         struct vty *vty = (struct vty *)args;
     246           0 :         struct bgp_addr *addr = (struct bgp_addr *)bucket->data;
     247           0 :         char *name;
     248           0 :         struct listnode *node;
     249           0 :         char str[INET6_ADDRSTRLEN] = {0};
     250             : 
     251           0 :         vty_out(vty, "addr: %s, count: %d : ",
     252           0 :                 inet_ntop(addr->p.family, &(addr->p.u.prefix),
     253             :                           str, INET6_ADDRSTRLEN),
     254           0 :                 addr->ifp_name_list->count);
     255             : 
     256           0 :         for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
     257           0 :                 vty_out(vty, " %s,", name);
     258             :         }
     259             : 
     260           0 :         vty_out(vty, "\n");
     261           0 : }
     262             : 
     263           0 : void bgp_nexthop_show_address_hash(struct vty *vty, struct bgp *bgp)
     264             : {
     265           0 :         hash_iterate(bgp->address_hash,
     266             :                      (void (*)(struct hash_bucket *, void *))show_address_entry,
     267             :                      vty);
     268           0 : }
     269             : 
     270           0 : static void bgp_address_hash_string_del(void *val)
     271             : {
     272           0 :         char *data = val;
     273             : 
     274           0 :         XFREE(MTYPE_MARTIAN_STRING, data);
     275           0 : }
     276             : 
     277           4 : static void *bgp_address_hash_alloc(void *p)
     278             : {
     279           4 :         struct bgp_addr *copy_addr = p;
     280           4 :         struct bgp_addr *addr = NULL;
     281             : 
     282           4 :         addr = XMALLOC(MTYPE_BGP_ADDR, sizeof(struct bgp_addr));
     283           4 :         prefix_copy(&addr->p, &copy_addr->p);
     284             : 
     285           4 :         addr->ifp_name_list = list_new();
     286           4 :         addr->ifp_name_list->del = bgp_address_hash_string_del;
     287             : 
     288           4 :         return addr;
     289             : }
     290             : 
     291           0 : static void bgp_address_hash_free(void *data)
     292             : {
     293           0 :         struct bgp_addr *addr = data;
     294             : 
     295           0 :         list_delete(&addr->ifp_name_list);
     296           0 :         XFREE(MTYPE_BGP_ADDR, addr);
     297           0 : }
     298             : 
     299          21 : static unsigned int bgp_address_hash_key_make(const void *p)
     300             : {
     301          21 :         const struct bgp_addr *addr = p;
     302             : 
     303          21 :         return prefix_hash_key(&addr->p);
     304             : }
     305             : 
     306          16 : static bool bgp_address_hash_cmp(const void *p1, const void *p2)
     307             : {
     308          16 :         const struct bgp_addr *addr1 = p1;
     309          16 :         const struct bgp_addr *addr2 = p2;
     310             : 
     311          16 :         return prefix_same(&addr1->p, &addr2->p);
     312             : }
     313             : 
     314           1 : void bgp_address_init(struct bgp *bgp)
     315             : {
     316           2 :         bgp->address_hash =
     317           1 :                 hash_create(bgp_address_hash_key_make, bgp_address_hash_cmp,
     318             :                                 "BGP Connected Address Hash");
     319           1 : }
     320             : 
     321           0 : void bgp_address_destroy(struct bgp *bgp)
     322             : {
     323           0 :         if (bgp->address_hash == NULL)
     324             :                 return;
     325           0 :         hash_clean(bgp->address_hash, bgp_address_hash_free);
     326           0 :         hash_free(bgp->address_hash);
     327           0 :         bgp->address_hash = NULL;
     328             : }
     329             : 
     330          12 : static void bgp_address_add(struct bgp *bgp, struct connected *ifc,
     331             :                             struct prefix *p)
     332             : {
     333          12 :         struct bgp_addr tmp;
     334          12 :         struct bgp_addr *addr;
     335          12 :         struct listnode *node;
     336          12 :         char *name;
     337             : 
     338          12 :         tmp.p = *p;
     339             : 
     340          12 :         if (tmp.p.family == AF_INET)
     341           6 :                 tmp.p.prefixlen = IPV4_MAX_BITLEN;
     342           6 :         else if (tmp.p.family == AF_INET6)
     343           6 :                 tmp.p.prefixlen = IPV6_MAX_BITLEN;
     344             : 
     345          12 :         addr = hash_get(bgp->address_hash, &tmp, bgp_address_hash_alloc);
     346             : 
     347          24 :         for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
     348           8 :                 if (strcmp(ifc->ifp->name, name) == 0)
     349             :                         break;
     350             :         }
     351          12 :         if (!node) {
     352           4 :                 name = XSTRDUP(MTYPE_MARTIAN_STRING, ifc->ifp->name);
     353           4 :                 listnode_add(addr->ifp_name_list, name);
     354             :         }
     355          12 : }
     356             : 
     357           4 : static void bgp_address_del(struct bgp *bgp, struct connected *ifc,
     358             :                             struct prefix *p)
     359             : {
     360           4 :         struct bgp_addr tmp;
     361           4 :         struct bgp_addr *addr;
     362           4 :         struct listnode *node;
     363           4 :         char *name;
     364             : 
     365           4 :         tmp.p = *p;
     366             : 
     367           4 :         if (tmp.p.family == AF_INET)
     368           2 :                 tmp.p.prefixlen = IPV4_MAX_BITLEN;
     369           2 :         else if (tmp.p.family == AF_INET6)
     370           2 :                 tmp.p.prefixlen = IPV6_MAX_BITLEN;
     371             : 
     372           4 :         addr = hash_lookup(bgp->address_hash, &tmp);
     373             :         /* may have been deleted earlier by bgp_interface_down() */
     374           4 :         if (addr == NULL)
     375           0 :                 return;
     376             : 
     377           8 :         for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
     378           4 :                 if (strcmp(ifc->ifp->name, name) == 0)
     379             :                         break;
     380             :         }
     381             : 
     382           4 :         if (node) {
     383           4 :                 list_delete_node(addr->ifp_name_list, node);
     384           4 :                 XFREE(MTYPE_MARTIAN_STRING, name);
     385             :         }
     386             : 
     387           4 :         if (addr->ifp_name_list->count == 0) {
     388           4 :                 hash_release(bgp->address_hash, addr);
     389           4 :                 list_delete(&addr->ifp_name_list);
     390           4 :                 XFREE(MTYPE_BGP_ADDR, addr);
     391             :         }
     392             : }
     393             : 
     394             : 
     395             : struct bgp_connected_ref {
     396             :         unsigned int refcnt;
     397             : };
     398             : 
     399          13 : void bgp_connected_add(struct bgp *bgp, struct connected *ifc)
     400             : {
     401          13 :         struct prefix p;
     402          13 :         struct prefix *addr;
     403          13 :         struct bgp_dest *dest;
     404          13 :         struct bgp_connected_ref *bc;
     405          13 :         struct listnode *node, *nnode;
     406          13 :         struct peer *peer;
     407             : 
     408          13 :         addr = ifc->address;
     409             : 
     410          13 :         p = *(CONNECTED_PREFIX(ifc));
     411          13 :         if (addr->family == AF_INET) {
     412           6 :                 apply_mask_ipv4((struct prefix_ipv4 *)&p);
     413             : 
     414           6 :                 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
     415           1 :                         return;
     416             : 
     417           6 :                 bgp_address_add(bgp, ifc, addr);
     418             : 
     419           6 :                 dest = bgp_node_get(bgp->connected_table[AFI_IP], &p);
     420           6 :                 bc = bgp_dest_get_bgp_connected_ref_info(dest);
     421           6 :                 if (bc)
     422           4 :                         bc->refcnt++;
     423             :                 else {
     424           2 :                         bc = XCALLOC(MTYPE_BGP_CONN,
     425             :                                      sizeof(struct bgp_connected_ref));
     426           2 :                         bc->refcnt = 1;
     427           2 :                         bgp_dest_set_bgp_connected_ref_info(dest, bc);
     428             :                 }
     429             : 
     430          18 :                 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
     431           6 :                         if (peer->conf_if
     432           0 :                             && (strcmp(peer->conf_if, ifc->ifp->name) == 0)
     433           0 :                             && !peer_established(peer)
     434           0 :                             && !CHECK_FLAG(peer->flags,
     435             :                                            PEER_FLAG_IFPEER_V6ONLY)) {
     436           0 :                                 if (peer_active(peer))
     437           0 :                                         BGP_EVENT_ADD(peer, BGP_Stop);
     438           0 :                                 BGP_EVENT_ADD(peer, BGP_Start);
     439             :                         }
     440             :                 }
     441           7 :         } else if (addr->family == AF_INET6) {
     442           7 :                 apply_mask_ipv6((struct prefix_ipv6 *)&p);
     443             : 
     444           7 :                 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
     445             :                         return;
     446             : 
     447           7 :                 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
     448             :                         return;
     449             : 
     450           6 :                 bgp_address_add(bgp, ifc, addr);
     451             : 
     452           6 :                 dest = bgp_node_get(bgp->connected_table[AFI_IP6], &p);
     453             : 
     454           6 :                 bc = bgp_dest_get_bgp_connected_ref_info(dest);
     455           6 :                 if (bc)
     456           4 :                         bc->refcnt++;
     457             :                 else {
     458           2 :                         bc = XCALLOC(MTYPE_BGP_CONN,
     459             :                                      sizeof(struct bgp_connected_ref));
     460           2 :                         bc->refcnt = 1;
     461          12 :                         bgp_dest_set_bgp_connected_ref_info(dest, bc);
     462             :                 }
     463             :         }
     464             : }
     465             : 
     466           5 : void bgp_connected_delete(struct bgp *bgp, struct connected *ifc)
     467             : {
     468           5 :         struct prefix p;
     469           5 :         struct prefix *addr;
     470           5 :         struct bgp_dest *dest = NULL;
     471           5 :         struct bgp_connected_ref *bc;
     472             : 
     473           5 :         addr = ifc->address;
     474             : 
     475           5 :         p = *(CONNECTED_PREFIX(ifc));
     476           5 :         apply_mask(&p);
     477           5 :         if (addr->family == AF_INET) {
     478           2 :                 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
     479           1 :                         return;
     480             : 
     481           2 :                 bgp_address_del(bgp, ifc, addr);
     482             : 
     483           2 :                 dest = bgp_node_lookup(bgp->connected_table[AFI_IP], &p);
     484           3 :         } else if (addr->family == AF_INET6) {
     485           3 :                 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
     486             :                         return;
     487             : 
     488           3 :                 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
     489             :                         return;
     490             : 
     491           2 :                 bgp_address_del(bgp, ifc, addr);
     492             : 
     493           2 :                 dest = bgp_node_lookup(bgp->connected_table[AFI_IP6], &p);
     494             :         }
     495             : 
     496           4 :         if (!dest)
     497           0 :                 return;
     498             : 
     499           4 :         bc = bgp_dest_get_bgp_connected_ref_info(dest);
     500           4 :         bc->refcnt--;
     501           4 :         if (bc->refcnt == 0) {
     502           0 :                 XFREE(MTYPE_BGP_CONN, bc);
     503           0 :                 bgp_dest_set_bgp_connected_ref_info(dest, NULL);
     504             :         }
     505           4 :         bgp_dest_unlock_node(dest);
     506           4 :         bgp_dest_unlock_node(dest);
     507             : }
     508             : 
     509           0 : static void bgp_connected_cleanup(struct route_table *table,
     510             :                                   struct route_node *rn)
     511             : {
     512           0 :         struct bgp_connected_ref *bc;
     513           0 :         struct bgp_dest *bn = bgp_dest_from_rnode(rn);
     514             : 
     515           0 :         bc = bgp_dest_get_bgp_connected_ref_info(bn);
     516           0 :         if (!bc)
     517             :                 return;
     518             : 
     519           0 :         XFREE(MTYPE_BGP_CONN, bc);
     520           0 :         bgp_dest_set_bgp_connected_ref_info(bn, NULL);
     521             : }
     522             : 
     523           1 : bool bgp_nexthop_self(struct bgp *bgp, afi_t afi, uint8_t type,
     524             :                       uint8_t sub_type, struct attr *attr,
     525             :                       struct bgp_dest *dest)
     526             : {
     527           1 :         uint8_t new_afi = afi == AFI_IP ? AF_INET : AF_INET6;
     528           1 :         struct bgp_addr tmp_addr = {{0}}, *addr = NULL;
     529           1 :         struct tip_addr tmp_tip, *tip = NULL;
     530           1 :         const struct prefix *p = bgp_dest_get_prefix(dest);
     531           1 :         bool is_bgp_static_route =
     532           1 :                 ((type == ZEBRA_ROUTE_BGP) && (sub_type == BGP_ROUTE_STATIC))
     533             :                         ? true
     534           1 :                         : false;
     535             : 
     536           1 :         if (!is_bgp_static_route)
     537           1 :                 new_afi = BGP_ATTR_NEXTHOP_AFI_IP6(attr) ? AF_INET6 : AF_INET;
     538             : 
     539           1 :         tmp_addr.p.family = new_afi;
     540           1 :         switch (new_afi) {
     541           1 :         case AF_INET:
     542           1 :                 if (is_bgp_static_route) {
     543           0 :                         tmp_addr.p.u.prefix4 = p->u.prefix4;
     544           0 :                         tmp_addr.p.prefixlen = p->prefixlen;
     545             :                 } else {
     546             :                         /* Here we need to find out which nexthop to be used*/
     547           1 :                         if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
     548           1 :                                 tmp_addr.p.u.prefix4 = attr->nexthop;
     549           1 :                                 tmp_addr.p.prefixlen = IPV4_MAX_BITLEN;
     550           0 :                         } else if ((attr->mp_nexthop_len)
     551           0 :                                    && ((attr->mp_nexthop_len
     552             :                                         == BGP_ATTR_NHLEN_IPV4)
     553           0 :                                        || (attr->mp_nexthop_len
     554             :                                            == BGP_ATTR_NHLEN_VPNV4))) {
     555           0 :                                 tmp_addr.p.u.prefix4 =
     556             :                                         attr->mp_nexthop_global_in;
     557           0 :                                 tmp_addr.p.prefixlen = IPV4_MAX_BITLEN;
     558             :                         } else
     559             :                                 return false;
     560             :                 }
     561             :                 break;
     562           0 :         case AF_INET6:
     563           0 :                 if (is_bgp_static_route) {
     564           0 :                         tmp_addr.p.u.prefix6 = p->u.prefix6;
     565           0 :                         tmp_addr.p.prefixlen = p->prefixlen;
     566             :                 } else {
     567           0 :                         tmp_addr.p.u.prefix6 = attr->mp_nexthop_global;
     568           0 :                         tmp_addr.p.prefixlen = IPV6_MAX_BITLEN;
     569             :                 }
     570             :                 break;
     571             :         default:
     572             :                 break;
     573             :         }
     574             : 
     575           1 :         addr = hash_lookup(bgp->address_hash, &tmp_addr);
     576           1 :         if (addr)
     577             :                 return true;
     578             : 
     579           1 :         if (new_afi == AF_INET && hashcount(bgp->tip_hash)) {
     580           0 :                 memset(&tmp_tip, 0, sizeof(tmp_tip));
     581           0 :                 tmp_tip.addr = attr->nexthop;
     582             : 
     583           0 :                 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
     584           0 :                         tmp_tip.addr = attr->nexthop;
     585           0 :                 } else if ((attr->mp_nexthop_len) &&
     586             :                            ((attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4)
     587           0 :                             || (attr->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV4))) {
     588           0 :                         tmp_tip.addr = attr->mp_nexthop_global_in;
     589             :                 }
     590             : 
     591           0 :                 tip = hash_lookup(bgp->tip_hash, &tmp_tip);
     592           0 :                 if (tip)
     593             :                         return true;
     594             :         }
     595             : 
     596             :         return false;
     597             : }
     598             : 
     599           0 : bool bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer)
     600             : {
     601           0 :         struct bgp_dest *dest1;
     602           0 :         struct bgp_dest *dest2;
     603           0 :         struct prefix p;
     604           0 :         int ret;
     605             : 
     606           0 :         p.family = AF_INET;
     607           0 :         p.prefixlen = IPV4_MAX_BITLEN;
     608           0 :         p.u.prefix4 = nexthop;
     609             : 
     610           0 :         dest1 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
     611           0 :         if (!dest1)
     612             :                 return false;
     613             : 
     614           0 :         p.family = AF_INET;
     615           0 :         p.prefixlen = IPV4_MAX_BITLEN;
     616           0 :         p.u.prefix4 = peer->su.sin.sin_addr;
     617             : 
     618           0 :         dest2 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
     619           0 :         if (!dest2) {
     620           0 :                 bgp_dest_unlock_node(dest1);
     621           0 :                 return false;
     622             :         }
     623             : 
     624           0 :         ret = (dest1 == dest2);
     625             : 
     626           0 :         bgp_dest_unlock_node(dest1);
     627           0 :         bgp_dest_unlock_node(dest2);
     628             : 
     629           0 :         return ret;
     630             : }
     631             : 
     632           0 : bool bgp_multiaccess_check_v6(struct in6_addr nexthop, struct peer *peer)
     633             : {
     634           0 :         struct bgp_dest *dest1;
     635           0 :         struct bgp_dest *dest2;
     636           0 :         struct prefix p;
     637           0 :         int ret;
     638             : 
     639           0 :         p.family = AF_INET6;
     640           0 :         p.prefixlen = IPV6_MAX_BITLEN;
     641           0 :         p.u.prefix6 = nexthop;
     642             : 
     643           0 :         dest1 = bgp_node_match(peer->bgp->connected_table[AFI_IP6], &p);
     644           0 :         if (!dest1)
     645             :                 return false;
     646             : 
     647           0 :         p.family = AF_INET6;
     648           0 :         p.prefixlen = IPV6_MAX_BITLEN;
     649           0 :         p.u.prefix6 = peer->su.sin6.sin6_addr;
     650             : 
     651           0 :         dest2 = bgp_node_match(peer->bgp->connected_table[AFI_IP6], &p);
     652           0 :         if (!dest2) {
     653           0 :                 bgp_dest_unlock_node(dest1);
     654           0 :                 return false;
     655             :         }
     656             : 
     657           0 :         ret = (dest1 == dest2);
     658             : 
     659           0 :         bgp_dest_unlock_node(dest1);
     660           0 :         bgp_dest_unlock_node(dest2);
     661             : 
     662           0 :         return ret;
     663             : }
     664             : 
     665           0 : bool bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop,
     666             :                                      struct update_subgroup *subgrp,
     667             :                                      struct peer *exclude)
     668             : {
     669           0 :         struct bgp_dest *dest1 = NULL, *dest2 = NULL;
     670           0 :         struct peer_af *paf = NULL;
     671           0 :         struct prefix p = {0}, np = {0};
     672           0 :         struct bgp *bgp = NULL;
     673             : 
     674           0 :         np.family = AF_INET6;
     675           0 :         np.prefixlen = IPV6_MAX_BITLEN;
     676           0 :         np.u.prefix6 = nexthop;
     677             : 
     678           0 :         p.family = AF_INET;
     679           0 :         p.prefixlen = IPV6_MAX_BITLEN;
     680             : 
     681           0 :         bgp = SUBGRP_INST(subgrp);
     682           0 :         dest1 = bgp_node_match(bgp->connected_table[AFI_IP6], &np);
     683           0 :         if (!dest1)
     684             :                 return false;
     685             : 
     686           0 :         SUBGRP_FOREACH_PEER (subgrp, paf) {
     687             :                 /* Skip peer we're told to exclude - e.g., source of route. */
     688           0 :                 if (paf->peer == exclude)
     689           0 :                         continue;
     690             : 
     691           0 :                 p.u.prefix6 = paf->peer->su.sin6.sin6_addr;
     692           0 :                 dest2 = bgp_node_match(bgp->connected_table[AFI_IP6], &p);
     693           0 :                 if (dest1 == dest2) {
     694           0 :                         bgp_dest_unlock_node(dest1);
     695           0 :                         bgp_dest_unlock_node(dest2);
     696           0 :                         return true;
     697             :                 }
     698             : 
     699           0 :                 if (dest2)
     700           0 :                         bgp_dest_unlock_node(dest2);
     701             :         }
     702             : 
     703           0 :         bgp_dest_unlock_node(dest1);
     704           0 :         return false;
     705             : }
     706             : 
     707           0 : bool bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
     708             :                                      struct update_subgroup *subgrp,
     709             :                                      struct peer *exclude)
     710             : {
     711           0 :         struct bgp_dest *dest1, *dest2;
     712           0 :         struct peer_af *paf;
     713           0 :         struct prefix p, np;
     714           0 :         struct bgp *bgp;
     715             : 
     716           0 :         np.family = AF_INET;
     717           0 :         np.prefixlen = IPV4_MAX_BITLEN;
     718           0 :         np.u.prefix4 = nexthop;
     719             : 
     720           0 :         p.family = AF_INET;
     721           0 :         p.prefixlen = IPV4_MAX_BITLEN;
     722             : 
     723           0 :         bgp = SUBGRP_INST(subgrp);
     724           0 :         dest1 = bgp_node_match(bgp->connected_table[AFI_IP], &np);
     725           0 :         if (!dest1)
     726             :                 return false;
     727             : 
     728           0 :         SUBGRP_FOREACH_PEER (subgrp, paf) {
     729             :                 /* Skip peer we're told to exclude - e.g., source of route. */
     730           0 :                 if (paf->peer == exclude)
     731           0 :                         continue;
     732             : 
     733           0 :                 p.u.prefix4 = paf->peer->su.sin.sin_addr;
     734             : 
     735           0 :                 dest2 = bgp_node_match(bgp->connected_table[AFI_IP], &p);
     736           0 :                 if (dest1 == dest2) {
     737           0 :                         bgp_dest_unlock_node(dest1);
     738           0 :                         bgp_dest_unlock_node(dest2);
     739           0 :                         return true;
     740             :                 }
     741             : 
     742           0 :                 if (dest2)
     743           0 :                         bgp_dest_unlock_node(dest2);
     744             :         }
     745             : 
     746           0 :         bgp_dest_unlock_node(dest1);
     747           0 :         return false;
     748             : }
     749             : 
     750           0 : static void bgp_show_bgp_path_info_flags(uint32_t flags, json_object *json)
     751             : {
     752           0 :         json_object *json_flags = NULL;
     753             : 
     754           0 :         if (!json)
     755             :                 return;
     756             : 
     757           0 :         json_flags = json_object_new_object();
     758           0 :         json_object_boolean_add(json_flags, "igpChanged",
     759             :                                 CHECK_FLAG(flags, BGP_PATH_IGP_CHANGED));
     760           0 :         json_object_boolean_add(json_flags, "damped",
     761           0 :                                 CHECK_FLAG(flags, BGP_PATH_DAMPED));
     762           0 :         json_object_boolean_add(json_flags, "history",
     763           0 :                                 CHECK_FLAG(flags, BGP_PATH_HISTORY));
     764           0 :         json_object_boolean_add(json_flags, "bestpath",
     765           0 :                                 CHECK_FLAG(flags, BGP_PATH_SELECTED));
     766           0 :         json_object_boolean_add(json_flags, "valid",
     767           0 :                                 CHECK_FLAG(flags, BGP_PATH_VALID));
     768           0 :         json_object_boolean_add(json_flags, "attrChanged",
     769           0 :                                 CHECK_FLAG(flags, BGP_PATH_ATTR_CHANGED));
     770           0 :         json_object_boolean_add(json_flags, "deterministicMedCheck",
     771           0 :                                 CHECK_FLAG(flags, BGP_PATH_DMED_CHECK));
     772           0 :         json_object_boolean_add(json_flags, "deterministicMedSelected",
     773           0 :                                 CHECK_FLAG(flags, BGP_PATH_DMED_SELECTED));
     774           0 :         json_object_boolean_add(json_flags, "stale",
     775           0 :                                 CHECK_FLAG(flags, BGP_PATH_STALE));
     776           0 :         json_object_boolean_add(json_flags, "removed",
     777           0 :                                 CHECK_FLAG(flags, BGP_PATH_REMOVED));
     778           0 :         json_object_boolean_add(json_flags, "counted",
     779           0 :                                 CHECK_FLAG(flags, BGP_PATH_COUNTED));
     780           0 :         json_object_boolean_add(json_flags, "multipath",
     781           0 :                                 CHECK_FLAG(flags, BGP_PATH_MULTIPATH));
     782           0 :         json_object_boolean_add(json_flags, "multipathChanged",
     783           0 :                                 CHECK_FLAG(flags, BGP_PATH_MULTIPATH_CHG));
     784           0 :         json_object_boolean_add(json_flags, "ribAttributeChanged",
     785           0 :                                 CHECK_FLAG(flags, BGP_PATH_RIB_ATTR_CHG));
     786           0 :         json_object_boolean_add(json_flags, "nexthopSelf",
     787           0 :                                 CHECK_FLAG(flags, BGP_PATH_ANNC_NH_SELF));
     788           0 :         json_object_boolean_add(json_flags, "linkBandwidthChanged",
     789           0 :                                 CHECK_FLAG(flags, BGP_PATH_LINK_BW_CHG));
     790           0 :         json_object_boolean_add(json_flags, "acceptOwn",
     791           0 :                                 CHECK_FLAG(flags, BGP_PATH_ACCEPT_OWN));
     792           0 :         json_object_object_add(json, "flags", json_flags);
     793             : }
     794             : 
     795           0 : static void bgp_show_nexthop_paths(struct vty *vty, struct bgp *bgp,
     796             :                                    struct bgp_nexthop_cache *bnc,
     797             :                                    json_object *json)
     798             : {
     799           0 :         struct bgp_dest *dest;
     800           0 :         struct bgp_path_info *path;
     801           0 :         afi_t afi;
     802           0 :         safi_t safi;
     803           0 :         struct bgp_table *table;
     804           0 :         struct bgp *bgp_path;
     805           0 :         json_object *paths = NULL;
     806           0 :         json_object *json_path = NULL;
     807             : 
     808           0 :         if (json)
     809           0 :                 paths = json_object_new_array();
     810             :         else
     811           0 :                 vty_out(vty, "  Paths:\n");
     812           0 :         LIST_FOREACH (path, &(bnc->paths), nh_thread) {
     813           0 :                 dest = path->net;
     814           0 :                 assert(dest && bgp_dest_table(dest));
     815           0 :                 afi = family2afi(bgp_dest_get_prefix(dest)->family);
     816           0 :                 table = bgp_dest_table(dest);
     817           0 :                 safi = table->safi;
     818           0 :                 bgp_path = table->bgp;
     819             : 
     820           0 :                 if (json) {
     821           0 :                         json_path = json_object_new_object();
     822           0 :                         json_object_string_add(json_path, "afi", afi2str(afi));
     823           0 :                         json_object_string_add(json_path, "safi",
     824             :                                                safi2str(safi));
     825           0 :                         json_object_string_addf(json_path, "prefix", "%pBD",
     826             :                                                 dest);
     827           0 :                         if (dest->pdest)
     828           0 :                                 json_object_string_addf(
     829             :                                         json_path, "rd", "%pRD",
     830           0 :                                         (struct prefix_rd *)bgp_dest_get_prefix(
     831           0 :                                                 dest->pdest));
     832           0 :                         json_object_string_add(
     833             :                                 json_path, "vrf",
     834             :                                 vrf_id_to_name(bgp_path->vrf_id));
     835           0 :                         bgp_show_bgp_path_info_flags(path->flags, json_path);
     836           0 :                         json_object_array_add(paths, json_path);
     837           0 :                         continue;
     838             :                 }
     839           0 :                 if (dest->pdest)
     840           0 :                         vty_out(vty, "    %d/%d %pBD RD %pRD %s flags 0x%x\n",
     841             :                                 afi, safi, dest,
     842           0 :                                 (struct prefix_rd *)bgp_dest_get_prefix(
     843           0 :                                         dest->pdest),
     844             :                                 bgp_path->name_pretty, path->flags);
     845             :                 else
     846           0 :                         vty_out(vty, "    %d/%d %pBD %s flags 0x%x\n",
     847             :                                 afi, safi, dest, bgp_path->name_pretty, path->flags);
     848             :         }
     849           0 :         if (json)
     850           0 :                 json_object_object_add(json, "paths", paths);
     851           0 : }
     852             : 
     853           0 : static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp,
     854             :                                      struct bgp_nexthop_cache *bnc,
     855             :                                      json_object *json)
     856             : {
     857           0 :         struct nexthop *nexthop;
     858           0 :         json_object *json_gates = NULL;
     859           0 :         json_object *json_gate = NULL;
     860             : 
     861           0 :         if (json)
     862           0 :                 json_gates = json_object_new_array();
     863           0 :         for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next) {
     864           0 :                 if (json) {
     865           0 :                         json_gate = json_object_new_object();
     866           0 :                         switch (nexthop->type) {
     867           0 :                         case NEXTHOP_TYPE_IPV6:
     868           0 :                                 json_object_string_addf(json_gate, "ip", "%pI6",
     869             :                                                         &nexthop->gate.ipv6);
     870           0 :                                 break;
     871           0 :                         case NEXTHOP_TYPE_IPV6_IFINDEX:
     872           0 :                                 json_object_string_addf(json_gate, "ip", "%pI6",
     873             :                                                         &nexthop->gate.ipv6);
     874           0 :                                 json_object_string_add(
     875             :                                         json_gate, "interfaceName",
     876             :                                         ifindex2ifname(
     877           0 :                                                 bnc->ifindex ? bnc->ifindex
     878             :                                                              : nexthop->ifindex,
     879             :                                                 bgp->vrf_id));
     880           0 :                                 break;
     881           0 :                         case NEXTHOP_TYPE_IPV4:
     882           0 :                                 json_object_string_addf(json_gate, "ip", "%pI4",
     883             :                                                         &nexthop->gate.ipv4);
     884           0 :                                 break;
     885           0 :                         case NEXTHOP_TYPE_IFINDEX:
     886           0 :                                 json_object_string_add(
     887             :                                         json_gate, "interfaceName",
     888             :                                         ifindex2ifname(
     889           0 :                                                 bnc->ifindex ? bnc->ifindex
     890             :                                                              : nexthop->ifindex,
     891             :                                                 bgp->vrf_id));
     892           0 :                                 break;
     893           0 :                         case NEXTHOP_TYPE_IPV4_IFINDEX:
     894           0 :                                 json_object_string_addf(json_gate, "ip", "%pI4",
     895             :                                                         &nexthop->gate.ipv4);
     896           0 :                                 json_object_string_add(
     897             :                                         json_gate, "interfaceName",
     898             :                                         ifindex2ifname(
     899           0 :                                                 bnc->ifindex ? bnc->ifindex
     900             :                                                              : nexthop->ifindex,
     901             :                                                 bgp->vrf_id));
     902           0 :                                 break;
     903           0 :                         case NEXTHOP_TYPE_BLACKHOLE:
     904           0 :                                 json_object_boolean_true_add(json_gate,
     905             :                                                              "unreachable");
     906           0 :                                 switch (nexthop->bh_type) {
     907           0 :                                 case BLACKHOLE_REJECT:
     908           0 :                                         json_object_boolean_true_add(json_gate,
     909             :                                                                      "reject");
     910           0 :                                         break;
     911           0 :                                 case BLACKHOLE_ADMINPROHIB:
     912           0 :                                         json_object_boolean_true_add(
     913             :                                                 json_gate, "adminProhibited");
     914           0 :                                         break;
     915           0 :                                 case BLACKHOLE_NULL:
     916           0 :                                         json_object_boolean_true_add(
     917             :                                                 json_gate, "blackhole");
     918           0 :                                         break;
     919             :                                 case BLACKHOLE_UNSPEC:
     920             :                                         break;
     921             :                                 }
     922             :                                 break;
     923             :                         default:
     924             :                                 break;
     925             :                         }
     926           0 :                         json_object_array_add(json_gates, json_gate);
     927           0 :                         continue;
     928             :                 }
     929           0 :                 switch (nexthop->type) {
     930           0 :                 case NEXTHOP_TYPE_IPV6:
     931           0 :                         vty_out(vty, "  gate %pI6\n", &nexthop->gate.ipv6);
     932           0 :                         break;
     933           0 :                 case NEXTHOP_TYPE_IPV6_IFINDEX:
     934           0 :                         vty_out(vty, "  gate %pI6, if %s\n",
     935             :                                 &nexthop->gate.ipv6,
     936           0 :                                 ifindex2ifname(bnc->ifindex ? bnc->ifindex
     937             :                                                             : nexthop->ifindex,
     938             :                                                bgp->vrf_id));
     939           0 :                         break;
     940           0 :                 case NEXTHOP_TYPE_IPV4:
     941           0 :                         vty_out(vty, "  gate %pI4\n", &nexthop->gate.ipv4);
     942           0 :                         break;
     943           0 :                 case NEXTHOP_TYPE_IFINDEX:
     944           0 :                         vty_out(vty, "  if %s\n",
     945           0 :                                 ifindex2ifname(bnc->ifindex ? bnc->ifindex
     946             :                                                             : nexthop->ifindex,
     947             :                                                bgp->vrf_id));
     948           0 :                         break;
     949           0 :                 case NEXTHOP_TYPE_IPV4_IFINDEX:
     950           0 :                         vty_out(vty, "  gate %pI4, if %s\n",
     951             :                                 &nexthop->gate.ipv4,
     952           0 :                                 ifindex2ifname(bnc->ifindex ? bnc->ifindex
     953             :                                                             : nexthop->ifindex,
     954             :                                                bgp->vrf_id));
     955           0 :                         break;
     956           0 :                 case NEXTHOP_TYPE_BLACKHOLE:
     957           0 :                         vty_out(vty, "  blackhole\n");
     958           0 :                         break;
     959           0 :                 default:
     960           0 :                         vty_out(vty, "  invalid nexthop type %u\n",
     961             :                                 nexthop->type);
     962             :                 }
     963             :         }
     964           0 :         if (json)
     965           0 :                 json_object_object_add(json, "nexthops", json_gates);
     966           0 : }
     967             : 
     968           0 : static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp,
     969             :                              struct bgp_nexthop_cache *bnc, bool specific,
     970             :                              json_object *json)
     971             : {
     972           0 :         char buf[PREFIX2STR_BUFFER];
     973           0 :         time_t tbuf;
     974           0 :         struct peer *peer;
     975           0 :         json_object *json_last_update = NULL;
     976           0 :         json_object *json_nexthop = NULL;
     977             : 
     978           0 :         peer = (struct peer *)bnc->nht_info;
     979             : 
     980           0 :         if (json)
     981           0 :                 json_nexthop = json_object_new_object();
     982           0 :         if (bnc->srte_color) {
     983           0 :                 if (json)
     984           0 :                         json_object_int_add(json_nexthop, "srteColor",
     985             :                                             bnc->srte_color);
     986             :                 else
     987           0 :                         vty_out(vty, " SR-TE color %u -", bnc->srte_color);
     988             :         }
     989           0 :         inet_ntop(bnc->prefix.family, &bnc->prefix.u.prefix, buf, sizeof(buf));
     990           0 :         if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) {
     991           0 :                 if (json) {
     992           0 :                         json_object_boolean_true_add(json_nexthop, "valid");
     993           0 :                         json_object_boolean_true_add(json_nexthop, "complete");
     994           0 :                         json_object_int_add(json_nexthop, "igpMetric",
     995           0 :                                             bnc->metric);
     996           0 :                         json_object_int_add(json_nexthop, "pathCount",
     997           0 :                                             bnc->path_count);
     998           0 :                         if (peer)
     999           0 :                                 json_object_string_add(json_nexthop, "peer",
    1000           0 :                                                        peer->host);
    1001           0 :                         if (bnc->is_evpn_gwip_nexthop)
    1002           0 :                                 json_object_boolean_true_add(json_nexthop,
    1003             :                                                              "isEvpnGatewayIp");
    1004             :                 } else {
    1005           0 :                         vty_out(vty, " %s valid [IGP metric %d], #paths %d",
    1006             :                                 buf, bnc->metric, bnc->path_count);
    1007           0 :                         if (peer)
    1008           0 :                                 vty_out(vty, ", peer %s", peer->host);
    1009           0 :                         if (bnc->is_evpn_gwip_nexthop)
    1010           0 :                                 vty_out(vty, " EVPN Gateway IP");
    1011           0 :                         vty_out(vty, "\n");
    1012             :                 }
    1013           0 :                 bgp_show_nexthops_detail(vty, bgp, bnc, json_nexthop);
    1014           0 :         } else if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_EVPN_INCOMPLETE)) {
    1015           0 :                 if (json) {
    1016           0 :                         json_object_boolean_true_add(json_nexthop, "valid");
    1017           0 :                         json_object_boolean_false_add(json_nexthop, "complete");
    1018           0 :                         json_object_int_add(json_nexthop, "igpMetric",
    1019           0 :                                             bnc->metric);
    1020           0 :                         json_object_int_add(json_nexthop, "pathCount",
    1021           0 :                                             bnc->path_count);
    1022           0 :                         if (bnc->is_evpn_gwip_nexthop)
    1023           0 :                                 json_object_boolean_true_add(json_nexthop,
    1024             :                                                              "isEvpnGatewayIp");
    1025             :                 } else {
    1026           0 :                         vty_out(vty,
    1027             :                                 " %s overlay index unresolved [IGP metric %d], #paths %d",
    1028             :                                 buf, bnc->metric, bnc->path_count);
    1029           0 :                         if (bnc->is_evpn_gwip_nexthop)
    1030           0 :                                 vty_out(vty, " EVPN Gateway IP");
    1031           0 :                         vty_out(vty, "\n");
    1032             :                 }
    1033           0 :                 bgp_show_nexthops_detail(vty, bgp, bnc, json_nexthop);
    1034             :         } else {
    1035           0 :                 if (json) {
    1036           0 :                         json_object_boolean_false_add(json_nexthop, "valid");
    1037           0 :                         json_object_boolean_false_add(json_nexthop, "complete");
    1038           0 :                         json_object_int_add(json_nexthop, "pathCount",
    1039           0 :                                             bnc->path_count);
    1040           0 :                         if (peer)
    1041           0 :                                 json_object_string_add(json_nexthop, "peer",
    1042           0 :                                                        peer->host);
    1043           0 :                         if (bnc->is_evpn_gwip_nexthop)
    1044           0 :                                 json_object_boolean_true_add(json_nexthop,
    1045             :                                                              "isEvpnGatewayIp");
    1046           0 :                         if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
    1047           0 :                                 json_object_boolean_false_add(json_nexthop,
    1048             :                                                               "isConnected");
    1049           0 :                         if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
    1050           0 :                                 json_object_boolean_false_add(json_nexthop,
    1051             :                                                               "isRegistered");
    1052             :                 } else {
    1053           0 :                         vty_out(vty, " %s invalid, #paths %d", buf,
    1054             :                                 bnc->path_count);
    1055           0 :                         if (peer)
    1056           0 :                                 vty_out(vty, ", peer %s", peer->host);
    1057           0 :                         if (bnc->is_evpn_gwip_nexthop)
    1058           0 :                                 vty_out(vty, " EVPN Gateway IP");
    1059           0 :                         vty_out(vty, "\n");
    1060           0 :                         if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
    1061           0 :                                 vty_out(vty, "  Must be Connected\n");
    1062           0 :                         if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
    1063           0 :                                 vty_out(vty, "  Is not Registered\n");
    1064             :                 }
    1065             :         }
    1066           0 :         tbuf = time(NULL) - (monotime(NULL) - bnc->last_update);
    1067           0 :         if (json) {
    1068           0 :                 if (!specific) {
    1069           0 :                         json_last_update = json_object_new_object();
    1070           0 :                         json_object_int_add(json_last_update, "epoch", tbuf);
    1071           0 :                         json_object_string_add(json_last_update, "string",
    1072           0 :                                                ctime(&tbuf));
    1073           0 :                         json_object_object_add(json_nexthop, "lastUpdate",
    1074             :                                                json_last_update);
    1075             :                 } else {
    1076           0 :                         json_object_int_add(json_nexthop, "lastUpdate", tbuf);
    1077             :                 }
    1078             :         } else {
    1079           0 :                 vty_out(vty, "  Last update: %s", ctime(&tbuf));
    1080             :         }
    1081             : 
    1082             :         /* show paths dependent on nexthop, if needed. */
    1083           0 :         if (specific)
    1084           0 :                 bgp_show_nexthop_paths(vty, bgp, bnc, json_nexthop);
    1085           0 :         if (json)
    1086           0 :                 json_object_object_add(json, buf, json_nexthop);
    1087           0 : }
    1088             : 
    1089           0 : static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp,
    1090             :                               bool import_table, json_object *json, afi_t afi,
    1091             :                               bool detail)
    1092             : {
    1093           0 :         struct bgp_nexthop_cache *bnc;
    1094           0 :         struct bgp_nexthop_cache_head(*tree)[AFI_MAX];
    1095           0 :         json_object *json_afi = NULL;
    1096           0 :         bool found = false;
    1097             : 
    1098           0 :         if (!json) {
    1099           0 :                 if (import_table)
    1100           0 :                         vty_out(vty, "Current BGP import check cache:\n");
    1101             :                 else
    1102           0 :                         vty_out(vty, "Current BGP nexthop cache:\n");
    1103             :         }
    1104           0 :         if (import_table)
    1105           0 :                 tree = &bgp->import_check_table;
    1106             :         else
    1107           0 :                 tree = &bgp->nexthop_cache_table;
    1108             : 
    1109           0 :         if (afi == AFI_IP || afi == AFI_IP6) {
    1110           0 :                 if (json)
    1111           0 :                         json_afi = json_object_new_object();
    1112           0 :                 frr_each (bgp_nexthop_cache, &(*tree)[afi], bnc) {
    1113           0 :                         bgp_show_nexthop(vty, bgp, bnc, detail, json_afi);
    1114           0 :                         found = true;
    1115             :                 }
    1116           0 :                 if (found && json)
    1117           0 :                         json_object_object_add(
    1118             :                                 json, (afi == AFI_IP) ? "ipv4" : "ipv6",
    1119             :                                 json_afi);
    1120           0 :                 return;
    1121             :         }
    1122             : 
    1123           0 :         for (afi = AFI_IP; afi < AFI_MAX; afi++) {
    1124           0 :                 if (json && (afi == AFI_IP || afi == AFI_IP6))
    1125           0 :                         json_afi = json_object_new_object();
    1126           0 :                 frr_each (bgp_nexthop_cache, &(*tree)[afi], bnc)
    1127           0 :                         bgp_show_nexthop(vty, bgp, bnc, detail, json_afi);
    1128           0 :                 if (json && (afi == AFI_IP || afi == AFI_IP6))
    1129           0 :                         json_object_object_add(
    1130             :                                 json, (afi == AFI_IP) ? "ipv4" : "ipv6",
    1131             :                                 json_afi);
    1132             :         }
    1133             : }
    1134             : 
    1135           0 : static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name,
    1136             :                                      const char *nhopip_str, bool import_table,
    1137             :                                      json_object *json, afi_t afi, bool detail)
    1138             : {
    1139           0 :         struct bgp *bgp;
    1140             : 
    1141           0 :         if (name && !strmatch(name, VRF_DEFAULT_NAME))
    1142           0 :                 bgp = bgp_lookup_by_name(name);
    1143             :         else
    1144           0 :                 bgp = bgp_get_default();
    1145           0 :         if (!bgp) {
    1146           0 :                 if (!json)
    1147           0 :                         vty_out(vty, "%% No such BGP instance exist\n");
    1148           0 :                 return CMD_WARNING;
    1149             :         }
    1150             : 
    1151           0 :         if (nhopip_str) {
    1152           0 :                 struct prefix nhop;
    1153           0 :                 struct bgp_nexthop_cache_head (*tree)[AFI_MAX];
    1154           0 :                 struct bgp_nexthop_cache *bnc;
    1155           0 :                 bool found = false;
    1156           0 :                 json_object *json_afi = NULL;
    1157             : 
    1158           0 :                 if (!str2prefix(nhopip_str, &nhop)) {
    1159           0 :                         if (!json)
    1160           0 :                                 vty_out(vty, "nexthop address is malformed\n");
    1161           0 :                         return CMD_WARNING;
    1162             :                 }
    1163           0 :                 tree = import_table ? &bgp->import_check_table
    1164           0 :                                     : &bgp->nexthop_cache_table;
    1165           0 :                 if (json)
    1166           0 :                         json_afi = json_object_new_object();
    1167           0 :                 frr_each (bgp_nexthop_cache, &(*tree)[family2afi(nhop.family)],
    1168             :                           bnc) {
    1169           0 :                         if (prefix_cmp(&bnc->prefix, &nhop))
    1170           0 :                                 continue;
    1171           0 :                         bgp_show_nexthop(vty, bgp, bnc, true, json_afi);
    1172           0 :                         found = true;
    1173             :                 }
    1174           0 :                 if (json)
    1175           0 :                         json_object_object_add(
    1176             :                                 json,
    1177           0 :                                 (family2afi(nhop.family) == AFI_IP) ? "ipv4"
    1178             :                                                                     : "ipv6",
    1179             :                                 json_afi);
    1180           0 :                 if (!found && !json)
    1181           0 :                         vty_out(vty, "nexthop %s does not have entry\n",
    1182             :                                 nhopip_str);
    1183             :         } else
    1184           0 :                 bgp_show_nexthops(vty, bgp, import_table, json, afi, detail);
    1185             : 
    1186             :         return CMD_SUCCESS;
    1187             : }
    1188             : 
    1189           0 : static void bgp_show_all_instances_nexthops_vty(struct vty *vty,
    1190             :                                                 json_object *json, afi_t afi,
    1191             :                                                 bool detail)
    1192             : {
    1193           0 :         struct listnode *node, *nnode;
    1194           0 :         struct bgp *bgp;
    1195           0 :         const char *inst_name;
    1196           0 :         json_object *json_instance = NULL;
    1197             : 
    1198           0 :         for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
    1199           0 :                 inst_name = (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
    1200           0 :                                     ? VRF_DEFAULT_NAME
    1201           0 :                                     : bgp->name;
    1202           0 :                 if (json)
    1203           0 :                         json_instance = json_object_new_object();
    1204             :                 else
    1205           0 :                         vty_out(vty, "\nInstance %s:\n", inst_name);
    1206             : 
    1207           0 :                 bgp_show_nexthops(vty, bgp, false, json_instance, afi, detail);
    1208             : 
    1209           0 :                 if (json)
    1210           0 :                         json_object_object_add(json, inst_name, json_instance);
    1211             :         }
    1212           0 : }
    1213             : 
    1214             : #include "bgpd/bgp_nexthop_clippy.c"
    1215             : 
    1216           0 : DEFPY (show_ip_bgp_nexthop,
    1217             :        show_ip_bgp_nexthop_cmd,
    1218             :        "show [ip] bgp [<view|vrf> VIEWVRFNAME$vrf] nexthop [<A.B.C.D|X:X::X:X>$nhop] [<ipv4$afi [A.B.C.D$nhop]|ipv6$afi [X:X::X:X$nhop]>] [detail$detail] [json$uj]",
    1219             :        SHOW_STR
    1220             :        IP_STR
    1221             :        BGP_STR
    1222             :        BGP_INSTANCE_HELP_STR
    1223             :        "BGP nexthop table\n"
    1224             :        "IPv4 nexthop address\n"
    1225             :        "IPv6 nexthop address\n"
    1226             :        "BGP nexthop IPv4 table\n"
    1227             :        "IPv4 nexthop address\n"
    1228             :        "BGP nexthop IPv6 table\n"
    1229             :        "IPv6 nexthop address\n"
    1230             :        "Show detailed information\n"
    1231             :        JSON_STR)
    1232             : {
    1233           0 :         int rc = 0;
    1234           0 :         json_object *json = NULL;
    1235           0 :         afi_t afiz = AFI_UNSPEC;
    1236             : 
    1237           0 :         if (uj)
    1238           0 :                 json = json_object_new_object();
    1239             : 
    1240           0 :         if (afi)
    1241           0 :                 afiz = bgp_vty_afi_from_str(afi);
    1242             : 
    1243           0 :         rc = show_ip_bgp_nexthop_table(vty, vrf, nhop_str, false, json, afiz,
    1244             :                                        detail);
    1245             : 
    1246           0 :         if (uj)
    1247           0 :                 vty_json(vty, json);
    1248             : 
    1249           0 :         return rc;
    1250             : }
    1251             : 
    1252           0 : DEFPY (show_ip_bgp_import_check,
    1253             :        show_ip_bgp_import_check_cmd,
    1254             :        "show [ip] bgp [<view|vrf> VIEWVRFNAME$vrf] import-check-table [detail$detail] [json$uj]",
    1255             :        SHOW_STR
    1256             :        IP_STR
    1257             :        BGP_STR
    1258             :        BGP_INSTANCE_HELP_STR
    1259             :        "BGP import check table\n"
    1260             :        "Show detailed information\n"
    1261             :        JSON_STR)
    1262             : {
    1263           0 :         int rc = 0;
    1264           0 :         json_object *json = NULL;
    1265             : 
    1266           0 :         if (uj)
    1267           0 :                 json = json_object_new_object();
    1268             : 
    1269           0 :         rc = show_ip_bgp_nexthop_table(vty, vrf, NULL, true, json, AFI_UNSPEC,
    1270             :                                        detail);
    1271             : 
    1272           0 :         if (uj)
    1273           0 :                 vty_json(vty, json);
    1274             : 
    1275           0 :         return rc;
    1276             : }
    1277             : 
    1278           0 : DEFPY (show_ip_bgp_instance_all_nexthop,
    1279             :        show_ip_bgp_instance_all_nexthop_cmd,
    1280             :        "show [ip] bgp <view|vrf> all nexthop [<ipv4|ipv6>$afi] [detail$detail] [json$uj]",
    1281             :        SHOW_STR
    1282             :        IP_STR
    1283             :        BGP_STR
    1284             :        BGP_INSTANCE_ALL_HELP_STR
    1285             :        "BGP nexthop table\n"
    1286             :        "BGP IPv4 nexthop table\n"
    1287             :        "BGP IPv6 nexthop table\n"
    1288             :        "Show detailed information\n"
    1289             :        JSON_STR)
    1290             : {
    1291           0 :         json_object *json = NULL;
    1292           0 :         afi_t afiz = AFI_UNSPEC;
    1293             : 
    1294           0 :         if (uj)
    1295           0 :                 json = json_object_new_object();
    1296             : 
    1297           0 :         if (afi)
    1298           0 :                 afiz = bgp_vty_afi_from_str(afi);
    1299             : 
    1300           0 :         bgp_show_all_instances_nexthops_vty(vty, json, afiz, detail);
    1301             : 
    1302           0 :         if (uj)
    1303           0 :                 vty_json(vty, json);
    1304             : 
    1305           0 :         return CMD_SUCCESS;
    1306             : }
    1307             : 
    1308           1 : void bgp_scan_init(struct bgp *bgp)
    1309             : {
    1310           1 :         afi_t afi;
    1311             : 
    1312           4 :         for (afi = AFI_IP; afi < AFI_MAX; afi++) {
    1313           3 :                 bgp_nexthop_cache_init(&bgp->nexthop_cache_table[afi]);
    1314           3 :                 bgp_nexthop_cache_init(&bgp->import_check_table[afi]);
    1315           3 :                 bgp->connected_table[afi] = bgp_table_init(bgp, afi,
    1316             :                         SAFI_UNICAST);
    1317             :         }
    1318           1 : }
    1319             : 
    1320           2 : void bgp_scan_vty_init(void)
    1321             : {
    1322           2 :         install_element(VIEW_NODE, &show_ip_bgp_nexthop_cmd);
    1323           2 :         install_element(VIEW_NODE, &show_ip_bgp_import_check_cmd);
    1324           2 :         install_element(VIEW_NODE, &show_ip_bgp_instance_all_nexthop_cmd);
    1325           2 : }
    1326             : 
    1327           0 : void bgp_scan_finish(struct bgp *bgp)
    1328             : {
    1329           0 :         afi_t afi;
    1330             : 
    1331           0 :         for (afi = AFI_IP; afi < AFI_MAX; afi++) {
    1332             :                 /* Only the current one needs to be reset. */
    1333           0 :                 bgp_nexthop_cache_reset(&bgp->nexthop_cache_table[afi]);
    1334           0 :                 bgp_nexthop_cache_reset(&bgp->import_check_table[afi]);
    1335             : 
    1336           0 :                 bgp->connected_table[afi]->route_table->cleanup =
    1337             :                         bgp_connected_cleanup;
    1338           0 :                 bgp_table_unlock(bgp->connected_table[afi]);
    1339           0 :                 bgp->connected_table[afi] = NULL;
    1340             :         }
    1341           0 : }
    1342             : 
    1343           0 : char *bgp_nexthop_dump_bnc_flags(struct bgp_nexthop_cache *bnc, char *buf,
    1344             :                                  size_t len)
    1345             : {
    1346           0 :         if (bnc->flags == 0) {
    1347           0 :                 snprintfrr(buf, len, "None ");
    1348           0 :                 return buf;
    1349             :         }
    1350             : 
    1351           0 :         snprintfrr(buf, len, "%s%s%s%s%s%s%s",
    1352             :                    CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) ? "Valid " : "",
    1353             :                    CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED) ? "Reg " : "",
    1354             :                    CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED) ? "Conn " : "",
    1355             :                    CHECK_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED) ? "Notify "
    1356             :                                                                      : "",
    1357             :                    CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE) ? "Static " : "",
    1358             :                    CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)
    1359             :                            ? "Static Exact "
    1360             :                            : "",
    1361             :                    CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID)
    1362             :                            ? "Label Valid "
    1363             :                            : "");
    1364             : 
    1365           0 :         return buf;
    1366             : }
    1367             : 
    1368           0 : char *bgp_nexthop_dump_bnc_change_flags(struct bgp_nexthop_cache *bnc,
    1369             :                                         char *buf, size_t len)
    1370             : {
    1371           0 :         if (bnc->flags == 0) {
    1372           0 :                 snprintfrr(buf, len, "None ");
    1373           0 :                 return buf;
    1374             :         }
    1375             : 
    1376           0 :         snprintfrr(buf, len, "%s%s%s",
    1377             :                    CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED)
    1378             :                            ? "Changed "
    1379             :                            : "",
    1380             :                    CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED)
    1381             :                            ? "Metric "
    1382             :                            : "",
    1383           0 :                    CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CONNECTED_CHANGED)
    1384             :                            ? "Connected "
    1385             :                            : "");
    1386             : 
    1387           0 :         return buf;
    1388             : }

Generated by: LCOV version v1.16-topotato