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