]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_nexthop.c
Merge pull request #3179 from donaldsharp/vni_cmp
[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"
26#include "zclient.h"
27#include "stream.h"
28#include "network.h"
29#include "log.h"
30#include "memory.h"
10f9bf3f
JBD
31#include "hash.h"
32#include "jhash.h"
fb018d25 33#include "nexthop.h"
3f9c7369 34#include "queue.h"
039f3a34 35#include "filter.h"
718e3744 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"
fb018d25 42#include "bgpd/bgp_nht.h"
718e3744 43#include "bgpd/bgp_debug.h"
44#include "bgpd/bgp_damp.h"
8ffedcea 45#include "bgpd/bgp_fsm.h"
8386ac43 46#include "bgpd/bgp_vty.h"
718e3744 47#include "zebra/rib.h"
d62a17ae 48#include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
718e3744 49
330cec3d
DS
50DEFINE_MTYPE_STATIC(BGPD, MARTIAN_STRING, "BGP Martian Address Intf String");
51
d62a17ae 52char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size)
fb018d25 53{
d62a17ae 54 prefix2str(&(bnc->node->p), buf, size);
55 return buf;
fb018d25
DS
56}
57
d62a17ae 58void bnc_nexthop_free(struct bgp_nexthop_cache *bnc)
718e3744 59{
d62a17ae 60 nexthops_free(bnc->nexthop);
718e3744 61}
62
d62a17ae 63struct bgp_nexthop_cache *bnc_new(void)
718e3744 64{
d62a17ae 65 struct bgp_nexthop_cache *bnc;
fb018d25 66
d62a17ae 67 bnc = XCALLOC(MTYPE_BGP_NEXTHOP_CACHE,
68 sizeof(struct bgp_nexthop_cache));
69 LIST_INIT(&(bnc->paths));
70 return bnc;
718e3744 71}
72
d62a17ae 73void bnc_free(struct bgp_nexthop_cache *bnc)
718e3744 74{
d62a17ae 75 bnc_nexthop_free(bnc);
76 XFREE(MTYPE_BGP_NEXTHOP_CACHE, bnc);
718e3744 77}
6b0655a2 78
718e3744 79/* Reset and free all BGP nexthop cache. */
d62a17ae 80static void bgp_nexthop_cache_reset(struct bgp_table *table)
718e3744 81{
d62a17ae 82 struct bgp_node *rn;
83 struct bgp_nexthop_cache *bnc;
84
14315f2d
DS
85 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
86 bnc = bgp_nexthop_get_node_info(rn);
87 if (bnc != NULL) {
d62a17ae 88 bnc_free(bnc);
14315f2d 89 bgp_nexthop_set_node_info(rn, NULL);
d62a17ae 90 bgp_unlock_node(rn);
91 }
14315f2d 92 }
718e3744 93}
94
db0e1937
MK
95static void *bgp_tip_hash_alloc(void *p)
96{
0291c246
MK
97 const struct in_addr *val = (const struct in_addr *)p;
98 struct tip_addr *addr;
db0e1937
MK
99
100 addr = XMALLOC(MTYPE_TIP_ADDR, sizeof(struct tip_addr));
101 addr->refcnt = 0;
102 addr->addr.s_addr = val->s_addr;
103
104 return addr;
105}
106
107static void bgp_tip_hash_free(void *addr)
108{
109 XFREE(MTYPE_TIP_ADDR, addr);
110}
111
112static unsigned int bgp_tip_hash_key_make(void *p)
113{
0291c246 114 const struct tip_addr *addr = p;
db0e1937
MK
115
116 return jhash_1word(addr->addr.s_addr, 0);
117}
118
119static int bgp_tip_hash_cmp(const void *p1, const void *p2)
120{
0291c246
MK
121 const struct tip_addr *addr1 = p1;
122 const struct tip_addr *addr2 = p2;
db0e1937
MK
123
124 return addr1->addr.s_addr == addr2->addr.s_addr;
125}
126
127void bgp_tip_hash_init(struct bgp *bgp)
128{
996c9314 129 bgp->tip_hash = hash_create(bgp_tip_hash_key_make, bgp_tip_hash_cmp,
3f65c5b1 130 "BGP TIP hash");
db0e1937
MK
131}
132
133void bgp_tip_hash_destroy(struct bgp *bgp)
134{
135 if (bgp->tip_hash == NULL)
136 return;
137 hash_clean(bgp->tip_hash, bgp_tip_hash_free);
138 hash_free(bgp->tip_hash);
139 bgp->tip_hash = NULL;
140}
141
142void bgp_tip_add(struct bgp *bgp, struct in_addr *tip)
143{
0291c246
MK
144 struct tip_addr tmp;
145 struct tip_addr *addr;
db0e1937
MK
146
147 tmp.addr = *tip;
148
149 addr = hash_get(bgp->tip_hash, &tmp, bgp_tip_hash_alloc);
150 if (!addr)
151 return;
152
153 addr->refcnt++;
154}
155
156void bgp_tip_del(struct bgp *bgp, struct in_addr *tip)
157{
0291c246
MK
158 struct tip_addr tmp;
159 struct tip_addr *addr;
db0e1937
MK
160
161 tmp.addr = *tip;
162
163 addr = hash_lookup(bgp->tip_hash, &tmp);
164 /* may have been deleted earlier by bgp_interface_down() */
165 if (addr == NULL)
166 return;
167
168 addr->refcnt--;
169
170 if (addr->refcnt == 0) {
171 hash_release(bgp->tip_hash, addr);
172 XFREE(MTYPE_TIP_ADDR, addr);
173 }
174}
10f9bf3f 175
af97a18b
DS
176/* BGP own address structure */
177struct bgp_addr {
178 struct in_addr addr;
f4c2fb93 179 struct list *ifp_name_list;
af97a18b
DS
180};
181
182static void show_address_entry(struct hash_backet *backet, void *args)
183{
184 struct vty *vty = (struct vty *)args;
185 struct bgp_addr *addr = (struct bgp_addr *)backet->data;
f4c2fb93
DS
186 char *name;
187 struct listnode *node;
af97a18b 188
f4c2fb93
DS
189 vty_out(vty, "addr: %s, count: %d : ", inet_ntoa(addr->addr),
190 addr->ifp_name_list->count);
191
192 for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
193 vty_out(vty, " %s,", name);
194 }
195
196 vty_out(vty, "\n");
af97a18b
DS
197}
198
199void bgp_nexthop_show_address_hash(struct vty *vty, struct bgp *bgp)
200{
201 hash_iterate(bgp->address_hash,
202 (void (*)(struct hash_backet *, void *))show_address_entry,
203 vty);
204}
205
f4c2fb93
DS
206static void bgp_address_hash_string_del(void *val)
207{
208 char *data = val;
209
330cec3d 210 XFREE(MTYPE_MARTIAN_STRING, data);
f4c2fb93
DS
211}
212
d62a17ae 213static void *bgp_address_hash_alloc(void *p)
10f9bf3f 214{
d62a17ae 215 const struct in_addr *val = (const struct in_addr *)p;
216 struct bgp_addr *addr;
10f9bf3f 217
d62a17ae 218 addr = XMALLOC(MTYPE_BGP_ADDR, sizeof(struct bgp_addr));
d62a17ae 219 addr->addr.s_addr = val->s_addr;
10f9bf3f 220
f4c2fb93
DS
221 addr->ifp_name_list = list_new();
222 addr->ifp_name_list->del = bgp_address_hash_string_del;
223
d62a17ae 224 return addr;
10f9bf3f
JBD
225}
226
f4c2fb93 227static void bgp_address_hash_free(void *data)
37d361e7 228{
f4c2fb93
DS
229 struct bgp_addr *addr = data;
230
6a154c88 231 list_delete(&addr->ifp_name_list);
d62a17ae 232 XFREE(MTYPE_BGP_ADDR, addr);
37d361e7
RW
233}
234
d62a17ae 235static unsigned int bgp_address_hash_key_make(void *p)
10f9bf3f 236{
d62a17ae 237 const struct bgp_addr *addr = p;
10f9bf3f 238
d62a17ae 239 return jhash_1word(addr->addr.s_addr, 0);
10f9bf3f
JBD
240}
241
d62a17ae 242static int bgp_address_hash_cmp(const void *p1, const void *p2)
10f9bf3f 243{
d62a17ae 244 const struct bgp_addr *addr1 = p1;
245 const struct bgp_addr *addr2 = p2;
10f9bf3f 246
d62a17ae 247 return addr1->addr.s_addr == addr2->addr.s_addr;
10f9bf3f
JBD
248}
249
d62a17ae 250void bgp_address_init(struct bgp *bgp)
10f9bf3f 251{
996c9314
LB
252 bgp->address_hash =
253 hash_create(bgp_address_hash_key_make, bgp_address_hash_cmp,
254 "BGP Address Hash");
10f9bf3f
JBD
255}
256
d62a17ae 257void bgp_address_destroy(struct bgp *bgp)
bb86c601 258{
d62a17ae 259 if (bgp->address_hash == NULL)
260 return;
261 hash_clean(bgp->address_hash, bgp_address_hash_free);
262 hash_free(bgp->address_hash);
263 bgp->address_hash = NULL;
bb86c601
LB
264}
265
f4c2fb93
DS
266static void bgp_address_add(struct bgp *bgp, struct connected *ifc,
267 struct prefix *p)
10f9bf3f 268{
d62a17ae 269 struct bgp_addr tmp;
270 struct bgp_addr *addr;
f4c2fb93
DS
271 struct listnode *node;
272 char *name;
10f9bf3f 273
d62a17ae 274 tmp.addr = p->u.prefix4;
10f9bf3f 275
d62a17ae 276 addr = hash_get(bgp->address_hash, &tmp, bgp_address_hash_alloc);
5ce10e92 277
f4c2fb93
DS
278 for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
279 if (strcmp(ifc->ifp->name, name) == 0)
280 break;
281 }
282 if (!node) {
330cec3d 283 name = XSTRDUP(MTYPE_MARTIAN_STRING, ifc->ifp->name);
f4c2fb93
DS
284 listnode_add(addr->ifp_name_list, name);
285 }
10f9bf3f
JBD
286}
287
f4c2fb93
DS
288static void bgp_address_del(struct bgp *bgp, struct connected *ifc,
289 struct prefix *p)
10f9bf3f 290{
d62a17ae 291 struct bgp_addr tmp;
292 struct bgp_addr *addr;
f4c2fb93
DS
293 struct listnode *node;
294 char *name;
10f9bf3f 295
d62a17ae 296 tmp.addr = p->u.prefix4;
10f9bf3f 297
d62a17ae 298 addr = hash_lookup(bgp->address_hash, &tmp);
299 /* may have been deleted earlier by bgp_interface_down() */
300 if (addr == NULL)
301 return;
9e47abd8 302
f4c2fb93
DS
303 for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
304 if (strcmp(ifc->ifp->name, name) == 0)
305 break;
306 }
10f9bf3f 307
b9129915 308 if (node) {
f4c2fb93 309 list_delete_node(addr->ifp_name_list, node);
b9129915
DS
310 XFREE(MTYPE_MARTIAN_STRING, name);
311 }
f4c2fb93
DS
312
313 if (addr->ifp_name_list->count == 0) {
d62a17ae 314 hash_release(bgp->address_hash, addr);
6a154c88 315 list_delete(&addr->ifp_name_list);
d62a17ae 316 XFREE(MTYPE_BGP_ADDR, addr);
317 }
10f9bf3f
JBD
318}
319
6b0655a2 320
d62a17ae 321struct bgp_connected_ref {
322 unsigned int refcnt;
718e3744 323};
324
d62a17ae 325void bgp_connected_add(struct bgp *bgp, struct connected *ifc)
718e3744 326{
d62a17ae 327 struct prefix p;
328 struct prefix *addr;
329 struct bgp_node *rn;
330 struct bgp_connected_ref *bc;
331 struct listnode *node, *nnode;
332 struct peer *peer;
333
334 addr = ifc->address;
335
336 p = *(CONNECTED_PREFIX(ifc));
337 if (addr->family == AF_INET) {
338 apply_mask_ipv4((struct prefix_ipv4 *)&p);
339
340 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
341 return;
342
f4c2fb93 343 bgp_address_add(bgp, ifc, addr);
d62a17ae 344
345 rn = bgp_node_get(bgp->connected_table[AFI_IP],
346 (struct prefix *)&p);
3d9dbdbe
DS
347 bc = bgp_connected_get_node_info(rn);
348 if (bc)
d62a17ae 349 bc->refcnt++;
3d9dbdbe 350 else {
d62a17ae 351 bc = XCALLOC(MTYPE_BGP_CONN,
352 sizeof(struct bgp_connected_ref));
353 bc->refcnt = 1;
3d9dbdbe 354 bgp_connected_set_node_info(rn, bc);
d62a17ae 355 }
8ffedcea 356
d62a17ae 357 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
358 if (peer->conf_if
359 && (strcmp(peer->conf_if, ifc->ifp->name) == 0)
360 && peer->status != Established
361 && !CHECK_FLAG(peer->flags,
362 PEER_FLAG_IFPEER_V6ONLY)) {
363 if (peer_active(peer))
364 BGP_EVENT_ADD(peer, BGP_Stop);
365 BGP_EVENT_ADD(peer, BGP_Start);
366 }
367 }
368 } else if (addr->family == AF_INET6) {
369 apply_mask_ipv6((struct prefix_ipv6 *)&p);
370
371 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
372 return;
373
374 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
375 return;
376
377 rn = bgp_node_get(bgp->connected_table[AFI_IP6],
378 (struct prefix *)&p);
3d9dbdbe
DS
379
380 bc = bgp_connected_get_node_info(rn);
381 if (bc)
d62a17ae 382 bc->refcnt++;
3d9dbdbe 383 else {
d62a17ae 384 bc = XCALLOC(MTYPE_BGP_CONN,
385 sizeof(struct bgp_connected_ref));
386 bc->refcnt = 1;
3d9dbdbe 387 bgp_connected_set_node_info(rn, bc);
d62a17ae 388 }
718e3744 389 }
718e3744 390}
391
d62a17ae 392void bgp_connected_delete(struct bgp *bgp, struct connected *ifc)
718e3744 393{
d62a17ae 394 struct prefix p;
395 struct prefix *addr;
f6bdc080 396 struct bgp_node *rn = NULL;
d62a17ae 397 struct bgp_connected_ref *bc;
718e3744 398
d62a17ae 399 addr = ifc->address;
718e3744 400
d62a17ae 401 p = *(CONNECTED_PREFIX(ifc));
f6bdc080 402 apply_mask(&p);
d62a17ae 403 if (addr->family == AF_INET) {
d62a17ae 404 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
405 return;
718e3744 406
f4c2fb93 407 bgp_address_del(bgp, ifc, addr);
10f9bf3f 408
d62a17ae 409 rn = bgp_node_lookup(bgp->connected_table[AFI_IP], &p);
d62a17ae 410 } else if (addr->family == AF_INET6) {
d62a17ae 411 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
412 return;
413
414 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
415 return;
416
417 rn = bgp_node_lookup(bgp->connected_table[AFI_IP6],
418 (struct prefix *)&p);
f6bdc080 419 }
d62a17ae 420
f6bdc080
DS
421 if (!rn)
422 return;
423
3d9dbdbe 424 bc = bgp_connected_get_node_info(rn);
f6bdc080
DS
425 bc->refcnt--;
426 if (bc->refcnt == 0) {
427 XFREE(MTYPE_BGP_CONN, bc);
3d9dbdbe 428 bgp_connected_set_node_info(rn, NULL);
718e3744 429 }
f6bdc080
DS
430 bgp_unlock_node(rn);
431 bgp_unlock_node(rn);
718e3744 432}
433
3292693b
DS
434static void bgp_connected_cleanup(struct route_table *table,
435 struct route_node *rn)
436{
437 struct bgp_connected_ref *bc;
3d9dbdbe 438 struct bgp_node *bn = bgp_node_from_rnode(rn);
3292693b 439
3d9dbdbe 440 bc = bgp_connected_get_node_info(bn);
3292693b
DS
441 if (!bc)
442 return;
443
444 bc->refcnt--;
445 if (bc->refcnt == 0) {
446 XFREE(MTYPE_BGP_CONN, bc);
3d9dbdbe 447 bgp_connected_set_node_info(bn, NULL);
3292693b
DS
448 }
449}
450
d62a17ae 451int bgp_nexthop_self(struct bgp *bgp, struct in_addr nh_addr)
718e3744 452{
d62a17ae 453 struct bgp_addr tmp, *addr;
db0e1937 454 struct tip_addr tmp_tip, *tip;
718e3744 455
d62a17ae 456 tmp.addr = nh_addr;
10f9bf3f 457
d62a17ae 458 addr = hash_lookup(bgp->address_hash, &tmp);
459 if (addr)
460 return 1;
718e3744 461
db0e1937
MK
462 tmp_tip.addr = nh_addr;
463 tip = hash_lookup(bgp->tip_hash, &tmp_tip);
464 if (tip)
465 return 1;
466
d62a17ae 467 return 0;
718e3744 468}
6b0655a2 469
d62a17ae 470int bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer)
718e3744 471{
d62a17ae 472 struct bgp_node *rn1;
473 struct bgp_node *rn2;
474 struct prefix p;
475 int ret;
476
477 p.family = AF_INET;
478 p.prefixlen = IPV4_MAX_BITLEN;
479 p.u.prefix4 = nexthop;
480
481 rn1 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
482 if (!rn1)
483 return 0;
484
485 p.family = AF_INET;
486 p.prefixlen = IPV4_MAX_BITLEN;
487 p.u.prefix4 = peer->su.sin.sin_addr;
488
489 rn2 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
490 if (!rn2) {
491 bgp_unlock_node(rn1);
492 return 0;
493 }
718e3744 494
d62a17ae 495 ret = (rn1 == rn2) ? 1 : 0;
718e3744 496
d62a17ae 497 bgp_unlock_node(rn1);
498 bgp_unlock_node(rn2);
718e3744 499
d62a17ae 500 return (ret);
718e3744 501}
502
65d4e0c6
DS
503int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
504 struct update_subgroup *subgrp)
505{
506 struct bgp_node *rn1, *rn2;
507 struct peer_af *paf;
508 struct prefix p, np;
a2b6e694 509 struct bgp *bgp;
65d4e0c6
DS
510
511 np.family = AF_INET;
512 np.prefixlen = IPV4_MAX_BITLEN;
513 np.u.prefix4 = nexthop;
514
515 p.family = AF_INET;
516 p.prefixlen = IPV4_MAX_BITLEN;
517
65d4e0c6 518 bgp = SUBGRP_INST(subgrp);
996c9314 519 rn1 = bgp_node_match(bgp->connected_table[AFI_IP], &np);
65d4e0c6
DS
520 if (!rn1)
521 return 0;
522
996c9314 523 SUBGRP_FOREACH_PEER (subgrp, paf) {
65d4e0c6
DS
524 p.u.prefix4 = paf->peer->su.sin.sin_addr;
525
996c9314 526 rn2 = bgp_node_match(bgp->connected_table[AFI_IP], &p);
65d4e0c6
DS
527 if (rn1 == rn2) {
528 bgp_unlock_node(rn1);
529 bgp_unlock_node(rn2);
530 return 1;
531 }
532
533 if (rn2)
534 bgp_unlock_node(rn2);
535 }
536
537 bgp_unlock_node(rn1);
538 return 0;
539}
540
996c9314 541static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp,
e22ac3ee
DS
542 struct bgp_nexthop_cache *bnc)
543{
544 char buf[PREFIX2STR_BUFFER];
545 struct nexthop *nexthop;
546
547 for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next)
548 switch (nexthop->type) {
549 case NEXTHOP_TYPE_IPV6:
550 vty_out(vty, " gate %s\n",
996c9314
LB
551 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
552 sizeof(buf)));
e22ac3ee
DS
553 break;
554 case NEXTHOP_TYPE_IPV6_IFINDEX:
555 vty_out(vty, " gate %s, if %s\n",
996c9314
LB
556 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
557 sizeof(buf)),
558 ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
e22ac3ee
DS
559 break;
560 case NEXTHOP_TYPE_IPV4:
561 vty_out(vty, " gate %s\n",
996c9314
LB
562 inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
563 sizeof(buf)));
e22ac3ee
DS
564 break;
565 case NEXTHOP_TYPE_IFINDEX:
566 vty_out(vty, " if %s\n",
996c9314 567 ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
e22ac3ee
DS
568 break;
569 case NEXTHOP_TYPE_IPV4_IFINDEX:
570 vty_out(vty, " gate %s, if %s\n",
996c9314
LB
571 inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
572 sizeof(buf)),
573 ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
e22ac3ee
DS
574 break;
575 case NEXTHOP_TYPE_BLACKHOLE:
576 vty_out(vty, " blackhole\n");
577 break;
578 default:
996c9314 579 vty_out(vty, " invalid nexthop type %u\n",
e22ac3ee
DS
580 nexthop->type);
581 }
582}
583
d62a17ae 584static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail)
fb018d25 585{
d62a17ae 586 struct bgp_node *rn;
587 struct bgp_nexthop_cache *bnc;
588 char buf[PREFIX2STR_BUFFER];
d62a17ae 589 time_t tbuf;
590 afi_t afi;
591
592 vty_out(vty, "Current BGP nexthop cache:\n");
593 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
594 if (!bgp->nexthop_cache_table[afi])
595 continue;
596
597 for (rn = bgp_table_top(bgp->nexthop_cache_table[afi]); rn;
598 rn = bgp_route_next(rn)) {
14315f2d
DS
599 bnc = bgp_nexthop_get_node_info(rn);
600 if (!bnc)
601 continue;
602
603 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) {
604 vty_out(vty,
605 " %s valid [IGP metric %d], #paths %d\n",
606 inet_ntop(rn->p.family,
607 &rn->p.u.prefix, buf,
608 sizeof(buf)),
609 bnc->metric, bnc->path_count);
610
611 if (!detail)
612 continue;
613
614 bgp_show_nexthops_detail(vty, bgp, bnc);
615
616 } else {
617 vty_out(vty, " %s invalid\n",
618 inet_ntop(rn->p.family,
619 &rn->p.u.prefix, buf,
620 sizeof(buf)));
621 if (CHECK_FLAG(bnc->flags,
622 BGP_NEXTHOP_CONNECTED))
623 vty_out(vty, " Must be Connected\n");
d62a17ae 624 }
14315f2d
DS
625 tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
626 vty_out(vty, " Last update: %s", ctime(&tbuf));
627 vty_out(vty, "\n");
da11a696 628 }
fb018d25 629 }
f186de26 630}
631
d62a17ae 632static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name,
633 int detail)
f186de26 634{
d62a17ae 635 struct bgp *bgp;
636
637 if (name)
638 bgp = bgp_lookup_by_name(name);
639 else
640 bgp = bgp_get_default();
641 if (!bgp) {
642 vty_out(vty, "%% No such BGP instance exist\n");
643 return CMD_WARNING;
644 }
f186de26 645
d62a17ae 646 bgp_show_nexthops(vty, bgp, detail);
f186de26 647
d62a17ae 648 return CMD_SUCCESS;
fb018d25
DS
649}
650
d62a17ae 651static void bgp_show_all_instances_nexthops_vty(struct vty *vty)
f186de26 652{
d62a17ae 653 struct listnode *node, *nnode;
654 struct bgp *bgp;
655
656 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
657 vty_out(vty, "\nInstance %s:\n",
658 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
659 ? "Default"
660 : bgp->name);
661 bgp_show_nexthops(vty, bgp, 0);
662 }
f186de26 663}
664
fb018d25
DS
665DEFUN (show_ip_bgp_nexthop,
666 show_ip_bgp_nexthop_cmd,
18c57037 667 "show [ip] bgp [<view|vrf> VIEWVRFNAME] nexthop [detail]",
50ef26d4 668 SHOW_STR
669 IP_STR
670 BGP_STR
8386ac43 671 BGP_INSTANCE_HELP_STR
3a2d747c
QY
672 "BGP nexthop table\n"
673 "Show detailed information\n")
50ef26d4 674{
d62a17ae 675 int idx = 0;
b7ada628
DS
676 char *vrf = NULL;
677
678 if (argv_find(argv, argc, "view", &idx)
679 || argv_find(argv, argc, "vrf", &idx))
680 vrf = argv[++idx]->arg;
d62a17ae 681 int detail = argv_find(argv, argc, "detail", &idx) ? 1 : 0;
682 return show_ip_bgp_nexthop_table(vty, vrf, detail);
50ef26d4 683}
684
f186de26 685DEFUN (show_ip_bgp_instance_all_nexthop,
686 show_ip_bgp_instance_all_nexthop_cmd,
bec37ba5 687 "show [ip] bgp <view|vrf> all nexthop",
f186de26 688 SHOW_STR
689 IP_STR
690 BGP_STR
691 BGP_INSTANCE_ALL_HELP_STR
692 "BGP nexthop table\n")
693{
d62a17ae 694 bgp_show_all_instances_nexthops_vty(vty);
695 return CMD_SUCCESS;
f186de26 696}
697
d62a17ae 698void bgp_scan_init(struct bgp *bgp)
718e3744 699{
d62a17ae 700 afi_t afi;
701
702 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
703 bgp->nexthop_cache_table[afi] =
960035b2
PZ
704 bgp_table_init(bgp, afi, SAFI_UNICAST);
705 bgp->connected_table[afi] = bgp_table_init(bgp, afi,
706 SAFI_UNICAST);
d62a17ae 707 bgp->import_check_table[afi] =
960035b2 708 bgp_table_init(bgp, afi, SAFI_UNICAST);
d62a17ae 709 }
fc9a856f
DS
710}
711
d62a17ae 712void bgp_scan_vty_init(void)
fc9a856f 713{
d62a17ae 714 install_element(VIEW_NODE, &show_ip_bgp_nexthop_cmd);
715 install_element(VIEW_NODE, &show_ip_bgp_instance_all_nexthop_cmd);
718e3744 716}
228da428 717
d62a17ae 718void bgp_scan_finish(struct bgp *bgp)
228da428 719{
d62a17ae 720 afi_t afi;
6c88b44d 721
d62a17ae 722 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
723 /* Only the current one needs to be reset. */
724 bgp_nexthop_cache_reset(bgp->nexthop_cache_table[afi]);
725 bgp_table_unlock(bgp->nexthop_cache_table[afi]);
726 bgp->nexthop_cache_table[afi] = NULL;
228da428 727
3292693b
DS
728 bgp->connected_table[afi]->route_table->cleanup =
729 bgp_connected_cleanup;
d62a17ae 730 bgp_table_unlock(bgp->connected_table[afi]);
731 bgp->connected_table[afi] = NULL;
078430f6 732
d62a17ae 733 bgp_table_unlock(bgp->import_check_table[afi]);
734 bgp->import_check_table[afi] = NULL;
735 }
228da428 736}