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