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