]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_nexthop.c
Merge pull request #4858 from donaldsharp/bgp_default
[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(&(bnc->node->p), 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 in_addr addr;
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
194 vty_out(vty, "addr: %s, count: %d : ", inet_ntoa(addr->addr),
195 addr->ifp_name_list->count);
196
197 for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
198 vty_out(vty, " %s,", name);
199 }
200
201 vty_out(vty, "\n");
202 }
203
204 void bgp_nexthop_show_address_hash(struct vty *vty, struct bgp *bgp)
205 {
206 hash_iterate(bgp->address_hash,
207 (void (*)(struct hash_bucket *, void *))show_address_entry,
208 vty);
209 }
210
211 static void bgp_address_hash_string_del(void *val)
212 {
213 char *data = val;
214
215 XFREE(MTYPE_MARTIAN_STRING, data);
216 }
217
218 static void *bgp_address_hash_alloc(void *p)
219 {
220 const struct in_addr *val = (const struct in_addr *)p;
221 struct bgp_addr *addr;
222
223 addr = XMALLOC(MTYPE_BGP_ADDR, sizeof(struct bgp_addr));
224 addr->addr.s_addr = val->s_addr;
225
226 addr->ifp_name_list = list_new();
227 addr->ifp_name_list->del = bgp_address_hash_string_del;
228
229 return addr;
230 }
231
232 static void bgp_address_hash_free(void *data)
233 {
234 struct bgp_addr *addr = data;
235
236 list_delete(&addr->ifp_name_list);
237 XFREE(MTYPE_BGP_ADDR, addr);
238 }
239
240 static unsigned int bgp_address_hash_key_make(const void *p)
241 {
242 const struct bgp_addr *addr = p;
243
244 return jhash_1word(addr->addr.s_addr, 0);
245 }
246
247 static bool bgp_address_hash_cmp(const void *p1, const void *p2)
248 {
249 const struct bgp_addr *addr1 = p1;
250 const struct bgp_addr *addr2 = p2;
251
252 return addr1->addr.s_addr == addr2->addr.s_addr;
253 }
254
255 void bgp_address_init(struct bgp *bgp)
256 {
257 bgp->address_hash =
258 hash_create(bgp_address_hash_key_make, bgp_address_hash_cmp,
259 "BGP Address Hash");
260 }
261
262 void bgp_address_destroy(struct bgp *bgp)
263 {
264 if (bgp->address_hash == NULL)
265 return;
266 hash_clean(bgp->address_hash, bgp_address_hash_free);
267 hash_free(bgp->address_hash);
268 bgp->address_hash = NULL;
269 }
270
271 static void bgp_address_add(struct bgp *bgp, struct connected *ifc,
272 struct prefix *p)
273 {
274 struct bgp_addr tmp;
275 struct bgp_addr *addr;
276 struct listnode *node;
277 char *name;
278
279 tmp.addr = p->u.prefix4;
280
281 addr = hash_get(bgp->address_hash, &tmp, bgp_address_hash_alloc);
282
283 for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
284 if (strcmp(ifc->ifp->name, name) == 0)
285 break;
286 }
287 if (!node) {
288 name = XSTRDUP(MTYPE_MARTIAN_STRING, ifc->ifp->name);
289 listnode_add(addr->ifp_name_list, name);
290 }
291 }
292
293 static void bgp_address_del(struct bgp *bgp, struct connected *ifc,
294 struct prefix *p)
295 {
296 struct bgp_addr tmp;
297 struct bgp_addr *addr;
298 struct listnode *node;
299 char *name;
300
301 tmp.addr = p->u.prefix4;
302
303 addr = hash_lookup(bgp->address_hash, &tmp);
304 /* may have been deleted earlier by bgp_interface_down() */
305 if (addr == NULL)
306 return;
307
308 for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
309 if (strcmp(ifc->ifp->name, name) == 0)
310 break;
311 }
312
313 if (node) {
314 list_delete_node(addr->ifp_name_list, node);
315 XFREE(MTYPE_MARTIAN_STRING, name);
316 }
317
318 if (addr->ifp_name_list->count == 0) {
319 hash_release(bgp->address_hash, addr);
320 list_delete(&addr->ifp_name_list);
321 XFREE(MTYPE_BGP_ADDR, addr);
322 }
323 }
324
325
326 struct bgp_connected_ref {
327 unsigned int refcnt;
328 };
329
330 void bgp_connected_add(struct bgp *bgp, struct connected *ifc)
331 {
332 struct prefix p;
333 struct prefix *addr;
334 struct bgp_node *rn;
335 struct bgp_connected_ref *bc;
336 struct listnode *node, *nnode;
337 struct peer *peer;
338
339 addr = ifc->address;
340
341 p = *(CONNECTED_PREFIX(ifc));
342 if (addr->family == AF_INET) {
343 apply_mask_ipv4((struct prefix_ipv4 *)&p);
344
345 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
346 return;
347
348 bgp_address_add(bgp, ifc, addr);
349
350 rn = bgp_node_get(bgp->connected_table[AFI_IP],
351 (struct prefix *)&p);
352 bc = bgp_node_get_bgp_connected_ref_info(rn);
353 if (bc)
354 bc->refcnt++;
355 else {
356 bc = XCALLOC(MTYPE_BGP_CONN,
357 sizeof(struct bgp_connected_ref));
358 bc->refcnt = 1;
359 bgp_node_set_bgp_connected_ref_info(rn, bc);
360 }
361
362 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
363 if (peer->conf_if
364 && (strcmp(peer->conf_if, ifc->ifp->name) == 0)
365 && peer->status != Established
366 && !CHECK_FLAG(peer->flags,
367 PEER_FLAG_IFPEER_V6ONLY)) {
368 if (peer_active(peer))
369 BGP_EVENT_ADD(peer, BGP_Stop);
370 BGP_EVENT_ADD(peer, BGP_Start);
371 }
372 }
373 } else if (addr->family == AF_INET6) {
374 apply_mask_ipv6((struct prefix_ipv6 *)&p);
375
376 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
377 return;
378
379 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
380 return;
381
382 rn = bgp_node_get(bgp->connected_table[AFI_IP6],
383 (struct prefix *)&p);
384
385 bc = bgp_node_get_bgp_connected_ref_info(rn);
386 if (bc)
387 bc->refcnt++;
388 else {
389 bc = XCALLOC(MTYPE_BGP_CONN,
390 sizeof(struct bgp_connected_ref));
391 bc->refcnt = 1;
392 bgp_node_set_bgp_connected_ref_info(rn, bc);
393 }
394 }
395 }
396
397 void bgp_connected_delete(struct bgp *bgp, struct connected *ifc)
398 {
399 struct prefix p;
400 struct prefix *addr;
401 struct bgp_node *rn = NULL;
402 struct bgp_connected_ref *bc;
403
404 addr = ifc->address;
405
406 p = *(CONNECTED_PREFIX(ifc));
407 apply_mask(&p);
408 if (addr->family == AF_INET) {
409 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
410 return;
411
412 bgp_address_del(bgp, ifc, addr);
413
414 rn = bgp_node_lookup(bgp->connected_table[AFI_IP], &p);
415 } else if (addr->family == AF_INET6) {
416 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
417 return;
418
419 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
420 return;
421
422 rn = bgp_node_lookup(bgp->connected_table[AFI_IP6],
423 (struct prefix *)&p);
424 }
425
426 if (!rn)
427 return;
428
429 bc = bgp_node_get_bgp_connected_ref_info(rn);
430 bc->refcnt--;
431 if (bc->refcnt == 0) {
432 XFREE(MTYPE_BGP_CONN, bc);
433 bgp_node_set_bgp_connected_ref_info(rn, NULL);
434 }
435 bgp_unlock_node(rn);
436 bgp_unlock_node(rn);
437 }
438
439 static void bgp_connected_cleanup(struct route_table *table,
440 struct route_node *rn)
441 {
442 struct bgp_connected_ref *bc;
443 struct bgp_node *bn = bgp_node_from_rnode(rn);
444
445 bc = bgp_node_get_bgp_connected_ref_info(bn);
446 if (!bc)
447 return;
448
449 bc->refcnt--;
450 if (bc->refcnt == 0) {
451 XFREE(MTYPE_BGP_CONN, bc);
452 bgp_node_set_bgp_connected_ref_info(bn, NULL);
453 }
454 }
455
456 int bgp_nexthop_self(struct bgp *bgp, struct in_addr nh_addr)
457 {
458 struct bgp_addr tmp, *addr;
459 struct tip_addr tmp_tip, *tip;
460
461 tmp.addr = nh_addr;
462
463 addr = hash_lookup(bgp->address_hash, &tmp);
464 if (addr)
465 return 1;
466
467 tmp_tip.addr = nh_addr;
468 tip = hash_lookup(bgp->tip_hash, &tmp_tip);
469 if (tip)
470 return 1;
471
472 return 0;
473 }
474
475 int bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer)
476 {
477 struct bgp_node *rn1;
478 struct bgp_node *rn2;
479 struct prefix p;
480 int ret;
481
482 p.family = AF_INET;
483 p.prefixlen = IPV4_MAX_BITLEN;
484 p.u.prefix4 = nexthop;
485
486 rn1 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
487 if (!rn1)
488 return 0;
489
490 p.family = AF_INET;
491 p.prefixlen = IPV4_MAX_BITLEN;
492 p.u.prefix4 = peer->su.sin.sin_addr;
493
494 rn2 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
495 if (!rn2) {
496 bgp_unlock_node(rn1);
497 return 0;
498 }
499
500 ret = (rn1 == rn2) ? 1 : 0;
501
502 bgp_unlock_node(rn1);
503 bgp_unlock_node(rn2);
504
505 return (ret);
506 }
507
508 int bgp_multiaccess_check_v6(struct in6_addr nexthop, struct peer *peer)
509 {
510 struct bgp_node *rn1;
511 struct bgp_node *rn2;
512 struct prefix p;
513 int ret;
514
515 p.family = AF_INET6;
516 p.prefixlen = IPV6_MAX_BITLEN;
517 p.u.prefix6 = nexthop;
518
519 rn1 = bgp_node_match(peer->bgp->connected_table[AFI_IP6], &p);
520 if (!rn1)
521 return 0;
522
523 p.family = AF_INET6;
524 p.prefixlen = IPV6_MAX_BITLEN;
525 p.u.prefix6 = peer->su.sin6.sin6_addr;
526
527 rn2 = bgp_node_match(peer->bgp->connected_table[AFI_IP6], &p);
528 if (!rn2) {
529 bgp_unlock_node(rn1);
530 return 0;
531 }
532
533 ret = (rn1 == rn2) ? 1 : 0;
534
535 bgp_unlock_node(rn1);
536 bgp_unlock_node(rn2);
537
538 return ret;
539 }
540
541 int bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop,
542 struct update_subgroup *subgrp)
543 {
544 struct bgp_node *rn1 = NULL, *rn2 = NULL;
545 struct peer_af *paf = NULL;
546 struct prefix p = {0}, np = {0};
547 struct bgp *bgp = NULL;
548
549 np.family = AF_INET6;
550 np.prefixlen = IPV6_MAX_BITLEN;
551 np.u.prefix6 = nexthop;
552
553 p.family = AF_INET;
554 p.prefixlen = IPV6_MAX_BITLEN;
555
556 bgp = SUBGRP_INST(subgrp);
557 rn1 = bgp_node_match(bgp->connected_table[AFI_IP6], &np);
558 if (!rn1)
559 return 0;
560
561 SUBGRP_FOREACH_PEER (subgrp, paf) {
562
563 p.u.prefix6 = paf->peer->su.sin6.sin6_addr;
564 rn2 = bgp_node_match(bgp->connected_table[AFI_IP6], &p);
565 if (rn1 == rn2) {
566 bgp_unlock_node(rn1);
567 bgp_unlock_node(rn2);
568 return 1;
569 }
570
571 if (rn2)
572 bgp_unlock_node(rn2);
573 }
574
575 bgp_unlock_node(rn1);
576 return 0;
577 }
578
579 int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
580 struct update_subgroup *subgrp)
581 {
582 struct bgp_node *rn1, *rn2;
583 struct peer_af *paf;
584 struct prefix p, np;
585 struct bgp *bgp;
586
587 np.family = AF_INET;
588 np.prefixlen = IPV4_MAX_BITLEN;
589 np.u.prefix4 = nexthop;
590
591 p.family = AF_INET;
592 p.prefixlen = IPV4_MAX_BITLEN;
593
594 bgp = SUBGRP_INST(subgrp);
595 rn1 = bgp_node_match(bgp->connected_table[AFI_IP], &np);
596 if (!rn1)
597 return 0;
598
599 SUBGRP_FOREACH_PEER (subgrp, paf) {
600 p.u.prefix4 = paf->peer->su.sin.sin_addr;
601
602 rn2 = bgp_node_match(bgp->connected_table[AFI_IP], &p);
603 if (rn1 == rn2) {
604 bgp_unlock_node(rn1);
605 bgp_unlock_node(rn2);
606 return 1;
607 }
608
609 if (rn2)
610 bgp_unlock_node(rn2);
611 }
612
613 bgp_unlock_node(rn1);
614 return 0;
615 }
616
617 static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp,
618 struct bgp_nexthop_cache *bnc)
619 {
620 char buf[PREFIX2STR_BUFFER];
621 struct nexthop *nexthop;
622
623 for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next)
624 switch (nexthop->type) {
625 case NEXTHOP_TYPE_IPV6:
626 vty_out(vty, " gate %s\n",
627 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
628 sizeof(buf)));
629 break;
630 case NEXTHOP_TYPE_IPV6_IFINDEX:
631 vty_out(vty, " gate %s, if %s\n",
632 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
633 sizeof(buf)),
634 ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
635 break;
636 case NEXTHOP_TYPE_IPV4:
637 vty_out(vty, " gate %s\n",
638 inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
639 sizeof(buf)));
640 break;
641 case NEXTHOP_TYPE_IFINDEX:
642 vty_out(vty, " if %s\n",
643 ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
644 break;
645 case NEXTHOP_TYPE_IPV4_IFINDEX:
646 vty_out(vty, " gate %s, if %s\n",
647 inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
648 sizeof(buf)),
649 ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
650 break;
651 case NEXTHOP_TYPE_BLACKHOLE:
652 vty_out(vty, " blackhole\n");
653 break;
654 default:
655 vty_out(vty, " invalid nexthop type %u\n",
656 nexthop->type);
657 }
658 }
659
660 static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail,
661 bool import_table)
662 {
663 struct bgp_node *rn;
664 struct bgp_nexthop_cache *bnc;
665 char buf[PREFIX2STR_BUFFER];
666 time_t tbuf;
667 afi_t afi;
668 struct bgp_table **table;
669
670 if (import_table)
671 vty_out(vty, "Current BGP import check cache:\n");
672 else
673 vty_out(vty, "Current BGP nexthop cache:\n");
674 if (import_table)
675 table = bgp->import_check_table;
676 else
677 table = bgp->nexthop_cache_table;
678 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
679 if (!table || !table[afi])
680 continue;
681 for (rn = bgp_table_top(table[afi]); rn;
682 rn = bgp_route_next(rn)) {
683 struct peer *peer;
684
685 bnc = bgp_node_get_bgp_nexthop_info(rn);
686 if (!bnc)
687 continue;
688 peer = (struct peer *)bnc->nht_info;
689
690 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) {
691 vty_out(vty,
692 " %s valid [IGP metric %d], #paths %d",
693 inet_ntop(rn->p.family,
694 &rn->p.u.prefix, buf,
695 sizeof(buf)),
696 bnc->metric, bnc->path_count);
697 if (peer)
698 vty_out(vty, ", peer %s", peer->host);
699 vty_out(vty, "\n");
700
701 if (!detail)
702 continue;
703
704 bgp_show_nexthops_detail(vty, bgp, bnc);
705
706 } else {
707 vty_out(vty, " %s invalid",
708 inet_ntop(rn->p.family,
709 &rn->p.u.prefix, buf,
710 sizeof(buf)));
711 if (peer)
712 vty_out(vty, ", peer %s", peer->host);
713 vty_out(vty, "\n");
714 if (CHECK_FLAG(bnc->flags,
715 BGP_NEXTHOP_CONNECTED))
716 vty_out(vty, " Must be Connected\n");
717 if (!CHECK_FLAG(bnc->flags,
718 BGP_NEXTHOP_REGISTERED))
719 vty_out(vty, " Is not Registered\n");
720 }
721 tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
722 vty_out(vty, " Last update: %s", ctime(&tbuf));
723 vty_out(vty, "\n");
724 }
725 }
726 }
727
728 static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name,
729 int detail, bool import_table)
730 {
731 struct bgp *bgp;
732
733 if (name)
734 bgp = bgp_lookup_by_name(name);
735 else
736 bgp = bgp_get_default();
737 if (!bgp) {
738 vty_out(vty, "%% No such BGP instance exist\n");
739 return CMD_WARNING;
740 }
741
742 bgp_show_nexthops(vty, bgp, detail, import_table);
743
744 return CMD_SUCCESS;
745 }
746
747 static void bgp_show_all_instances_nexthops_vty(struct vty *vty)
748 {
749 struct listnode *node, *nnode;
750 struct bgp *bgp;
751
752 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
753 vty_out(vty, "\nInstance %s:\n",
754 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
755 ? VRF_DEFAULT_NAME
756 : bgp->name);
757 bgp_show_nexthops(vty, bgp, 0, false);
758 }
759 }
760
761 DEFUN (show_ip_bgp_nexthop,
762 show_ip_bgp_nexthop_cmd,
763 "show [ip] bgp [<view|vrf> VIEWVRFNAME] nexthop [detail]",
764 SHOW_STR
765 IP_STR
766 BGP_STR
767 BGP_INSTANCE_HELP_STR
768 "BGP nexthop table\n"
769 "Show detailed information\n")
770 {
771 int idx = 0;
772 char *vrf = NULL;
773
774 if (argv_find(argv, argc, "view", &idx)
775 || argv_find(argv, argc, "vrf", &idx))
776 vrf = argv[++idx]->arg;
777 int detail = argv_find(argv, argc, "detail", &idx) ? 1 : 0;
778
779 return show_ip_bgp_nexthop_table(vty, vrf, detail, false);
780 }
781
782 DEFUN (show_ip_bgp_import_check,
783 show_ip_bgp_import_check_cmd,
784 "show [ip] bgp [<view|vrf> VIEWVRFNAME] import-check-table [detail]",
785 SHOW_STR
786 IP_STR
787 BGP_STR
788 BGP_INSTANCE_HELP_STR
789 "BGP import check table\n"
790 "Show detailed information\n")
791 {
792 int idx = 0;
793 char *vrf = NULL;
794
795 if (argv_find(argv, argc, "view", &idx)
796 || argv_find(argv, argc, "vrf", &idx))
797 vrf = argv[++idx]->arg;
798 int detail = argv_find(argv, argc, "detail", &idx) ? 1 : 0;
799 return show_ip_bgp_nexthop_table(vty, vrf, detail, true);
800 }
801
802 DEFUN (show_ip_bgp_instance_all_nexthop,
803 show_ip_bgp_instance_all_nexthop_cmd,
804 "show [ip] bgp <view|vrf> all nexthop",
805 SHOW_STR
806 IP_STR
807 BGP_STR
808 BGP_INSTANCE_ALL_HELP_STR
809 "BGP nexthop table\n")
810 {
811 bgp_show_all_instances_nexthops_vty(vty);
812 return CMD_SUCCESS;
813 }
814
815 void bgp_scan_init(struct bgp *bgp)
816 {
817 afi_t afi;
818
819 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
820 bgp->nexthop_cache_table[afi] =
821 bgp_table_init(bgp, afi, SAFI_UNICAST);
822 bgp->connected_table[afi] = bgp_table_init(bgp, afi,
823 SAFI_UNICAST);
824 bgp->import_check_table[afi] =
825 bgp_table_init(bgp, afi, SAFI_UNICAST);
826 }
827 }
828
829 void bgp_scan_vty_init(void)
830 {
831 install_element(VIEW_NODE, &show_ip_bgp_nexthop_cmd);
832 install_element(VIEW_NODE, &show_ip_bgp_import_check_cmd);
833 install_element(VIEW_NODE, &show_ip_bgp_instance_all_nexthop_cmd);
834 }
835
836 void bgp_scan_finish(struct bgp *bgp)
837 {
838 afi_t afi;
839
840 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
841 /* Only the current one needs to be reset. */
842 bgp_nexthop_cache_reset(bgp->nexthop_cache_table[afi]);
843 bgp_table_unlock(bgp->nexthop_cache_table[afi]);
844 bgp->nexthop_cache_table[afi] = NULL;
845
846 bgp->connected_table[afi]->route_table->cleanup =
847 bgp_connected_cleanup;
848 bgp_table_unlock(bgp->connected_table[afi]);
849 bgp->connected_table[afi] = NULL;
850
851 bgp_table_unlock(bgp->import_check_table[afi]);
852 bgp->import_check_table[afi] = NULL;
853 }
854 }