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