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