]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_nexthop.c
*: Properly use memset() when zeroing
[mirror_frr.git] / bgpd / bgp_nexthop.c
1 /* BGP nexthop scan
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 */
20
21 #include <zebra.h>
22
23 #include "command.h"
24 #include "thread.h"
25 #include "prefix.h"
26 #include "zclient.h"
27 #include "stream.h"
28 #include "network.h"
29 #include "log.h"
30 #include "memory.h"
31 #include "hash.h"
32 #include "jhash.h"
33 #include "nexthop.h"
34 #include "queue.h"
35 #include "filter.h"
36 #include "printfrr.h"
37
38 #include "bgpd/bgpd.h"
39 #include "bgpd/bgp_route.h"
40 #include "bgpd/bgp_attr.h"
41 #include "bgpd/bgp_nexthop.h"
42 #include "bgpd/bgp_nht.h"
43 #include "bgpd/bgp_debug.h"
44 #include "bgpd/bgp_damp.h"
45 #include "bgpd/bgp_fsm.h"
46 #include "bgpd/bgp_vty.h"
47 #include "bgpd/bgp_rd.h"
48
49 DEFINE_MTYPE_STATIC(BGPD, MARTIAN_STRING, "BGP Martian Addr Intf String");
50
51 int bgp_nexthop_cache_compare(const struct bgp_nexthop_cache *a,
52 const struct bgp_nexthop_cache *b)
53 {
54 if (a->srte_color < b->srte_color)
55 return -1;
56 if (a->srte_color > b->srte_color)
57 return 1;
58
59 return prefix_cmp(&a->prefix, &b->prefix);
60 }
61
62 const char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size)
63 {
64 return prefix2str(&bnc->prefix, buf, size);
65 }
66
67 void bnc_nexthop_free(struct bgp_nexthop_cache *bnc)
68 {
69 nexthops_free(bnc->nexthop);
70 }
71
72 struct bgp_nexthop_cache *bnc_new(struct bgp_nexthop_cache_head *tree,
73 struct prefix *prefix, uint32_t srte_color)
74 {
75 struct bgp_nexthop_cache *bnc;
76
77 bnc = XCALLOC(MTYPE_BGP_NEXTHOP_CACHE,
78 sizeof(struct bgp_nexthop_cache));
79 bnc->prefix = *prefix;
80 bnc->srte_color = srte_color;
81 bnc->tree = tree;
82 LIST_INIT(&(bnc->paths));
83 bgp_nexthop_cache_add(tree, bnc);
84
85 return bnc;
86 }
87
88 bool bnc_existing_for_prefix(struct bgp_nexthop_cache *bnc)
89 {
90 struct bgp_nexthop_cache *bnc_tmp;
91
92 frr_each (bgp_nexthop_cache, bnc->tree, bnc_tmp) {
93 if (bnc_tmp == bnc)
94 continue;
95 if (prefix_cmp(&bnc->prefix, &bnc_tmp->prefix) == 0)
96 return true;
97 }
98 return false;
99 }
100
101 void bnc_free(struct bgp_nexthop_cache *bnc)
102 {
103 bnc_nexthop_free(bnc);
104 bgp_nexthop_cache_del(bnc->tree, bnc);
105 XFREE(MTYPE_BGP_NEXTHOP_CACHE, bnc);
106 }
107
108 struct bgp_nexthop_cache *bnc_find(struct bgp_nexthop_cache_head *tree,
109 struct prefix *prefix, uint32_t srte_color)
110 {
111 struct bgp_nexthop_cache bnc = {};
112
113 if (!tree)
114 return NULL;
115
116 bnc.prefix = *prefix;
117 bnc.srte_color = srte_color;
118 return bgp_nexthop_cache_find(tree, &bnc);
119 }
120
121 /* Reset and free all BGP nexthop cache. */
122 static void bgp_nexthop_cache_reset(struct bgp_nexthop_cache_head *tree)
123 {
124 struct bgp_nexthop_cache *bnc;
125
126 while (bgp_nexthop_cache_count(tree) > 0) {
127 bnc = bgp_nexthop_cache_first(tree);
128
129 while (!LIST_EMPTY(&(bnc->paths))) {
130 struct bgp_path_info *path = LIST_FIRST(&(bnc->paths));
131
132 path_nh_map(path, bnc, false);
133 }
134
135 bnc_free(bnc);
136 }
137 }
138
139 static void *bgp_tip_hash_alloc(void *p)
140 {
141 const struct in_addr *val = (const struct in_addr *)p;
142 struct tip_addr *addr;
143
144 addr = XMALLOC(MTYPE_TIP_ADDR, sizeof(struct tip_addr));
145 addr->refcnt = 0;
146 addr->addr.s_addr = val->s_addr;
147
148 return addr;
149 }
150
151 static void bgp_tip_hash_free(void *addr)
152 {
153 XFREE(MTYPE_TIP_ADDR, addr);
154 }
155
156 static unsigned int bgp_tip_hash_key_make(const void *p)
157 {
158 const struct tip_addr *addr = p;
159
160 return jhash_1word(addr->addr.s_addr, 0);
161 }
162
163 static bool bgp_tip_hash_cmp(const void *p1, const void *p2)
164 {
165 const struct tip_addr *addr1 = p1;
166 const struct tip_addr *addr2 = p2;
167
168 return addr1->addr.s_addr == addr2->addr.s_addr;
169 }
170
171 void bgp_tip_hash_init(struct bgp *bgp)
172 {
173 bgp->tip_hash = hash_create(bgp_tip_hash_key_make, bgp_tip_hash_cmp,
174 "BGP TIP hash");
175 }
176
177 void bgp_tip_hash_destroy(struct bgp *bgp)
178 {
179 if (bgp->tip_hash == NULL)
180 return;
181 hash_clean(bgp->tip_hash, bgp_tip_hash_free);
182 hash_free(bgp->tip_hash);
183 bgp->tip_hash = NULL;
184 }
185
186 void bgp_tip_add(struct bgp *bgp, struct in_addr *tip)
187 {
188 struct tip_addr tmp;
189 struct tip_addr *addr;
190
191 tmp.addr = *tip;
192
193 addr = hash_get(bgp->tip_hash, &tmp, bgp_tip_hash_alloc);
194 addr->refcnt++;
195 }
196
197 void bgp_tip_del(struct bgp *bgp, struct in_addr *tip)
198 {
199 struct tip_addr tmp;
200 struct tip_addr *addr;
201
202 tmp.addr = *tip;
203
204 addr = hash_lookup(bgp->tip_hash, &tmp);
205 /* may have been deleted earlier by bgp_interface_down() */
206 if (addr == NULL)
207 return;
208
209 addr->refcnt--;
210
211 if (addr->refcnt == 0) {
212 hash_release(bgp->tip_hash, addr);
213 XFREE(MTYPE_TIP_ADDR, addr);
214 }
215 }
216
217 /* BGP own address structure */
218 struct bgp_addr {
219 struct prefix p;
220 struct list *ifp_name_list;
221 };
222
223 static void show_address_entry(struct hash_bucket *bucket, void *args)
224 {
225 struct vty *vty = (struct vty *)args;
226 struct bgp_addr *addr = (struct bgp_addr *)bucket->data;
227 char *name;
228 struct listnode *node;
229 char str[INET6_ADDRSTRLEN] = {0};
230
231 vty_out(vty, "addr: %s, count: %d : ",
232 inet_ntop(addr->p.family, &(addr->p.u.prefix),
233 str, INET6_ADDRSTRLEN),
234 addr->ifp_name_list->count);
235
236 for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
237 vty_out(vty, " %s,", name);
238 }
239
240 vty_out(vty, "\n");
241 }
242
243 void bgp_nexthop_show_address_hash(struct vty *vty, struct bgp *bgp)
244 {
245 hash_iterate(bgp->address_hash,
246 (void (*)(struct hash_bucket *, void *))show_address_entry,
247 vty);
248 }
249
250 static void bgp_address_hash_string_del(void *val)
251 {
252 char *data = val;
253
254 XFREE(MTYPE_MARTIAN_STRING, data);
255 }
256
257 static void *bgp_address_hash_alloc(void *p)
258 {
259 struct bgp_addr *copy_addr = p;
260 struct bgp_addr *addr = NULL;
261
262 addr = XMALLOC(MTYPE_BGP_ADDR, sizeof(struct bgp_addr));
263 prefix_copy(&addr->p, &copy_addr->p);
264
265 addr->ifp_name_list = list_new();
266 addr->ifp_name_list->del = bgp_address_hash_string_del;
267
268 return addr;
269 }
270
271 static void bgp_address_hash_free(void *data)
272 {
273 struct bgp_addr *addr = data;
274
275 list_delete(&addr->ifp_name_list);
276 XFREE(MTYPE_BGP_ADDR, addr);
277 }
278
279 static unsigned int bgp_address_hash_key_make(const void *p)
280 {
281 const struct bgp_addr *addr = p;
282
283 return prefix_hash_key(&addr->p);
284 }
285
286 static bool bgp_address_hash_cmp(const void *p1, const void *p2)
287 {
288 const struct bgp_addr *addr1 = p1;
289 const struct bgp_addr *addr2 = p2;
290
291 return prefix_same(&addr1->p, &addr2->p);
292 }
293
294 void bgp_address_init(struct bgp *bgp)
295 {
296 bgp->address_hash =
297 hash_create(bgp_address_hash_key_make, bgp_address_hash_cmp,
298 "BGP Connected Address Hash");
299 }
300
301 void bgp_address_destroy(struct bgp *bgp)
302 {
303 if (bgp->address_hash == NULL)
304 return;
305 hash_clean(bgp->address_hash, bgp_address_hash_free);
306 hash_free(bgp->address_hash);
307 bgp->address_hash = NULL;
308 }
309
310 static void bgp_address_add(struct bgp *bgp, struct connected *ifc,
311 struct prefix *p)
312 {
313 struct bgp_addr tmp;
314 struct bgp_addr *addr;
315 struct listnode *node;
316 char *name;
317
318 tmp.p = *p;
319
320 if (tmp.p.family == AF_INET)
321 tmp.p.prefixlen = IPV4_MAX_BITLEN;
322 else if (tmp.p.family == AF_INET6)
323 tmp.p.prefixlen = IPV6_MAX_BITLEN;
324
325 addr = hash_get(bgp->address_hash, &tmp, bgp_address_hash_alloc);
326
327 for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
328 if (strcmp(ifc->ifp->name, name) == 0)
329 break;
330 }
331 if (!node) {
332 name = XSTRDUP(MTYPE_MARTIAN_STRING, ifc->ifp->name);
333 listnode_add(addr->ifp_name_list, name);
334 }
335 }
336
337 static void bgp_address_del(struct bgp *bgp, struct connected *ifc,
338 struct prefix *p)
339 {
340 struct bgp_addr tmp;
341 struct bgp_addr *addr;
342 struct listnode *node;
343 char *name;
344
345 tmp.p = *p;
346
347 if (tmp.p.family == AF_INET)
348 tmp.p.prefixlen = IPV4_MAX_BITLEN;
349 else if (tmp.p.family == AF_INET6)
350 tmp.p.prefixlen = IPV6_MAX_BITLEN;
351
352 addr = hash_lookup(bgp->address_hash, &tmp);
353 /* may have been deleted earlier by bgp_interface_down() */
354 if (addr == NULL)
355 return;
356
357 for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
358 if (strcmp(ifc->ifp->name, name) == 0)
359 break;
360 }
361
362 if (node) {
363 list_delete_node(addr->ifp_name_list, node);
364 XFREE(MTYPE_MARTIAN_STRING, name);
365 }
366
367 if (addr->ifp_name_list->count == 0) {
368 hash_release(bgp->address_hash, addr);
369 list_delete(&addr->ifp_name_list);
370 XFREE(MTYPE_BGP_ADDR, addr);
371 }
372 }
373
374
375 struct bgp_connected_ref {
376 unsigned int refcnt;
377 };
378
379 void bgp_connected_add(struct bgp *bgp, struct connected *ifc)
380 {
381 struct prefix p;
382 struct prefix *addr;
383 struct bgp_dest *dest;
384 struct bgp_connected_ref *bc;
385 struct listnode *node, *nnode;
386 struct peer *peer;
387
388 addr = ifc->address;
389
390 p = *(CONNECTED_PREFIX(ifc));
391 if (addr->family == AF_INET) {
392 apply_mask_ipv4((struct prefix_ipv4 *)&p);
393
394 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
395 return;
396
397 bgp_address_add(bgp, ifc, addr);
398
399 dest = bgp_node_get(bgp->connected_table[AFI_IP], &p);
400 bc = bgp_dest_get_bgp_connected_ref_info(dest);
401 if (bc)
402 bc->refcnt++;
403 else {
404 bc = XCALLOC(MTYPE_BGP_CONN,
405 sizeof(struct bgp_connected_ref));
406 bc->refcnt = 1;
407 bgp_dest_set_bgp_connected_ref_info(dest, bc);
408 }
409
410 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
411 if (peer->conf_if
412 && (strcmp(peer->conf_if, ifc->ifp->name) == 0)
413 && !peer_established(peer)
414 && !CHECK_FLAG(peer->flags,
415 PEER_FLAG_IFPEER_V6ONLY)) {
416 if (peer_active(peer))
417 BGP_EVENT_ADD(peer, BGP_Stop);
418 BGP_EVENT_ADD(peer, BGP_Start);
419 }
420 }
421 } else if (addr->family == AF_INET6) {
422 apply_mask_ipv6((struct prefix_ipv6 *)&p);
423
424 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
425 return;
426
427 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
428 return;
429
430 bgp_address_add(bgp, ifc, addr);
431
432 dest = bgp_node_get(bgp->connected_table[AFI_IP6], &p);
433
434 bc = bgp_dest_get_bgp_connected_ref_info(dest);
435 if (bc)
436 bc->refcnt++;
437 else {
438 bc = XCALLOC(MTYPE_BGP_CONN,
439 sizeof(struct bgp_connected_ref));
440 bc->refcnt = 1;
441 bgp_dest_set_bgp_connected_ref_info(dest, bc);
442 }
443 }
444 }
445
446 void bgp_connected_delete(struct bgp *bgp, struct connected *ifc)
447 {
448 struct prefix p;
449 struct prefix *addr;
450 struct bgp_dest *dest = NULL;
451 struct bgp_connected_ref *bc;
452
453 addr = ifc->address;
454
455 p = *(CONNECTED_PREFIX(ifc));
456 apply_mask(&p);
457 if (addr->family == AF_INET) {
458 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
459 return;
460
461 bgp_address_del(bgp, ifc, addr);
462
463 dest = bgp_node_lookup(bgp->connected_table[AFI_IP], &p);
464 } else if (addr->family == AF_INET6) {
465 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
466 return;
467
468 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
469 return;
470
471 bgp_address_del(bgp, ifc, addr);
472
473 dest = bgp_node_lookup(bgp->connected_table[AFI_IP6], &p);
474 }
475
476 if (!dest)
477 return;
478
479 bc = bgp_dest_get_bgp_connected_ref_info(dest);
480 bc->refcnt--;
481 if (bc->refcnt == 0) {
482 XFREE(MTYPE_BGP_CONN, bc);
483 bgp_dest_set_bgp_connected_ref_info(dest, NULL);
484 }
485 bgp_dest_unlock_node(dest);
486 bgp_dest_unlock_node(dest);
487 }
488
489 static void bgp_connected_cleanup(struct route_table *table,
490 struct route_node *rn)
491 {
492 struct bgp_connected_ref *bc;
493 struct bgp_dest *bn = bgp_dest_from_rnode(rn);
494
495 bc = bgp_dest_get_bgp_connected_ref_info(bn);
496 if (!bc)
497 return;
498
499 bc->refcnt--;
500 if (bc->refcnt == 0) {
501 XFREE(MTYPE_BGP_CONN, bc);
502 bgp_dest_set_bgp_connected_ref_info(bn, NULL);
503 }
504 }
505
506 bool bgp_nexthop_self(struct bgp *bgp, afi_t afi, uint8_t type,
507 uint8_t sub_type, struct attr *attr,
508 struct bgp_dest *dest)
509 {
510 uint8_t new_afi = afi == AFI_IP ? AF_INET : AF_INET6;
511 struct bgp_addr tmp_addr = {{0}}, *addr = NULL;
512 struct tip_addr tmp_tip, *tip = NULL;
513 const struct prefix *p = bgp_dest_get_prefix(dest);
514 bool is_bgp_static_route =
515 ((type == ZEBRA_ROUTE_BGP) && (sub_type == BGP_ROUTE_STATIC))
516 ? true
517 : false;
518
519 if (!is_bgp_static_route)
520 new_afi = BGP_ATTR_NEXTHOP_AFI_IP6(attr) ? AF_INET6 : AF_INET;
521
522 tmp_addr.p.family = new_afi;
523 switch (new_afi) {
524 case AF_INET:
525 if (is_bgp_static_route) {
526 tmp_addr.p.u.prefix4 = p->u.prefix4;
527 tmp_addr.p.prefixlen = p->prefixlen;
528 } else {
529 /* Here we need to find out which nexthop to be used*/
530 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
531 tmp_addr.p.u.prefix4 = attr->nexthop;
532 tmp_addr.p.prefixlen = IPV4_MAX_BITLEN;
533 } else if ((attr->mp_nexthop_len)
534 && ((attr->mp_nexthop_len
535 == BGP_ATTR_NHLEN_IPV4)
536 || (attr->mp_nexthop_len
537 == BGP_ATTR_NHLEN_VPNV4))) {
538 tmp_addr.p.u.prefix4 =
539 attr->mp_nexthop_global_in;
540 tmp_addr.p.prefixlen = IPV4_MAX_BITLEN;
541 } else
542 return false;
543 }
544 break;
545 case AF_INET6:
546 if (is_bgp_static_route) {
547 tmp_addr.p.u.prefix6 = p->u.prefix6;
548 tmp_addr.p.prefixlen = p->prefixlen;
549 } else {
550 tmp_addr.p.u.prefix6 = attr->mp_nexthop_global;
551 tmp_addr.p.prefixlen = IPV6_MAX_BITLEN;
552 }
553 break;
554 default:
555 break;
556 }
557
558 addr = hash_lookup(bgp->address_hash, &tmp_addr);
559 if (addr)
560 return true;
561
562 if (new_afi == AF_INET && hashcount(bgp->tip_hash)) {
563 memset(&tmp_tip, 0, sizeof(tmp_tip));
564 tmp_tip.addr = attr->nexthop;
565
566 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
567 tmp_tip.addr = attr->nexthop;
568 } else if ((attr->mp_nexthop_len) &&
569 ((attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4)
570 || (attr->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV4))) {
571 tmp_tip.addr = attr->mp_nexthop_global_in;
572 }
573
574 tip = hash_lookup(bgp->tip_hash, &tmp_tip);
575 if (tip)
576 return true;
577 }
578
579 return false;
580 }
581
582 bool bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer)
583 {
584 struct bgp_dest *dest1;
585 struct bgp_dest *dest2;
586 struct prefix p;
587 int ret;
588
589 p.family = AF_INET;
590 p.prefixlen = IPV4_MAX_BITLEN;
591 p.u.prefix4 = nexthop;
592
593 dest1 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
594 if (!dest1)
595 return false;
596
597 p.family = AF_INET;
598 p.prefixlen = IPV4_MAX_BITLEN;
599 p.u.prefix4 = peer->su.sin.sin_addr;
600
601 dest2 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
602 if (!dest2) {
603 bgp_dest_unlock_node(dest1);
604 return false;
605 }
606
607 ret = (dest1 == dest2);
608
609 bgp_dest_unlock_node(dest1);
610 bgp_dest_unlock_node(dest2);
611
612 return ret;
613 }
614
615 bool bgp_multiaccess_check_v6(struct in6_addr nexthop, struct peer *peer)
616 {
617 struct bgp_dest *dest1;
618 struct bgp_dest *dest2;
619 struct prefix p;
620 int ret;
621
622 p.family = AF_INET6;
623 p.prefixlen = IPV6_MAX_BITLEN;
624 p.u.prefix6 = nexthop;
625
626 dest1 = bgp_node_match(peer->bgp->connected_table[AFI_IP6], &p);
627 if (!dest1)
628 return false;
629
630 p.family = AF_INET6;
631 p.prefixlen = IPV6_MAX_BITLEN;
632 p.u.prefix6 = peer->su.sin6.sin6_addr;
633
634 dest2 = bgp_node_match(peer->bgp->connected_table[AFI_IP6], &p);
635 if (!dest2) {
636 bgp_dest_unlock_node(dest1);
637 return false;
638 }
639
640 ret = (dest1 == dest2);
641
642 bgp_dest_unlock_node(dest1);
643 bgp_dest_unlock_node(dest2);
644
645 return ret;
646 }
647
648 bool bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop,
649 struct update_subgroup *subgrp,
650 struct peer *exclude)
651 {
652 struct bgp_dest *dest1 = NULL, *dest2 = NULL;
653 struct peer_af *paf = NULL;
654 struct prefix p = {0}, np = {0};
655 struct bgp *bgp = NULL;
656
657 np.family = AF_INET6;
658 np.prefixlen = IPV6_MAX_BITLEN;
659 np.u.prefix6 = nexthop;
660
661 p.family = AF_INET;
662 p.prefixlen = IPV6_MAX_BITLEN;
663
664 bgp = SUBGRP_INST(subgrp);
665 dest1 = bgp_node_match(bgp->connected_table[AFI_IP6], &np);
666 if (!dest1)
667 return false;
668
669 SUBGRP_FOREACH_PEER (subgrp, paf) {
670 /* Skip peer we're told to exclude - e.g., source of route. */
671 if (paf->peer == exclude)
672 continue;
673
674 p.u.prefix6 = paf->peer->su.sin6.sin6_addr;
675 dest2 = bgp_node_match(bgp->connected_table[AFI_IP6], &p);
676 if (dest1 == dest2) {
677 bgp_dest_unlock_node(dest1);
678 bgp_dest_unlock_node(dest2);
679 return true;
680 }
681
682 if (dest2)
683 bgp_dest_unlock_node(dest2);
684 }
685
686 bgp_dest_unlock_node(dest1);
687 return false;
688 }
689
690 bool bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
691 struct update_subgroup *subgrp,
692 struct peer *exclude)
693 {
694 struct bgp_dest *dest1, *dest2;
695 struct peer_af *paf;
696 struct prefix p, np;
697 struct bgp *bgp;
698
699 np.family = AF_INET;
700 np.prefixlen = IPV4_MAX_BITLEN;
701 np.u.prefix4 = nexthop;
702
703 p.family = AF_INET;
704 p.prefixlen = IPV4_MAX_BITLEN;
705
706 bgp = SUBGRP_INST(subgrp);
707 dest1 = bgp_node_match(bgp->connected_table[AFI_IP], &np);
708 if (!dest1)
709 return false;
710
711 SUBGRP_FOREACH_PEER (subgrp, paf) {
712 /* Skip peer we're told to exclude - e.g., source of route. */
713 if (paf->peer == exclude)
714 continue;
715
716 p.u.prefix4 = paf->peer->su.sin.sin_addr;
717
718 dest2 = bgp_node_match(bgp->connected_table[AFI_IP], &p);
719 if (dest1 == dest2) {
720 bgp_dest_unlock_node(dest1);
721 bgp_dest_unlock_node(dest2);
722 return true;
723 }
724
725 if (dest2)
726 bgp_dest_unlock_node(dest2);
727 }
728
729 bgp_dest_unlock_node(dest1);
730 return false;
731 }
732
733 static void bgp_show_nexthop_paths(struct vty *vty, struct bgp *bgp,
734 struct bgp_nexthop_cache *bnc)
735 {
736 struct bgp_dest *dest;
737 struct bgp_path_info *path;
738 int afi;
739 safi_t safi;
740 struct bgp_table *table;
741 struct bgp *bgp_path;
742 char buf1[BUFSIZ];
743
744 vty_out(vty, " Paths:\n");
745 LIST_FOREACH (path, &(bnc->paths), nh_thread) {
746 dest = path->net;
747 assert(dest && bgp_dest_table(dest));
748 afi = family2afi(bgp_dest_get_prefix(dest)->family);
749 table = bgp_dest_table(dest);
750 safi = table->safi;
751 bgp_path = table->bgp;
752
753 if (dest->pdest) {
754 prefix_rd2str((struct prefix_rd *)bgp_dest_get_prefix(dest->pdest),
755 buf1, sizeof(buf1));
756 vty_out(vty, " %d/%d %pBD RD %s %s flags 0x%x\n",
757 afi, safi, dest, buf1, bgp_path->name_pretty, path->flags);
758 } else
759 vty_out(vty, " %d/%d %pBD %s flags 0x%x\n",
760 afi, safi, dest, bgp_path->name_pretty, path->flags);
761 }
762 }
763
764 static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp,
765 struct bgp_nexthop_cache *bnc)
766 {
767 char buf[PREFIX2STR_BUFFER];
768 struct nexthop *nexthop;
769
770 for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next) {
771 switch (nexthop->type) {
772 case NEXTHOP_TYPE_IPV6:
773 vty_out(vty, " gate %s\n",
774 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
775 sizeof(buf)));
776 break;
777 case NEXTHOP_TYPE_IPV6_IFINDEX:
778 vty_out(vty, " gate %s, if %s\n",
779 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
780 sizeof(buf)),
781 ifindex2ifname(bnc->ifindex ? bnc->ifindex
782 : nexthop->ifindex,
783 bgp->vrf_id));
784 break;
785 case NEXTHOP_TYPE_IPV4:
786 vty_out(vty, " gate %s\n",
787 inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
788 sizeof(buf)));
789 break;
790 case NEXTHOP_TYPE_IFINDEX:
791 vty_out(vty, " if %s\n",
792 ifindex2ifname(bnc->ifindex ? bnc->ifindex
793 : nexthop->ifindex,
794 bgp->vrf_id));
795 break;
796 case NEXTHOP_TYPE_IPV4_IFINDEX:
797 vty_out(vty, " gate %s, if %s\n",
798 inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
799 sizeof(buf)),
800 ifindex2ifname(bnc->ifindex ? bnc->ifindex
801 : nexthop->ifindex,
802 bgp->vrf_id));
803 break;
804 case NEXTHOP_TYPE_BLACKHOLE:
805 vty_out(vty, " blackhole\n");
806 break;
807 default:
808 vty_out(vty, " invalid nexthop type %u\n",
809 nexthop->type);
810 }
811 }
812 }
813
814 static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp,
815 struct bgp_nexthop_cache *bnc,
816 bool specific)
817 {
818 char buf[PREFIX2STR_BUFFER];
819 time_t tbuf;
820 struct peer *peer;
821
822 peer = (struct peer *)bnc->nht_info;
823
824 if (bnc->srte_color)
825 vty_out(vty, " SR-TE color %u -", bnc->srte_color);
826 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) {
827 vty_out(vty, " %s valid [IGP metric %d], #paths %d",
828 inet_ntop(bnc->prefix.family, &bnc->prefix.u.prefix,
829 buf, sizeof(buf)),
830 bnc->metric, bnc->path_count);
831 if (peer)
832 vty_out(vty, ", peer %s", peer->host);
833 if (bnc->is_evpn_gwip_nexthop)
834 vty_out(vty, " EVPN Gateway IP");
835 vty_out(vty, "\n");
836 bgp_show_nexthops_detail(vty, bgp, bnc);
837 } else if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_EVPN_INCOMPLETE)) {
838 vty_out(vty,
839 " %s overlay index unresolved [IGP metric %d], #paths %d",
840 inet_ntop(bnc->prefix.family, &bnc->prefix.u.prefix,
841 buf, sizeof(buf)),
842 bnc->metric, bnc->path_count);
843 if (bnc->is_evpn_gwip_nexthop)
844 vty_out(vty, " EVPN Gateway IP");
845 vty_out(vty, "\n");
846 bgp_show_nexthops_detail(vty, bgp, bnc);
847 } else {
848 vty_out(vty, " %s invalid, #paths %d",
849 inet_ntop(bnc->prefix.family, &bnc->prefix.u.prefix,
850 buf, sizeof(buf)),
851 bnc->path_count);
852 if (peer)
853 vty_out(vty, ", peer %s", peer->host);
854 if (bnc->is_evpn_gwip_nexthop)
855 vty_out(vty, " EVPN Gateway IP");
856 vty_out(vty, "\n");
857 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
858 vty_out(vty, " Must be Connected\n");
859 if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
860 vty_out(vty, " Is not Registered\n");
861 }
862 tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
863 vty_out(vty, " Last update: %s", ctime(&tbuf));
864 vty_out(vty, "\n");
865
866 /* show paths dependent on nexthop, if needed. */
867 if (specific)
868 bgp_show_nexthop_paths(vty, bgp, bnc);
869 }
870
871 static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp,
872 bool import_table)
873 {
874 struct bgp_nexthop_cache *bnc;
875 afi_t afi;
876 struct bgp_nexthop_cache_head(*tree)[AFI_MAX];
877
878 if (import_table)
879 vty_out(vty, "Current BGP import check cache:\n");
880 else
881 vty_out(vty, "Current BGP nexthop cache:\n");
882 if (import_table)
883 tree = &bgp->import_check_table;
884 else
885 tree = &bgp->nexthop_cache_table;
886 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
887 frr_each (bgp_nexthop_cache, &(*tree)[afi], bnc)
888 bgp_show_nexthop(vty, bgp, bnc, false);
889 }
890 }
891
892 static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name,
893 const char *nhopip_str,
894 bool import_table)
895 {
896 struct bgp *bgp;
897
898 if (name)
899 bgp = bgp_lookup_by_name(name);
900 else
901 bgp = bgp_get_default();
902 if (!bgp) {
903 vty_out(vty, "%% No such BGP instance exist\n");
904 return CMD_WARNING;
905 }
906
907 if (nhopip_str) {
908 struct prefix nhop;
909 struct bgp_nexthop_cache_head (*tree)[AFI_MAX];
910 struct bgp_nexthop_cache *bnc;
911
912 if (!str2prefix(nhopip_str, &nhop)) {
913 vty_out(vty, "nexthop address is malformed\n");
914 return CMD_WARNING;
915 }
916 tree = import_table ? &bgp->import_check_table
917 : &bgp->nexthop_cache_table;
918 bnc = bnc_find(tree[family2afi(nhop.family)], &nhop, 0);
919 if (!bnc) {
920 vty_out(vty, "specified nexthop does not have entry\n");
921 return CMD_SUCCESS;
922 }
923 bgp_show_nexthop(vty, bgp, bnc, true);
924 } else
925 bgp_show_nexthops(vty, bgp, import_table);
926
927 return CMD_SUCCESS;
928 }
929
930 static void bgp_show_all_instances_nexthops_vty(struct vty *vty)
931 {
932 struct listnode *node, *nnode;
933 struct bgp *bgp;
934
935 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
936 vty_out(vty, "\nInstance %s:\n",
937 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
938 ? VRF_DEFAULT_NAME
939 : bgp->name);
940 bgp_show_nexthops(vty, bgp, false);
941 }
942 }
943
944 DEFUN (show_ip_bgp_nexthop,
945 show_ip_bgp_nexthop_cmd,
946 "show [ip] bgp [<view|vrf> VIEWVRFNAME] nexthop [<A.B.C.D|X:X::X:X>] [detail]",
947 SHOW_STR
948 IP_STR
949 BGP_STR
950 BGP_INSTANCE_HELP_STR
951 "BGP nexthop table\n"
952 "IPv4 nexthop address\n"
953 "IPv6 nexthop address\n"
954 "Show detailed information\n")
955 {
956 int idx = 0;
957 int nh_idx = 0;
958 char *vrf = NULL;
959 char *nhop_ip = NULL;
960
961 if (argv_find(argv, argc, "view", &idx)
962 || argv_find(argv, argc, "vrf", &idx))
963 vrf = argv[++idx]->arg;
964
965 if (argv_find(argv, argc, "A.B.C.D", &nh_idx)
966 || argv_find(argv, argc, "X:X::X:X", &nh_idx))
967 nhop_ip = argv[nh_idx]->arg;
968
969 return show_ip_bgp_nexthop_table(vty, vrf, nhop_ip, false);
970 }
971
972 DEFUN (show_ip_bgp_import_check,
973 show_ip_bgp_import_check_cmd,
974 "show [ip] bgp [<view|vrf> VIEWVRFNAME] import-check-table [detail]",
975 SHOW_STR
976 IP_STR
977 BGP_STR
978 BGP_INSTANCE_HELP_STR
979 "BGP import check table\n"
980 "Show detailed information\n")
981 {
982 int idx = 0;
983 char *vrf = NULL;
984
985 if (argv_find(argv, argc, "view", &idx)
986 || argv_find(argv, argc, "vrf", &idx))
987 vrf = argv[++idx]->arg;
988
989 return show_ip_bgp_nexthop_table(vty, vrf, NULL, true);
990 }
991
992 DEFUN (show_ip_bgp_instance_all_nexthop,
993 show_ip_bgp_instance_all_nexthop_cmd,
994 "show [ip] bgp <view|vrf> all nexthop",
995 SHOW_STR
996 IP_STR
997 BGP_STR
998 BGP_INSTANCE_ALL_HELP_STR
999 "BGP nexthop table\n")
1000 {
1001 bgp_show_all_instances_nexthops_vty(vty);
1002 return CMD_SUCCESS;
1003 }
1004
1005 void bgp_scan_init(struct bgp *bgp)
1006 {
1007 afi_t afi;
1008
1009 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
1010 bgp_nexthop_cache_init(&bgp->nexthop_cache_table[afi]);
1011 bgp_nexthop_cache_init(&bgp->import_check_table[afi]);
1012 bgp->connected_table[afi] = bgp_table_init(bgp, afi,
1013 SAFI_UNICAST);
1014 }
1015 }
1016
1017 void bgp_scan_vty_init(void)
1018 {
1019 install_element(VIEW_NODE, &show_ip_bgp_nexthop_cmd);
1020 install_element(VIEW_NODE, &show_ip_bgp_import_check_cmd);
1021 install_element(VIEW_NODE, &show_ip_bgp_instance_all_nexthop_cmd);
1022 }
1023
1024 void bgp_scan_finish(struct bgp *bgp)
1025 {
1026 afi_t afi;
1027
1028 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
1029 /* Only the current one needs to be reset. */
1030 bgp_nexthop_cache_reset(&bgp->nexthop_cache_table[afi]);
1031 bgp_nexthop_cache_reset(&bgp->import_check_table[afi]);
1032
1033 bgp->connected_table[afi]->route_table->cleanup =
1034 bgp_connected_cleanup;
1035 bgp_table_unlock(bgp->connected_table[afi]);
1036 bgp->connected_table[afi] = NULL;
1037 }
1038 }
1039
1040 char *bgp_nexthop_dump_bnc_flags(struct bgp_nexthop_cache *bnc, char *buf,
1041 size_t len)
1042 {
1043 if (bnc->flags == 0) {
1044 snprintfrr(buf, len, "None ");
1045 return buf;
1046 }
1047
1048 snprintfrr(buf, len, "%s%s%s%s%s%s%s",
1049 CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) ? "Valid " : "",
1050 CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED) ? "Reg " : "",
1051 CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED) ? "Conn " : "",
1052 CHECK_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED) ? "Notify "
1053 : "",
1054 CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE) ? "Static " : "",
1055 CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)
1056 ? "Static Exact "
1057 : "",
1058 CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID)
1059 ? "Label Valid "
1060 : "");
1061
1062 return buf;
1063 }
1064
1065 char *bgp_nexthop_dump_bnc_change_flags(struct bgp_nexthop_cache *bnc,
1066 char *buf, size_t len)
1067 {
1068 if (bnc->flags == 0) {
1069 snprintfrr(buf, len, "None ");
1070 return buf;
1071 }
1072
1073 snprintfrr(buf, len, "%s%s%s",
1074 CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED)
1075 ? "Changed "
1076 : "",
1077 CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED)
1078 ? "Metric "
1079 : "",
1080 CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CONNECTED_CHANGED)
1081 ? "Connected "
1082 : "");
1083
1084 return buf;
1085 }