]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_nexthop.c
Merge pull request #12690 from opensourcerouting/feature/deny_merging_prs_with_freeze...
[mirror_frr.git] / bgpd / bgp_nexthop.c
CommitLineData
718e3744 1/* BGP nexthop scan
896014f4
DL
2 * Copyright (C) 2000 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
718e3744 20
21#include <zebra.h>
22
23#include "command.h"
24#include "thread.h"
25#include "prefix.h"
bf85e4c5 26#include "lib/json.h"
718e3744 27#include "zclient.h"
28#include "stream.h"
29#include "network.h"
30#include "log.h"
31#include "memory.h"
10f9bf3f
JBD
32#include "hash.h"
33#include "jhash.h"
fb018d25 34#include "nexthop.h"
3f9c7369 35#include "queue.h"
039f3a34 36#include "filter.h"
987a720a 37#include "printfrr.h"
718e3744 38
39#include "bgpd/bgpd.h"
718e3744 40#include "bgpd/bgp_route.h"
41#include "bgpd/bgp_attr.h"
42#include "bgpd/bgp_nexthop.h"
fb018d25 43#include "bgpd/bgp_nht.h"
718e3744 44#include "bgpd/bgp_debug.h"
45#include "bgpd/bgp_damp.h"
8ffedcea 46#include "bgpd/bgp_fsm.h"
8386ac43 47#include "bgpd/bgp_vty.h"
5d76a53d 48#include "bgpd/bgp_rd.h"
718e3744 49
2a99175f 50DEFINE_MTYPE_STATIC(BGPD, MARTIAN_STRING, "BGP Martian Addr Intf String");
330cec3d 51
f663c581
RW
52int bgp_nexthop_cache_compare(const struct bgp_nexthop_cache *a,
53 const struct bgp_nexthop_cache *b)
fb018d25 54{
545aeef1
RW
55 if (a->srte_color < b->srte_color)
56 return -1;
57 if (a->srte_color > b->srte_color)
58 return 1;
59
35aae5c9
DS
60 if (a->ifindex < b->ifindex)
61 return -1;
62 if (a->ifindex > b->ifindex)
63 return 1;
64
f663c581
RW
65 return prefix_cmp(&a->prefix, &b->prefix);
66}
67
d62a17ae 68void bnc_nexthop_free(struct bgp_nexthop_cache *bnc)
718e3744 69{
d62a17ae 70 nexthops_free(bnc->nexthop);
718e3744 71}
72
f663c581 73struct bgp_nexthop_cache *bnc_new(struct bgp_nexthop_cache_head *tree,
35aae5c9
DS
74 struct prefix *prefix, uint32_t srte_color,
75 ifindex_t ifindex)
718e3744 76{
d62a17ae 77 struct bgp_nexthop_cache *bnc;
fb018d25 78
d62a17ae 79 bnc = XCALLOC(MTYPE_BGP_NEXTHOP_CACHE,
80 sizeof(struct bgp_nexthop_cache));
f663c581 81 bnc->prefix = *prefix;
35aae5c9 82 bnc->ifindex = ifindex;
545aeef1 83 bnc->srte_color = srte_color;
f663c581 84 bnc->tree = tree;
d62a17ae 85 LIST_INIT(&(bnc->paths));
f663c581
RW
86 bgp_nexthop_cache_add(tree, bnc);
87
d62a17ae 88 return bnc;
718e3744 89}
90
e37e1e27
PR
91bool bnc_existing_for_prefix(struct bgp_nexthop_cache *bnc)
92{
93 struct bgp_nexthop_cache *bnc_tmp;
94
95 frr_each (bgp_nexthop_cache, bnc->tree, bnc_tmp) {
96 if (bnc_tmp == bnc)
97 continue;
98 if (prefix_cmp(&bnc->prefix, &bnc_tmp->prefix) == 0)
99 return true;
100 }
101 return false;
102}
103
d62a17ae 104void bnc_free(struct bgp_nexthop_cache *bnc)
718e3744 105{
d62a17ae 106 bnc_nexthop_free(bnc);
f663c581 107 bgp_nexthop_cache_del(bnc->tree, bnc);
d62a17ae 108 XFREE(MTYPE_BGP_NEXTHOP_CACHE, bnc);
718e3744 109}
6b0655a2 110
f663c581 111struct bgp_nexthop_cache *bnc_find(struct bgp_nexthop_cache_head *tree,
35aae5c9
DS
112 struct prefix *prefix, uint32_t srte_color,
113 ifindex_t ifindex)
f663c581
RW
114{
115 struct bgp_nexthop_cache bnc = {};
116
117 if (!tree)
118 return NULL;
119
120 bnc.prefix = *prefix;
545aeef1 121 bnc.srte_color = srte_color;
35aae5c9 122 bnc.ifindex = ifindex;
f663c581
RW
123 return bgp_nexthop_cache_find(tree, &bnc);
124}
125
718e3744 126/* Reset and free all BGP nexthop cache. */
f663c581 127static void bgp_nexthop_cache_reset(struct bgp_nexthop_cache_head *tree)
718e3744 128{
d62a17ae 129 struct bgp_nexthop_cache *bnc;
130
f663c581
RW
131 while (bgp_nexthop_cache_count(tree) > 0) {
132 bnc = bgp_nexthop_cache_first(tree);
7f040da1 133
3d111939
DS
134 while (!LIST_EMPTY(&(bnc->paths))) {
135 struct bgp_path_info *path = LIST_FIRST(&(bnc->paths));
7f040da1 136
3d111939 137 path_nh_map(path, bnc, false);
d62a17ae 138 }
3d111939
DS
139
140 bnc_free(bnc);
14315f2d 141 }
718e3744 142}
143
db0e1937
MK
144static void *bgp_tip_hash_alloc(void *p)
145{
0291c246
MK
146 const struct in_addr *val = (const struct in_addr *)p;
147 struct tip_addr *addr;
db0e1937
MK
148
149 addr = XMALLOC(MTYPE_TIP_ADDR, sizeof(struct tip_addr));
150 addr->refcnt = 0;
151 addr->addr.s_addr = val->s_addr;
152
153 return addr;
154}
155
156static void bgp_tip_hash_free(void *addr)
157{
158 XFREE(MTYPE_TIP_ADDR, addr);
159}
160
d8b87afe 161static unsigned int bgp_tip_hash_key_make(const void *p)
db0e1937 162{
0291c246 163 const struct tip_addr *addr = p;
db0e1937
MK
164
165 return jhash_1word(addr->addr.s_addr, 0);
166}
167
74df8d6d 168static bool bgp_tip_hash_cmp(const void *p1, const void *p2)
db0e1937 169{
0291c246
MK
170 const struct tip_addr *addr1 = p1;
171 const struct tip_addr *addr2 = p2;
db0e1937
MK
172
173 return addr1->addr.s_addr == addr2->addr.s_addr;
174}
175
176void bgp_tip_hash_init(struct bgp *bgp)
177{
996c9314 178 bgp->tip_hash = hash_create(bgp_tip_hash_key_make, bgp_tip_hash_cmp,
3f65c5b1 179 "BGP TIP hash");
db0e1937
MK
180}
181
182void bgp_tip_hash_destroy(struct bgp *bgp)
183{
184 if (bgp->tip_hash == NULL)
185 return;
186 hash_clean(bgp->tip_hash, bgp_tip_hash_free);
187 hash_free(bgp->tip_hash);
188 bgp->tip_hash = NULL;
189}
190
191void bgp_tip_add(struct bgp *bgp, struct in_addr *tip)
192{
0291c246
MK
193 struct tip_addr tmp;
194 struct tip_addr *addr;
db0e1937
MK
195
196 tmp.addr = *tip;
197
198 addr = hash_get(bgp->tip_hash, &tmp, bgp_tip_hash_alloc);
db0e1937
MK
199 addr->refcnt++;
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
bf85e4c5
PJD
805 if (json) {
806 json_path = json_object_new_object();
807 json_object_string_add(json_path, "afi", afi2str(afi));
808 json_object_string_add(json_path, "safi",
809 safi2str(safi));
810 json_object_string_addf(json_path, "prefix", "%pBD",
811 dest);
812 if (dest->pdest)
813 json_object_string_addf(
814 json_path, "rd", "%pRD",
815 (struct prefix_rd *)bgp_dest_get_prefix(
816 dest->pdest));
817 json_object_string_add(
818 json_path, "vrf",
819 vrf_id_to_name(bgp_path->vrf_id));
820 bgp_show_bgp_path_info_flags(path->flags, json_path);
821 json_object_array_add(paths, json_path);
822 continue;
823 }
c4f64ea9
DA
824 if (dest->pdest)
825 vty_out(vty, " %d/%d %pBD RD %pRD %s flags 0x%x\n",
826 afi, safi, dest,
827 (struct prefix_rd *)bgp_dest_get_prefix(
828 dest->pdest),
829 bgp_path->name_pretty, path->flags);
830 else
56ca3b5b 831 vty_out(vty, " %d/%d %pBD %s flags 0x%x\n",
9bcb3eef 832 afi, safi, dest, bgp_path->name_pretty, path->flags);
5d76a53d 833 }
bf85e4c5
PJD
834 if (json)
835 json_object_object_add(json, "paths", paths);
5d76a53d 836}
837
996c9314 838static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp,
bf85e4c5
PJD
839 struct bgp_nexthop_cache *bnc,
840 json_object *json)
e22ac3ee 841{
e22ac3ee 842 struct nexthop *nexthop;
bf85e4c5
PJD
843 json_object *json_gates = NULL;
844 json_object *json_gate = NULL;
e22ac3ee 845
bf85e4c5
PJD
846 if (json)
847 json_gates = json_object_new_array();
5d76a53d 848 for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next) {
bf85e4c5
PJD
849 if (json) {
850 json_gate = json_object_new_object();
851 switch (nexthop->type) {
852 case NEXTHOP_TYPE_IPV6:
853 json_object_string_addf(json_gate, "ip", "%pI6",
854 &nexthop->gate.ipv6);
855 break;
856 case NEXTHOP_TYPE_IPV6_IFINDEX:
857 json_object_string_addf(json_gate, "ip", "%pI6",
858 &nexthop->gate.ipv6);
859 json_object_string_add(
8da79d08 860 json_gate, "interfaceName",
bf85e4c5
PJD
861 ifindex2ifname(
862 bnc->ifindex ? bnc->ifindex
863 : nexthop->ifindex,
864 bgp->vrf_id));
865 break;
866 case NEXTHOP_TYPE_IPV4:
867 json_object_string_addf(json_gate, "ip", "%pI4",
868 &nexthop->gate.ipv4);
869 break;
870 case NEXTHOP_TYPE_IFINDEX:
871 json_object_string_add(
8da79d08 872 json_gate, "interfaceName",
bf85e4c5
PJD
873 ifindex2ifname(
874 bnc->ifindex ? bnc->ifindex
875 : nexthop->ifindex,
876 bgp->vrf_id));
877 break;
878 case NEXTHOP_TYPE_IPV4_IFINDEX:
879 json_object_string_addf(json_gate, "ip", "%pI4",
880 &nexthop->gate.ipv4);
881 json_object_string_add(
8da79d08 882 json_gate, "interfaceName",
bf85e4c5
PJD
883 ifindex2ifname(
884 bnc->ifindex ? bnc->ifindex
885 : nexthop->ifindex,
886 bgp->vrf_id));
887 break;
888 case NEXTHOP_TYPE_BLACKHOLE:
889 json_object_boolean_true_add(json_gate,
8da79d08
PJD
890 "unreachable");
891 switch (nexthop->bh_type) {
892 case BLACKHOLE_REJECT:
893 json_object_boolean_true_add(json_gate,
894 "reject");
895 break;
896 case BLACKHOLE_ADMINPROHIB:
897 json_object_boolean_true_add(
898 json_gate, "adminProhibited");
899 break;
900 case BLACKHOLE_NULL:
901 json_object_boolean_true_add(
902 json_gate, "blackhole");
903 break;
904 case BLACKHOLE_UNSPEC:
905 break;
906 }
bf85e4c5
PJD
907 break;
908 default:
8da79d08 909 break;
bf85e4c5
PJD
910 }
911 json_object_array_add(json_gates, json_gate);
912 continue;
913 }
e22ac3ee
DS
914 switch (nexthop->type) {
915 case NEXTHOP_TYPE_IPV6:
07380148 916 vty_out(vty, " gate %pI6\n", &nexthop->gate.ipv6);
e22ac3ee
DS
917 break;
918 case NEXTHOP_TYPE_IPV6_IFINDEX:
07380148
DA
919 vty_out(vty, " gate %pI6, if %s\n",
920 &nexthop->gate.ipv6,
8761cd6d
DS
921 ifindex2ifname(bnc->ifindex ? bnc->ifindex
922 : nexthop->ifindex,
923 bgp->vrf_id));
e22ac3ee
DS
924 break;
925 case NEXTHOP_TYPE_IPV4:
07380148 926 vty_out(vty, " gate %pI4\n", &nexthop->gate.ipv4);
e22ac3ee
DS
927 break;
928 case NEXTHOP_TYPE_IFINDEX:
929 vty_out(vty, " if %s\n",
8761cd6d
DS
930 ifindex2ifname(bnc->ifindex ? bnc->ifindex
931 : nexthop->ifindex,
932 bgp->vrf_id));
e22ac3ee
DS
933 break;
934 case NEXTHOP_TYPE_IPV4_IFINDEX:
07380148
DA
935 vty_out(vty, " gate %pI4, if %s\n",
936 &nexthop->gate.ipv4,
8761cd6d
DS
937 ifindex2ifname(bnc->ifindex ? bnc->ifindex
938 : nexthop->ifindex,
939 bgp->vrf_id));
e22ac3ee
DS
940 break;
941 case NEXTHOP_TYPE_BLACKHOLE:
942 vty_out(vty, " blackhole\n");
943 break;
944 default:
996c9314 945 vty_out(vty, " invalid nexthop type %u\n",
e22ac3ee
DS
946 nexthop->type);
947 }
5d76a53d 948 }
bf85e4c5 949 if (json)
8da79d08 950 json_object_object_add(json, "nexthops", json_gates);
e22ac3ee
DS
951}
952
5d76a53d 953static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp,
bf85e4c5
PJD
954 struct bgp_nexthop_cache *bnc, bool specific,
955 json_object *json)
fb018d25 956{
d62a17ae 957 char buf[PREFIX2STR_BUFFER];
d62a17ae 958 time_t tbuf;
5d76a53d 959 struct peer *peer;
bf85e4c5
PJD
960 json_object *json_last_update = NULL;
961 json_object *json_nexthop = NULL;
5d76a53d 962
963 peer = (struct peer *)bnc->nht_info;
964
bf85e4c5
PJD
965 if (json)
966 json_nexthop = json_object_new_object();
967 if (bnc->srte_color) {
968 if (json)
969 json_object_int_add(json_nexthop, "srteColor",
970 bnc->srte_color);
971 else
972 vty_out(vty, " SR-TE color %u -", bnc->srte_color);
973 }
974 inet_ntop(bnc->prefix.family, &bnc->prefix.u.prefix, buf, sizeof(buf));
5d76a53d 975 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) {
bf85e4c5
PJD
976 if (json) {
977 json_object_boolean_true_add(json_nexthop, "valid");
978 json_object_boolean_true_add(json_nexthop, "complete");
979 json_object_int_add(json_nexthop, "igpMetric",
980 bnc->metric);
981 json_object_int_add(json_nexthop, "pathCount",
982 bnc->path_count);
983 if (peer)
984 json_object_string_add(json_nexthop, "peer",
985 peer->host);
986 if (bnc->is_evpn_gwip_nexthop)
987 json_object_boolean_true_add(json_nexthop,
988 "isEvpnGatewayIp");
989 } else {
990 vty_out(vty, " %s valid [IGP metric %d], #paths %d",
991 buf, bnc->metric, bnc->path_count);
992 if (peer)
993 vty_out(vty, ", peer %s", peer->host);
994 if (bnc->is_evpn_gwip_nexthop)
995 vty_out(vty, " EVPN Gateway IP");
996 vty_out(vty, "\n");
997 }
998 bgp_show_nexthops_detail(vty, bgp, bnc, json_nexthop);
021b6596 999 } else if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_EVPN_INCOMPLETE)) {
bf85e4c5
PJD
1000 if (json) {
1001 json_object_boolean_true_add(json_nexthop, "valid");
1002 json_object_boolean_false_add(json_nexthop, "complete");
1003 json_object_int_add(json_nexthop, "igpMetric",
1004 bnc->metric);
1005 json_object_int_add(json_nexthop, "pathCount",
1006 bnc->path_count);
1007 if (bnc->is_evpn_gwip_nexthop)
1008 json_object_boolean_true_add(json_nexthop,
1009 "isEvpnGatewayIp");
1010 } else {
1011 vty_out(vty,
1012 " %s overlay index unresolved [IGP metric %d], #paths %d",
1013 buf, bnc->metric, bnc->path_count);
1014 if (bnc->is_evpn_gwip_nexthop)
1015 vty_out(vty, " EVPN Gateway IP");
1016 vty_out(vty, "\n");
1017 }
1018 bgp_show_nexthops_detail(vty, bgp, bnc, json_nexthop);
5d76a53d 1019 } else {
bf85e4c5
PJD
1020 if (json) {
1021 json_object_boolean_false_add(json_nexthop, "valid");
1022 json_object_boolean_false_add(json_nexthop, "complete");
1023 json_object_int_add(json_nexthop, "pathCount",
1024 bnc->path_count);
1025 if (peer)
1026 json_object_string_add(json_nexthop, "peer",
1027 peer->host);
1028 if (bnc->is_evpn_gwip_nexthop)
1029 json_object_boolean_true_add(json_nexthop,
1030 "isEvpnGatewayIp");
1031 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
1032 json_object_boolean_false_add(json_nexthop,
1033 "isConnected");
1034 if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
1035 json_object_boolean_false_add(json_nexthop,
1036 "isRegistered");
1037 } else {
1038 vty_out(vty, " %s invalid, #paths %d", buf,
1039 bnc->path_count);
1040 if (peer)
1041 vty_out(vty, ", peer %s", peer->host);
1042 if (bnc->is_evpn_gwip_nexthop)
1043 vty_out(vty, " EVPN Gateway IP");
1044 vty_out(vty, "\n");
1045 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
1046 vty_out(vty, " Must be Connected\n");
1047 if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
1048 vty_out(vty, " Is not Registered\n");
1049 }
5d76a53d 1050 }
083ec940 1051 tbuf = time(NULL) - (monotime(NULL) - bnc->last_update);
bf85e4c5 1052 if (json) {
8da79d08
PJD
1053 if (!specific) {
1054 json_last_update = json_object_new_object();
1055 json_object_int_add(json_last_update, "epoch", tbuf);
1056 json_object_string_add(json_last_update, "string",
1057 ctime(&tbuf));
1058 json_object_object_add(json_nexthop, "lastUpdate",
1059 json_last_update);
1060 } else {
1061 json_object_int_add(json_nexthop, "lastUpdate", tbuf);
1062 }
bf85e4c5
PJD
1063 } else {
1064 vty_out(vty, " Last update: %s", ctime(&tbuf));
1065 }
5d76a53d 1066
1067 /* show paths dependent on nexthop, if needed. */
1068 if (specific)
bf85e4c5
PJD
1069 bgp_show_nexthop_paths(vty, bgp, bnc, json_nexthop);
1070 if (json)
1071 json_object_object_add(json, buf, json_nexthop);
5d76a53d 1072}
1073
1074static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp,
8da79d08
PJD
1075 bool import_table, json_object *json, afi_t afi,
1076 bool detail)
5d76a53d 1077{
5d76a53d 1078 struct bgp_nexthop_cache *bnc;
f663c581 1079 struct bgp_nexthop_cache_head(*tree)[AFI_MAX];
8da79d08
PJD
1080 json_object *json_afi = NULL;
1081 bool found = false;
d62a17ae 1082
bf85e4c5
PJD
1083 if (!json) {
1084 if (import_table)
1085 vty_out(vty, "Current BGP import check cache:\n");
1086 else
1087 vty_out(vty, "Current BGP nexthop cache:\n");
1088 }
05e47722 1089 if (import_table)
f663c581 1090 tree = &bgp->import_check_table;
05e47722 1091 else
f663c581 1092 tree = &bgp->nexthop_cache_table;
8da79d08
PJD
1093
1094 if (afi == AFI_IP || afi == AFI_IP6) {
1095 if (json)
1096 json_afi = json_object_new_object();
1097 frr_each (bgp_nexthop_cache, &(*tree)[afi], bnc) {
1098 bgp_show_nexthop(vty, bgp, bnc, detail, json_afi);
1099 found = true;
1100 }
1101 if (found && json)
1102 json_object_object_add(
1103 json, (afi == AFI_IP) ? "ipv4" : "ipv6",
1104 json_afi);
8da79d08
PJD
1105 return;
1106 }
1107
d62a17ae 1108 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
8da79d08
PJD
1109 if (json && (afi == AFI_IP || afi == AFI_IP6))
1110 json_afi = json_object_new_object();
f663c581 1111 frr_each (bgp_nexthop_cache, &(*tree)[afi], bnc)
8da79d08
PJD
1112 bgp_show_nexthop(vty, bgp, bnc, detail, json_afi);
1113 if (json && (afi == AFI_IP || afi == AFI_IP6))
1114 json_object_object_add(
1115 json, (afi == AFI_IP) ? "ipv4" : "ipv6",
1116 json_afi);
fb018d25 1117 }
f186de26 1118}
1119
d62a17ae 1120static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name,
bf85e4c5 1121 const char *nhopip_str, bool import_table,
8da79d08 1122 json_object *json, afi_t afi, bool detail)
f186de26 1123{
d62a17ae 1124 struct bgp *bgp;
1125
071ec807 1126 if (name && !strmatch(name, VRF_DEFAULT_NAME))
d62a17ae 1127 bgp = bgp_lookup_by_name(name);
1128 else
1129 bgp = bgp_get_default();
1130 if (!bgp) {
bf85e4c5
PJD
1131 if (!json)
1132 vty_out(vty, "%% No such BGP instance exist\n");
d62a17ae 1133 return CMD_WARNING;
1134 }
f186de26 1135
5d76a53d 1136 if (nhopip_str) {
1137 struct prefix nhop;
f663c581 1138 struct bgp_nexthop_cache_head (*tree)[AFI_MAX];
5d76a53d 1139 struct bgp_nexthop_cache *bnc;
8c6a164f 1140 bool found = false;
8da79d08 1141 json_object *json_afi = NULL;
5d76a53d 1142
1143 if (!str2prefix(nhopip_str, &nhop)) {
bf85e4c5
PJD
1144 if (!json)
1145 vty_out(vty, "nexthop address is malformed\n");
5d76a53d 1146 return CMD_WARNING;
1147 }
f663c581
RW
1148 tree = import_table ? &bgp->import_check_table
1149 : &bgp->nexthop_cache_table;
bf85e4c5 1150 if (json)
8da79d08 1151 json_afi = json_object_new_object();
8c6a164f
PG
1152 frr_each (bgp_nexthop_cache, &(*tree)[family2afi(nhop.family)],
1153 bnc) {
1154 if (prefix_cmp(&bnc->prefix, &nhop))
1155 continue;
8da79d08 1156 bgp_show_nexthop(vty, bgp, bnc, true, json_afi);
8c6a164f 1157 found = true;
5d76a53d 1158 }
bf85e4c5 1159 if (json)
8da79d08
PJD
1160 json_object_object_add(
1161 json,
1162 (family2afi(nhop.family) == AFI_IP) ? "ipv4"
1163 : "ipv6",
1164 json_afi);
bf85e4c5 1165 if (!found && !json)
8c6a164f
PG
1166 vty_out(vty, "nexthop %s does not have entry\n",
1167 nhopip_str);
5d76a53d 1168 } else
8da79d08 1169 bgp_show_nexthops(vty, bgp, import_table, json, afi, detail);
f186de26 1170
d62a17ae 1171 return CMD_SUCCESS;
fb018d25
DS
1172}
1173
bf85e4c5 1174static void bgp_show_all_instances_nexthops_vty(struct vty *vty,
8da79d08
PJD
1175 json_object *json, afi_t afi,
1176 bool detail)
f186de26 1177{
d62a17ae 1178 struct listnode *node, *nnode;
1179 struct bgp *bgp;
bf85e4c5
PJD
1180 const char *inst_name;
1181 json_object *json_instance = NULL;
d62a17ae 1182
1183 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
bf85e4c5
PJD
1184 inst_name = (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
1185 ? VRF_DEFAULT_NAME
1186 : bgp->name;
1187 if (json)
1188 json_instance = json_object_new_object();
1189 else
1190 vty_out(vty, "\nInstance %s:\n", inst_name);
1191
8da79d08 1192 bgp_show_nexthops(vty, bgp, false, json_instance, afi, detail);
bf85e4c5
PJD
1193
1194 if (json)
1195 json_object_object_add(json, inst_name, json_instance);
d62a17ae 1196 }
f186de26 1197}
1198
071ec807
PJD
1199#include "bgpd/bgp_nexthop_clippy.c"
1200
1201DEFPY (show_ip_bgp_nexthop,
fb018d25 1202 show_ip_bgp_nexthop_cmd,
071ec807 1203 "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 1204 SHOW_STR
1205 IP_STR
1206 BGP_STR
8386ac43 1207 BGP_INSTANCE_HELP_STR
3a2d747c 1208 "BGP nexthop table\n"
5d76a53d 1209 "IPv4 nexthop address\n"
1210 "IPv6 nexthop address\n"
071ec807
PJD
1211 "BGP nexthop IPv4 table\n"
1212 "IPv4 nexthop address\n"
1213 "BGP nexthop IPv6 table\n"
1214 "IPv6 nexthop address\n"
bf85e4c5
PJD
1215 "Show detailed information\n"
1216 JSON_STR)
50ef26d4 1217{
bf85e4c5 1218 int rc = 0;
bf85e4c5 1219 json_object *json = NULL;
071ec807 1220 afi_t afiz = AFI_UNSPEC;
bf85e4c5
PJD
1221
1222 if (uj)
1223 json = json_object_new_object();
b7ada628 1224
071ec807
PJD
1225 if (afi)
1226 afiz = bgp_vty_afi_from_str(afi);
05e47722 1227
071ec807
PJD
1228 rc = show_ip_bgp_nexthop_table(vty, vrf, nhop_str, false, json, afiz,
1229 detail);
5d76a53d 1230
bf85e4c5
PJD
1231 if (uj)
1232 vty_json(vty, json);
071ec807 1233
bf85e4c5 1234 return rc;
05e47722
PG
1235}
1236
071ec807 1237DEFPY (show_ip_bgp_import_check,
05e47722 1238 show_ip_bgp_import_check_cmd,
071ec807 1239 "show [ip] bgp [<view|vrf> VIEWVRFNAME$vrf] import-check-table [detail$detail] [json$uj]",
05e47722
PG
1240 SHOW_STR
1241 IP_STR
1242 BGP_STR
1243 BGP_INSTANCE_HELP_STR
1244 "BGP import check table\n"
bf85e4c5
PJD
1245 "Show detailed information\n"
1246 JSON_STR)
05e47722 1247{
bf85e4c5 1248 int rc = 0;
bf85e4c5 1249 json_object *json = NULL;
bf85e4c5
PJD
1250
1251 if (uj)
1252 json = json_object_new_object();
05e47722 1253
8da79d08
PJD
1254 rc = show_ip_bgp_nexthop_table(vty, vrf, NULL, true, json, AFI_UNSPEC,
1255 detail);
05e47722 1256
bf85e4c5
PJD
1257 if (uj)
1258 vty_json(vty, json);
5d76a53d 1259
bf85e4c5 1260 return rc;
50ef26d4 1261}
1262
071ec807 1263DEFPY (show_ip_bgp_instance_all_nexthop,
f186de26 1264 show_ip_bgp_instance_all_nexthop_cmd,
071ec807 1265 "show [ip] bgp <view|vrf> all nexthop [<ipv4|ipv6>$afi] [detail$detail] [json$uj]",
f186de26 1266 SHOW_STR
1267 IP_STR
1268 BGP_STR
1269 BGP_INSTANCE_ALL_HELP_STR
bf85e4c5 1270 "BGP nexthop table\n"
071ec807
PJD
1271 "BGP IPv4 nexthop table\n"
1272 "BGP IPv6 nexthop table\n"
1273 "Show detailed information\n"
bf85e4c5 1274 JSON_STR)
f186de26 1275{
bf85e4c5 1276 json_object *json = NULL;
071ec807 1277 afi_t afiz = AFI_UNSPEC;
bf85e4c5
PJD
1278
1279 if (uj)
1280 json = json_object_new_object();
1281
071ec807
PJD
1282 if (afi)
1283 afiz = bgp_vty_afi_from_str(afi);
8da79d08 1284
071ec807 1285 bgp_show_all_instances_nexthops_vty(vty, json, afiz, detail);
bf85e4c5
PJD
1286
1287 if (uj)
1288 vty_json(vty, json);
071ec807 1289
d62a17ae 1290 return CMD_SUCCESS;
f186de26 1291}
1292
d62a17ae 1293void bgp_scan_init(struct bgp *bgp)
718e3744 1294{
d62a17ae 1295 afi_t afi;
1296
1297 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
f663c581
RW
1298 bgp_nexthop_cache_init(&bgp->nexthop_cache_table[afi]);
1299 bgp_nexthop_cache_init(&bgp->import_check_table[afi]);
960035b2
PZ
1300 bgp->connected_table[afi] = bgp_table_init(bgp, afi,
1301 SAFI_UNICAST);
d62a17ae 1302 }
fc9a856f
DS
1303}
1304
d62a17ae 1305void bgp_scan_vty_init(void)
fc9a856f 1306{
d62a17ae 1307 install_element(VIEW_NODE, &show_ip_bgp_nexthop_cmd);
05e47722 1308 install_element(VIEW_NODE, &show_ip_bgp_import_check_cmd);
d62a17ae 1309 install_element(VIEW_NODE, &show_ip_bgp_instance_all_nexthop_cmd);
718e3744 1310}
228da428 1311
d62a17ae 1312void bgp_scan_finish(struct bgp *bgp)
228da428 1313{
d62a17ae 1314 afi_t afi;
6c88b44d 1315
d62a17ae 1316 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
1317 /* Only the current one needs to be reset. */
f663c581
RW
1318 bgp_nexthop_cache_reset(&bgp->nexthop_cache_table[afi]);
1319 bgp_nexthop_cache_reset(&bgp->import_check_table[afi]);
228da428 1320
3292693b
DS
1321 bgp->connected_table[afi]->route_table->cleanup =
1322 bgp_connected_cleanup;
d62a17ae 1323 bgp_table_unlock(bgp->connected_table[afi]);
1324 bgp->connected_table[afi] = NULL;
d62a17ae 1325 }
228da428 1326}
987a720a
DS
1327
1328char *bgp_nexthop_dump_bnc_flags(struct bgp_nexthop_cache *bnc, char *buf,
1329 size_t len)
1330{
1331 if (bnc->flags == 0) {
1332 snprintfrr(buf, len, "None ");
1333 return buf;
1334 }
1335
1336 snprintfrr(buf, len, "%s%s%s%s%s%s%s",
1337 CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) ? "Valid " : "",
1338 CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED) ? "Reg " : "",
1339 CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED) ? "Conn " : "",
1340 CHECK_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED) ? "Notify "
1341 : "",
1342 CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE) ? "Static " : "",
1343 CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)
1344 ? "Static Exact "
1345 : "",
1346 CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID)
1347 ? "Label Valid "
1348 : "");
1349
1350 return buf;
1351}
df2a41a9
DS
1352
1353char *bgp_nexthop_dump_bnc_change_flags(struct bgp_nexthop_cache *bnc,
1354 char *buf, size_t len)
1355{
1356 if (bnc->flags == 0) {
1357 snprintfrr(buf, len, "None ");
1358 return buf;
1359 }
1360
1361 snprintfrr(buf, len, "%s%s%s",
1362 CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED)
1363 ? "Changed "
1364 : "",
1365 CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED)
1366 ? "Metric "
1367 : "",
1368 CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CONNECTED_CHANGED)
1369 ? "Connected "
1370 : "");
1371
1372 return buf;
1373}