]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_nexthop.c
Merge pull request #6011 from patrasar/pim-no-msdp-group-cmd
[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
37 #include "bgpd/bgpd.h"
38 #include "bgpd/bgp_table.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
48 DEFINE_MTYPE_STATIC(BGPD, MARTIAN_STRING, "BGP Martian Address Intf String");
49
50 char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size)
51 {
52 prefix2str(bgp_node_get_prefix(bnc->node), buf, size);
53 return buf;
54 }
55
56 void bnc_nexthop_free(struct bgp_nexthop_cache *bnc)
57 {
58 nexthops_free(bnc->nexthop);
59 }
60
61 struct bgp_nexthop_cache *bnc_new(void)
62 {
63 struct bgp_nexthop_cache *bnc;
64
65 bnc = XCALLOC(MTYPE_BGP_NEXTHOP_CACHE,
66 sizeof(struct bgp_nexthop_cache));
67 LIST_INIT(&(bnc->paths));
68 return bnc;
69 }
70
71 void bnc_free(struct bgp_nexthop_cache *bnc)
72 {
73 bnc_nexthop_free(bnc);
74 XFREE(MTYPE_BGP_NEXTHOP_CACHE, bnc);
75 }
76
77 /* Reset and free all BGP nexthop cache. */
78 static void bgp_nexthop_cache_reset(struct bgp_table *table)
79 {
80 struct bgp_node *rn;
81 struct bgp_nexthop_cache *bnc;
82
83 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
84 bnc = bgp_node_get_bgp_nexthop_info(rn);
85 if (!bnc)
86 continue;
87
88 while (!LIST_EMPTY(&(bnc->paths))) {
89 struct bgp_path_info *path = LIST_FIRST(&(bnc->paths));
90
91 path_nh_map(path, bnc, false);
92 }
93
94 bnc_free(bnc);
95 bgp_node_set_bgp_nexthop_info(rn, NULL);
96 bgp_unlock_node(rn);
97 }
98 }
99
100 static void *bgp_tip_hash_alloc(void *p)
101 {
102 const struct in_addr *val = (const struct in_addr *)p;
103 struct tip_addr *addr;
104
105 addr = XMALLOC(MTYPE_TIP_ADDR, sizeof(struct tip_addr));
106 addr->refcnt = 0;
107 addr->addr.s_addr = val->s_addr;
108
109 return addr;
110 }
111
112 static void bgp_tip_hash_free(void *addr)
113 {
114 XFREE(MTYPE_TIP_ADDR, addr);
115 }
116
117 static unsigned int bgp_tip_hash_key_make(const void *p)
118 {
119 const struct tip_addr *addr = p;
120
121 return jhash_1word(addr->addr.s_addr, 0);
122 }
123
124 static bool bgp_tip_hash_cmp(const void *p1, const void *p2)
125 {
126 const struct tip_addr *addr1 = p1;
127 const struct tip_addr *addr2 = p2;
128
129 return addr1->addr.s_addr == addr2->addr.s_addr;
130 }
131
132 void bgp_tip_hash_init(struct bgp *bgp)
133 {
134 bgp->tip_hash = hash_create(bgp_tip_hash_key_make, bgp_tip_hash_cmp,
135 "BGP TIP hash");
136 }
137
138 void bgp_tip_hash_destroy(struct bgp *bgp)
139 {
140 if (bgp->tip_hash == NULL)
141 return;
142 hash_clean(bgp->tip_hash, bgp_tip_hash_free);
143 hash_free(bgp->tip_hash);
144 bgp->tip_hash = NULL;
145 }
146
147 void bgp_tip_add(struct bgp *bgp, struct in_addr *tip)
148 {
149 struct tip_addr tmp;
150 struct tip_addr *addr;
151
152 tmp.addr = *tip;
153
154 addr = hash_get(bgp->tip_hash, &tmp, bgp_tip_hash_alloc);
155 if (!addr)
156 return;
157
158 addr->refcnt++;
159 }
160
161 void bgp_tip_del(struct bgp *bgp, struct in_addr *tip)
162 {
163 struct tip_addr tmp;
164 struct tip_addr *addr;
165
166 tmp.addr = *tip;
167
168 addr = hash_lookup(bgp->tip_hash, &tmp);
169 /* may have been deleted earlier by bgp_interface_down() */
170 if (addr == NULL)
171 return;
172
173 addr->refcnt--;
174
175 if (addr->refcnt == 0) {
176 hash_release(bgp->tip_hash, addr);
177 XFREE(MTYPE_TIP_ADDR, addr);
178 }
179 }
180
181 /* BGP own address structure */
182 struct bgp_addr {
183 struct prefix p;
184 struct list *ifp_name_list;
185 };
186
187 static void show_address_entry(struct hash_bucket *bucket, void *args)
188 {
189 struct vty *vty = (struct vty *)args;
190 struct bgp_addr *addr = (struct bgp_addr *)bucket->data;
191 char *name;
192 struct listnode *node;
193 char str[INET6_ADDRSTRLEN] = {0};
194
195 vty_out(vty, "addr: %s, count: %d : ",
196 inet_ntop(addr->p.family, &(addr->p.u.prefix),
197 str, INET6_ADDRSTRLEN),
198 addr->ifp_name_list->count);
199
200 for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
201 vty_out(vty, " %s,", name);
202 }
203
204 vty_out(vty, "\n");
205 }
206
207 void bgp_nexthop_show_address_hash(struct vty *vty, struct bgp *bgp)
208 {
209 hash_iterate(bgp->address_hash,
210 (void (*)(struct hash_bucket *, void *))show_address_entry,
211 vty);
212 }
213
214 static void bgp_address_hash_string_del(void *val)
215 {
216 char *data = val;
217
218 XFREE(MTYPE_MARTIAN_STRING, data);
219 }
220
221 static void *bgp_address_hash_alloc(void *p)
222 {
223 struct bgp_addr *copy_addr = p;
224 struct bgp_addr *addr = NULL;
225
226 addr = XMALLOC(MTYPE_BGP_ADDR, sizeof(struct bgp_addr));
227 prefix_copy(&addr->p, &copy_addr->p);
228
229 addr->ifp_name_list = list_new();
230 addr->ifp_name_list->del = bgp_address_hash_string_del;
231
232 return addr;
233 }
234
235 static void bgp_address_hash_free(void *data)
236 {
237 struct bgp_addr *addr = data;
238
239 list_delete(&addr->ifp_name_list);
240 XFREE(MTYPE_BGP_ADDR, addr);
241 }
242
243 static unsigned int bgp_address_hash_key_make(const void *p)
244 {
245 const struct bgp_addr *addr = p;
246
247 return prefix_hash_key(&addr->p);
248 }
249
250 static bool bgp_address_hash_cmp(const void *p1, const void *p2)
251 {
252 const struct bgp_addr *addr1 = p1;
253 const struct bgp_addr *addr2 = p2;
254
255 return prefix_same(&addr1->p, &addr2->p);
256 }
257
258 void bgp_address_init(struct bgp *bgp)
259 {
260 bgp->address_hash =
261 hash_create(bgp_address_hash_key_make, bgp_address_hash_cmp,
262 "BGP Connected Address Hash");
263 }
264
265 void bgp_address_destroy(struct bgp *bgp)
266 {
267 if (bgp->address_hash == NULL)
268 return;
269 hash_clean(bgp->address_hash, bgp_address_hash_free);
270 hash_free(bgp->address_hash);
271 bgp->address_hash = NULL;
272 }
273
274 static void bgp_address_add(struct bgp *bgp, struct connected *ifc,
275 struct prefix *p)
276 {
277 struct bgp_addr tmp;
278 struct bgp_addr *addr;
279 struct listnode *node;
280 char *name;
281
282 tmp.p = *p;
283
284 if (tmp.p.family == AF_INET)
285 tmp.p.prefixlen = IPV4_MAX_BITLEN;
286 else if (tmp.p.family == AF_INET6)
287 tmp.p.prefixlen = IPV6_MAX_BITLEN;
288
289 addr = hash_get(bgp->address_hash, &tmp, bgp_address_hash_alloc);
290
291 for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
292 if (strcmp(ifc->ifp->name, name) == 0)
293 break;
294 }
295 if (!node) {
296 name = XSTRDUP(MTYPE_MARTIAN_STRING, ifc->ifp->name);
297 listnode_add(addr->ifp_name_list, name);
298 }
299 }
300
301 static void bgp_address_del(struct bgp *bgp, struct connected *ifc,
302 struct prefix *p)
303 {
304 struct bgp_addr tmp;
305 struct bgp_addr *addr;
306 struct listnode *node;
307 char *name;
308
309 tmp.p = *p;
310
311 if (tmp.p.family == AF_INET)
312 tmp.p.prefixlen = IPV4_MAX_BITLEN;
313 else if (tmp.p.family == AF_INET6)
314 tmp.p.prefixlen = IPV6_MAX_BITLEN;
315
316 addr = hash_lookup(bgp->address_hash, &tmp);
317 /* may have been deleted earlier by bgp_interface_down() */
318 if (addr == NULL)
319 return;
320
321 for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
322 if (strcmp(ifc->ifp->name, name) == 0)
323 break;
324 }
325
326 if (node) {
327 list_delete_node(addr->ifp_name_list, node);
328 XFREE(MTYPE_MARTIAN_STRING, name);
329 }
330
331 if (addr->ifp_name_list->count == 0) {
332 hash_release(bgp->address_hash, addr);
333 list_delete(&addr->ifp_name_list);
334 XFREE(MTYPE_BGP_ADDR, addr);
335 }
336 }
337
338
339 struct bgp_connected_ref {
340 unsigned int refcnt;
341 };
342
343 void bgp_connected_add(struct bgp *bgp, struct connected *ifc)
344 {
345 struct prefix p;
346 struct prefix *addr;
347 struct bgp_node *rn;
348 struct bgp_connected_ref *bc;
349 struct listnode *node, *nnode;
350 struct peer *peer;
351
352 addr = ifc->address;
353
354 p = *(CONNECTED_PREFIX(ifc));
355 if (addr->family == AF_INET) {
356 apply_mask_ipv4((struct prefix_ipv4 *)&p);
357
358 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
359 return;
360
361 bgp_address_add(bgp, ifc, addr);
362
363 rn = bgp_node_get(bgp->connected_table[AFI_IP],
364 (struct prefix *)&p);
365 bc = bgp_node_get_bgp_connected_ref_info(rn);
366 if (bc)
367 bc->refcnt++;
368 else {
369 bc = XCALLOC(MTYPE_BGP_CONN,
370 sizeof(struct bgp_connected_ref));
371 bc->refcnt = 1;
372 bgp_node_set_bgp_connected_ref_info(rn, bc);
373 }
374
375 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
376 if (peer->conf_if
377 && (strcmp(peer->conf_if, ifc->ifp->name) == 0)
378 && peer->status != Established
379 && !CHECK_FLAG(peer->flags,
380 PEER_FLAG_IFPEER_V6ONLY)) {
381 if (peer_active(peer))
382 BGP_EVENT_ADD(peer, BGP_Stop);
383 BGP_EVENT_ADD(peer, BGP_Start);
384 }
385 }
386 } else if (addr->family == AF_INET6) {
387 apply_mask_ipv6((struct prefix_ipv6 *)&p);
388
389 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
390 return;
391
392 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
393 return;
394
395 bgp_address_add(bgp, ifc, addr);
396
397 rn = bgp_node_get(bgp->connected_table[AFI_IP6],
398 (struct prefix *)&p);
399
400 bc = bgp_node_get_bgp_connected_ref_info(rn);
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_node_set_bgp_connected_ref_info(rn, bc);
408 }
409 }
410 }
411
412 void bgp_connected_delete(struct bgp *bgp, struct connected *ifc)
413 {
414 struct prefix p;
415 struct prefix *addr;
416 struct bgp_node *rn = NULL;
417 struct bgp_connected_ref *bc;
418
419 addr = ifc->address;
420
421 p = *(CONNECTED_PREFIX(ifc));
422 apply_mask(&p);
423 if (addr->family == AF_INET) {
424 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
425 return;
426
427 bgp_address_del(bgp, ifc, addr);
428
429 rn = bgp_node_lookup(bgp->connected_table[AFI_IP], &p);
430 } else if (addr->family == AF_INET6) {
431 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
432 return;
433
434 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
435 return;
436
437 bgp_address_del(bgp, ifc, addr);
438
439 rn = bgp_node_lookup(bgp->connected_table[AFI_IP6], &p);
440 }
441
442 if (!rn)
443 return;
444
445 bc = bgp_node_get_bgp_connected_ref_info(rn);
446 bc->refcnt--;
447 if (bc->refcnt == 0) {
448 XFREE(MTYPE_BGP_CONN, bc);
449 bgp_node_set_bgp_connected_ref_info(rn, NULL);
450 }
451 bgp_unlock_node(rn);
452 bgp_unlock_node(rn);
453 }
454
455 static void bgp_connected_cleanup(struct route_table *table,
456 struct route_node *rn)
457 {
458 struct bgp_connected_ref *bc;
459 struct bgp_node *bn = bgp_node_from_rnode(rn);
460
461 bc = bgp_node_get_bgp_connected_ref_info(bn);
462 if (!bc)
463 return;
464
465 bc->refcnt--;
466 if (bc->refcnt == 0) {
467 XFREE(MTYPE_BGP_CONN, bc);
468 bgp_node_set_bgp_connected_ref_info(bn, NULL);
469 }
470 }
471
472 bool bgp_nexthop_self(struct bgp *bgp, afi_t afi, uint8_t type,
473 uint8_t sub_type, struct attr *attr, struct bgp_node *rn)
474 {
475 uint8_t new_afi = afi == AFI_IP ? AF_INET : AF_INET6;
476 struct bgp_addr tmp_addr = {{0}}, *addr = NULL;
477 struct tip_addr tmp_tip, *tip = NULL;
478 const struct prefix *p = bgp_node_get_prefix(rn);
479 bool is_bgp_static_route =
480 ((type == ZEBRA_ROUTE_BGP) && (sub_type == BGP_ROUTE_STATIC))
481 ? true
482 : false;
483
484 if (!is_bgp_static_route)
485 new_afi = BGP_ATTR_NEXTHOP_AFI_IP6(attr) ? AF_INET6 : AF_INET;
486
487 tmp_addr.p.family = new_afi;
488 switch (new_afi) {
489 case AF_INET:
490 if (is_bgp_static_route) {
491 tmp_addr.p.u.prefix4 = p->u.prefix4;
492 tmp_addr.p.prefixlen = p->prefixlen;
493 } else {
494 /* Here we need to find out which nexthop to be used*/
495 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
496 tmp_addr.p.u.prefix4 = attr->nexthop;
497 tmp_addr.p.prefixlen = IPV4_MAX_BITLEN;
498 } else if ((attr->mp_nexthop_len)
499 && ((attr->mp_nexthop_len
500 == BGP_ATTR_NHLEN_IPV4)
501 || (attr->mp_nexthop_len
502 == BGP_ATTR_NHLEN_VPNV4))) {
503 tmp_addr.p.u.prefix4 =
504 attr->mp_nexthop_global_in;
505 tmp_addr.p.prefixlen = IPV4_MAX_BITLEN;
506 } else
507 return false;
508 }
509 break;
510 case AF_INET6:
511 if (is_bgp_static_route) {
512 tmp_addr.p.u.prefix6 = p->u.prefix6;
513 tmp_addr.p.prefixlen = p->prefixlen;
514 } else {
515 tmp_addr.p.u.prefix6 = attr->mp_nexthop_global;
516 tmp_addr.p.prefixlen = IPV6_MAX_BITLEN;
517 }
518 break;
519 default:
520 break;
521 }
522
523 addr = hash_lookup(bgp->address_hash, &tmp_addr);
524 if (addr)
525 return true;
526
527 if (new_afi == AF_INET) {
528 memset(&tmp_tip, 0, sizeof(struct tip_addr));
529 tmp_tip.addr = attr->nexthop;
530
531 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
532 tmp_tip.addr = attr->nexthop;
533 } else if ((attr->mp_nexthop_len) &&
534 ((attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4)
535 || (attr->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV4))) {
536 tmp_tip.addr = attr->mp_nexthop_global_in;
537 }
538
539 tip = hash_lookup(bgp->tip_hash, &tmp_tip);
540 if (tip)
541 return true;
542 }
543
544 return false;
545 }
546
547 bool bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer)
548 {
549 struct bgp_node *rn1;
550 struct bgp_node *rn2;
551 struct prefix p;
552 int ret;
553
554 p.family = AF_INET;
555 p.prefixlen = IPV4_MAX_BITLEN;
556 p.u.prefix4 = nexthop;
557
558 rn1 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
559 if (!rn1)
560 return false;
561
562 p.family = AF_INET;
563 p.prefixlen = IPV4_MAX_BITLEN;
564 p.u.prefix4 = peer->su.sin.sin_addr;
565
566 rn2 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
567 if (!rn2) {
568 bgp_unlock_node(rn1);
569 return false;
570 }
571
572 ret = (rn1 == rn2);
573
574 bgp_unlock_node(rn1);
575 bgp_unlock_node(rn2);
576
577 return ret;
578 }
579
580 bool bgp_multiaccess_check_v6(struct in6_addr nexthop, struct peer *peer)
581 {
582 struct bgp_node *rn1;
583 struct bgp_node *rn2;
584 struct prefix p;
585 int ret;
586
587 p.family = AF_INET6;
588 p.prefixlen = IPV6_MAX_BITLEN;
589 p.u.prefix6 = nexthop;
590
591 rn1 = bgp_node_match(peer->bgp->connected_table[AFI_IP6], &p);
592 if (!rn1)
593 return false;
594
595 p.family = AF_INET6;
596 p.prefixlen = IPV6_MAX_BITLEN;
597 p.u.prefix6 = peer->su.sin6.sin6_addr;
598
599 rn2 = bgp_node_match(peer->bgp->connected_table[AFI_IP6], &p);
600 if (!rn2) {
601 bgp_unlock_node(rn1);
602 return false;
603 }
604
605 ret = (rn1 == rn2);
606
607 bgp_unlock_node(rn1);
608 bgp_unlock_node(rn2);
609
610 return ret;
611 }
612
613 bool bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop,
614 struct update_subgroup *subgrp,
615 struct peer *exclude)
616 {
617 struct bgp_node *rn1 = NULL, *rn2 = NULL;
618 struct peer_af *paf = NULL;
619 struct prefix p = {0}, np = {0};
620 struct bgp *bgp = NULL;
621
622 np.family = AF_INET6;
623 np.prefixlen = IPV6_MAX_BITLEN;
624 np.u.prefix6 = nexthop;
625
626 p.family = AF_INET;
627 p.prefixlen = IPV6_MAX_BITLEN;
628
629 bgp = SUBGRP_INST(subgrp);
630 rn1 = bgp_node_match(bgp->connected_table[AFI_IP6], &np);
631 if (!rn1)
632 return false;
633
634 SUBGRP_FOREACH_PEER (subgrp, paf) {
635 /* Skip peer we're told to exclude - e.g., source of route. */
636 if (paf->peer == exclude)
637 continue;
638
639 p.u.prefix6 = paf->peer->su.sin6.sin6_addr;
640 rn2 = bgp_node_match(bgp->connected_table[AFI_IP6], &p);
641 if (rn1 == rn2) {
642 bgp_unlock_node(rn1);
643 bgp_unlock_node(rn2);
644 return true;
645 }
646
647 if (rn2)
648 bgp_unlock_node(rn2);
649 }
650
651 bgp_unlock_node(rn1);
652 return false;
653 }
654
655 bool bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
656 struct update_subgroup *subgrp,
657 struct peer *exclude)
658 {
659 struct bgp_node *rn1, *rn2;
660 struct peer_af *paf;
661 struct prefix p, np;
662 struct bgp *bgp;
663
664 np.family = AF_INET;
665 np.prefixlen = IPV4_MAX_BITLEN;
666 np.u.prefix4 = nexthop;
667
668 p.family = AF_INET;
669 p.prefixlen = IPV4_MAX_BITLEN;
670
671 bgp = SUBGRP_INST(subgrp);
672 rn1 = bgp_node_match(bgp->connected_table[AFI_IP], &np);
673 if (!rn1)
674 return false;
675
676 SUBGRP_FOREACH_PEER (subgrp, paf) {
677 /* Skip peer we're told to exclude - e.g., source of route. */
678 if (paf->peer == exclude)
679 continue;
680
681 p.u.prefix4 = paf->peer->su.sin.sin_addr;
682
683 rn2 = bgp_node_match(bgp->connected_table[AFI_IP], &p);
684 if (rn1 == rn2) {
685 bgp_unlock_node(rn1);
686 bgp_unlock_node(rn2);
687 return true;
688 }
689
690 if (rn2)
691 bgp_unlock_node(rn2);
692 }
693
694 bgp_unlock_node(rn1);
695 return false;
696 }
697
698 static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp,
699 struct bgp_nexthop_cache *bnc)
700 {
701 char buf[PREFIX2STR_BUFFER];
702 struct nexthop *nexthop;
703
704 for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next)
705 switch (nexthop->type) {
706 case NEXTHOP_TYPE_IPV6:
707 vty_out(vty, " gate %s\n",
708 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
709 sizeof(buf)));
710 break;
711 case NEXTHOP_TYPE_IPV6_IFINDEX:
712 vty_out(vty, " gate %s, if %s\n",
713 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
714 sizeof(buf)),
715 ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
716 break;
717 case NEXTHOP_TYPE_IPV4:
718 vty_out(vty, " gate %s\n",
719 inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
720 sizeof(buf)));
721 break;
722 case NEXTHOP_TYPE_IFINDEX:
723 vty_out(vty, " if %s\n",
724 ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
725 break;
726 case NEXTHOP_TYPE_IPV4_IFINDEX:
727 vty_out(vty, " gate %s, if %s\n",
728 inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
729 sizeof(buf)),
730 ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
731 break;
732 case NEXTHOP_TYPE_BLACKHOLE:
733 vty_out(vty, " blackhole\n");
734 break;
735 default:
736 vty_out(vty, " invalid nexthop type %u\n",
737 nexthop->type);
738 }
739 }
740
741 static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail,
742 bool import_table)
743 {
744 struct bgp_node *rn;
745 struct bgp_nexthop_cache *bnc;
746 char buf[PREFIX2STR_BUFFER];
747 time_t tbuf;
748 afi_t afi;
749 struct bgp_table **table;
750
751 if (import_table)
752 vty_out(vty, "Current BGP import check cache:\n");
753 else
754 vty_out(vty, "Current BGP nexthop cache:\n");
755 if (import_table)
756 table = bgp->import_check_table;
757 else
758 table = bgp->nexthop_cache_table;
759 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
760 if (!table || !table[afi])
761 continue;
762 for (rn = bgp_table_top(table[afi]); rn;
763 rn = bgp_route_next(rn)) {
764 struct peer *peer;
765 const struct prefix *p = bgp_node_get_prefix(rn);
766
767 bnc = bgp_node_get_bgp_nexthop_info(rn);
768 if (!bnc)
769 continue;
770 peer = (struct peer *)bnc->nht_info;
771
772 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) {
773 vty_out(vty,
774 " %s valid [IGP metric %d], #paths %d",
775 inet_ntop(p->family, &p->u.prefix, buf,
776 sizeof(buf)),
777 bnc->metric, bnc->path_count);
778 if (peer)
779 vty_out(vty, ", peer %s", peer->host);
780 vty_out(vty, "\n");
781
782 if (!detail)
783 continue;
784
785 bgp_show_nexthops_detail(vty, bgp, bnc);
786
787 } else {
788 vty_out(vty, " %s invalid",
789 inet_ntop(p->family, &p->u.prefix, buf,
790 sizeof(buf)));
791 if (peer)
792 vty_out(vty, ", peer %s", peer->host);
793 vty_out(vty, "\n");
794 if (CHECK_FLAG(bnc->flags,
795 BGP_NEXTHOP_CONNECTED))
796 vty_out(vty, " Must be Connected\n");
797 if (!CHECK_FLAG(bnc->flags,
798 BGP_NEXTHOP_REGISTERED))
799 vty_out(vty, " Is not Registered\n");
800 }
801 tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
802 vty_out(vty, " Last update: %s", ctime(&tbuf));
803 vty_out(vty, "\n");
804 }
805 }
806 }
807
808 static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name,
809 int detail, bool import_table)
810 {
811 struct bgp *bgp;
812
813 if (name)
814 bgp = bgp_lookup_by_name(name);
815 else
816 bgp = bgp_get_default();
817 if (!bgp) {
818 vty_out(vty, "%% No such BGP instance exist\n");
819 return CMD_WARNING;
820 }
821
822 bgp_show_nexthops(vty, bgp, detail, import_table);
823
824 return CMD_SUCCESS;
825 }
826
827 static void bgp_show_all_instances_nexthops_vty(struct vty *vty)
828 {
829 struct listnode *node, *nnode;
830 struct bgp *bgp;
831
832 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
833 vty_out(vty, "\nInstance %s:\n",
834 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
835 ? VRF_DEFAULT_NAME
836 : bgp->name);
837 bgp_show_nexthops(vty, bgp, 0, false);
838 }
839 }
840
841 DEFUN (show_ip_bgp_nexthop,
842 show_ip_bgp_nexthop_cmd,
843 "show [ip] bgp [<view|vrf> VIEWVRFNAME] nexthop [detail]",
844 SHOW_STR
845 IP_STR
846 BGP_STR
847 BGP_INSTANCE_HELP_STR
848 "BGP nexthop table\n"
849 "Show detailed information\n")
850 {
851 int idx = 0;
852 char *vrf = NULL;
853
854 if (argv_find(argv, argc, "view", &idx)
855 || argv_find(argv, argc, "vrf", &idx))
856 vrf = argv[++idx]->arg;
857 int detail = argv_find(argv, argc, "detail", &idx) ? 1 : 0;
858
859 return show_ip_bgp_nexthop_table(vty, vrf, detail, false);
860 }
861
862 DEFUN (show_ip_bgp_import_check,
863 show_ip_bgp_import_check_cmd,
864 "show [ip] bgp [<view|vrf> VIEWVRFNAME] import-check-table [detail]",
865 SHOW_STR
866 IP_STR
867 BGP_STR
868 BGP_INSTANCE_HELP_STR
869 "BGP import check table\n"
870 "Show detailed information\n")
871 {
872 int idx = 0;
873 char *vrf = NULL;
874
875 if (argv_find(argv, argc, "view", &idx)
876 || argv_find(argv, argc, "vrf", &idx))
877 vrf = argv[++idx]->arg;
878 int detail = argv_find(argv, argc, "detail", &idx) ? 1 : 0;
879 return show_ip_bgp_nexthop_table(vty, vrf, detail, true);
880 }
881
882 DEFUN (show_ip_bgp_instance_all_nexthop,
883 show_ip_bgp_instance_all_nexthop_cmd,
884 "show [ip] bgp <view|vrf> all nexthop",
885 SHOW_STR
886 IP_STR
887 BGP_STR
888 BGP_INSTANCE_ALL_HELP_STR
889 "BGP nexthop table\n")
890 {
891 bgp_show_all_instances_nexthops_vty(vty);
892 return CMD_SUCCESS;
893 }
894
895 void bgp_scan_init(struct bgp *bgp)
896 {
897 afi_t afi;
898
899 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
900 bgp->nexthop_cache_table[afi] =
901 bgp_table_init(bgp, afi, SAFI_UNICAST);
902 bgp->connected_table[afi] = bgp_table_init(bgp, afi,
903 SAFI_UNICAST);
904 bgp->import_check_table[afi] =
905 bgp_table_init(bgp, afi, SAFI_UNICAST);
906 }
907 }
908
909 void bgp_scan_vty_init(void)
910 {
911 install_element(VIEW_NODE, &show_ip_bgp_nexthop_cmd);
912 install_element(VIEW_NODE, &show_ip_bgp_import_check_cmd);
913 install_element(VIEW_NODE, &show_ip_bgp_instance_all_nexthop_cmd);
914 }
915
916 void bgp_scan_finish(struct bgp *bgp)
917 {
918 afi_t afi;
919
920 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
921 /* Only the current one needs to be reset. */
922 bgp_nexthop_cache_reset(bgp->nexthop_cache_table[afi]);
923 bgp_table_unlock(bgp->nexthop_cache_table[afi]);
924 bgp->nexthop_cache_table[afi] = NULL;
925
926 bgp->connected_table[afi]->route_table->cleanup =
927 bgp_connected_cleanup;
928 bgp_table_unlock(bgp->connected_table[afi]);
929 bgp->connected_table[afi] = NULL;
930
931 bgp_table_unlock(bgp->import_check_table[afi]);
932 bgp->import_check_table[afi] = NULL;
933 }
934 }