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