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