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