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