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