]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_nexthop.c
Merge pull request #6577 from rtrlib/2020-06-12-master-fixes
[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"
5d76a53d 47#include "bgpd/bgp_rd.h"
718e3744 48
330cec3d
DS
49DEFINE_MTYPE_STATIC(BGPD, MARTIAN_STRING, "BGP Martian Address Intf String");
50
d62a17ae 51char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size)
fb018d25 52{
b54892e0 53 prefix2str(bgp_node_get_prefix(bnc->node), buf, size);
d62a17ae 54 return buf;
fb018d25
DS
55}
56
d62a17ae 57void bnc_nexthop_free(struct bgp_nexthop_cache *bnc)
718e3744 58{
d62a17ae 59 nexthops_free(bnc->nexthop);
718e3744 60}
61
d62a17ae 62struct bgp_nexthop_cache *bnc_new(void)
718e3744 63{
d62a17ae 64 struct bgp_nexthop_cache *bnc;
fb018d25 65
d62a17ae 66 bnc = XCALLOC(MTYPE_BGP_NEXTHOP_CACHE,
67 sizeof(struct bgp_nexthop_cache));
68 LIST_INIT(&(bnc->paths));
69 return bnc;
718e3744 70}
71
d62a17ae 72void bnc_free(struct bgp_nexthop_cache *bnc)
718e3744 73{
d62a17ae 74 bnc_nexthop_free(bnc);
75 XFREE(MTYPE_BGP_NEXTHOP_CACHE, bnc);
718e3744 76}
6b0655a2 77
718e3744 78/* Reset and free all BGP nexthop cache. */
d62a17ae 79static void bgp_nexthop_cache_reset(struct bgp_table *table)
718e3744 80{
d62a17ae 81 struct bgp_node *rn;
82 struct bgp_nexthop_cache *bnc;
83
14315f2d 84 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5b8d32bd 85 bnc = bgp_node_get_bgp_nexthop_info(rn);
3d111939
DS
86 if (!bnc)
87 continue;
7f040da1 88
3d111939
DS
89 while (!LIST_EMPTY(&(bnc->paths))) {
90 struct bgp_path_info *path = LIST_FIRST(&(bnc->paths));
7f040da1 91
3d111939 92 path_nh_map(path, bnc, false);
d62a17ae 93 }
3d111939
DS
94
95 bnc_free(bnc);
5b8d32bd 96 bgp_node_set_bgp_nexthop_info(rn, NULL);
3d111939 97 bgp_unlock_node(rn);
14315f2d 98 }
718e3744 99}
100
db0e1937
MK
101static void *bgp_tip_hash_alloc(void *p)
102{
0291c246
MK
103 const struct in_addr *val = (const struct in_addr *)p;
104 struct tip_addr *addr;
db0e1937
MK
105
106 addr = XMALLOC(MTYPE_TIP_ADDR, sizeof(struct tip_addr));
107 addr->refcnt = 0;
108 addr->addr.s_addr = val->s_addr;
109
110 return addr;
111}
112
113static void bgp_tip_hash_free(void *addr)
114{
115 XFREE(MTYPE_TIP_ADDR, addr);
116}
117
d8b87afe 118static unsigned int bgp_tip_hash_key_make(const void *p)
db0e1937 119{
0291c246 120 const struct tip_addr *addr = p;
db0e1937
MK
121
122 return jhash_1word(addr->addr.s_addr, 0);
123}
124
74df8d6d 125static bool bgp_tip_hash_cmp(const void *p1, const void *p2)
db0e1937 126{
0291c246
MK
127 const struct tip_addr *addr1 = p1;
128 const struct tip_addr *addr2 = p2;
db0e1937
MK
129
130 return addr1->addr.s_addr == addr2->addr.s_addr;
131}
132
133void bgp_tip_hash_init(struct bgp *bgp)
134{
996c9314 135 bgp->tip_hash = hash_create(bgp_tip_hash_key_make, bgp_tip_hash_cmp,
3f65c5b1 136 "BGP TIP hash");
db0e1937
MK
137}
138
139void bgp_tip_hash_destroy(struct bgp *bgp)
140{
141 if (bgp->tip_hash == NULL)
142 return;
143 hash_clean(bgp->tip_hash, bgp_tip_hash_free);
144 hash_free(bgp->tip_hash);
145 bgp->tip_hash = NULL;
146}
147
148void bgp_tip_add(struct bgp *bgp, struct in_addr *tip)
149{
0291c246
MK
150 struct tip_addr tmp;
151 struct tip_addr *addr;
db0e1937
MK
152
153 tmp.addr = *tip;
154
155 addr = hash_get(bgp->tip_hash, &tmp, bgp_tip_hash_alloc);
156 if (!addr)
157 return;
158
159 addr->refcnt++;
160}
161
162void bgp_tip_del(struct bgp *bgp, struct in_addr *tip)
163{
0291c246
MK
164 struct tip_addr tmp;
165 struct tip_addr *addr;
db0e1937
MK
166
167 tmp.addr = *tip;
168
169 addr = hash_lookup(bgp->tip_hash, &tmp);
170 /* may have been deleted earlier by bgp_interface_down() */
171 if (addr == NULL)
172 return;
173
174 addr->refcnt--;
175
176 if (addr->refcnt == 0) {
177 hash_release(bgp->tip_hash, addr);
178 XFREE(MTYPE_TIP_ADDR, addr);
179 }
180}
10f9bf3f 181
af97a18b
DS
182/* BGP own address structure */
183struct bgp_addr {
2ec802d1 184 struct prefix p;
f4c2fb93 185 struct list *ifp_name_list;
af97a18b
DS
186};
187
e3b78da8 188static void show_address_entry(struct hash_bucket *bucket, void *args)
af97a18b
DS
189{
190 struct vty *vty = (struct vty *)args;
e3b78da8 191 struct bgp_addr *addr = (struct bgp_addr *)bucket->data;
f4c2fb93
DS
192 char *name;
193 struct listnode *node;
949b0f24 194 char str[INET6_ADDRSTRLEN] = {0};
195
e61f7c0a 196 vty_out(vty, "addr: %s, count: %d : ",
2ec802d1 197 inet_ntop(addr->p.family, &(addr->p.u.prefix),
e61f7c0a
DS
198 str, INET6_ADDRSTRLEN),
199 addr->ifp_name_list->count);
f4c2fb93
DS
200
201 for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
202 vty_out(vty, " %s,", name);
203 }
204
205 vty_out(vty, "\n");
af97a18b
DS
206}
207
208void bgp_nexthop_show_address_hash(struct vty *vty, struct bgp *bgp)
209{
210 hash_iterate(bgp->address_hash,
e3b78da8 211 (void (*)(struct hash_bucket *, void *))show_address_entry,
af97a18b
DS
212 vty);
213}
214
f4c2fb93
DS
215static void bgp_address_hash_string_del(void *val)
216{
217 char *data = val;
218
330cec3d 219 XFREE(MTYPE_MARTIAN_STRING, data);
f4c2fb93
DS
220}
221
d62a17ae 222static void *bgp_address_hash_alloc(void *p)
10f9bf3f 223{
949b0f24 224 struct bgp_addr *copy_addr = p;
225 struct bgp_addr *addr = NULL;
10f9bf3f 226
d62a17ae 227 addr = XMALLOC(MTYPE_BGP_ADDR, sizeof(struct bgp_addr));
2ec802d1 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
6a154c88 240 list_delete(&addr->ifp_name_list);
d62a17ae 241 XFREE(MTYPE_BGP_ADDR, addr);
37d361e7
RW
242}
243
d8b87afe 244static unsigned int bgp_address_hash_key_make(const void *p)
10f9bf3f 245{
d62a17ae 246 const struct bgp_addr *addr = p;
10f9bf3f 247
2ec802d1 248 return prefix_hash_key(&addr->p);
10f9bf3f
JBD
249}
250
74df8d6d 251static bool bgp_address_hash_cmp(const void *p1, const void *p2)
10f9bf3f 252{
d62a17ae 253 const struct bgp_addr *addr1 = p1;
254 const struct bgp_addr *addr2 = p2;
10f9bf3f 255
2ec802d1 256 return prefix_same(&addr1->p, &addr2->p);
10f9bf3f
JBD
257}
258
d62a17ae 259void bgp_address_init(struct bgp *bgp)
10f9bf3f 260{
996c9314
LB
261 bgp->address_hash =
262 hash_create(bgp_address_hash_key_make, bgp_address_hash_cmp,
949b0f24 263 "BGP Connected Address Hash");
10f9bf3f
JBD
264}
265
d62a17ae 266void bgp_address_destroy(struct bgp *bgp)
bb86c601 267{
d62a17ae 268 if (bgp->address_hash == NULL)
269 return;
270 hash_clean(bgp->address_hash, bgp_address_hash_free);
271 hash_free(bgp->address_hash);
272 bgp->address_hash = NULL;
bb86c601
LB
273}
274
f4c2fb93
DS
275static void bgp_address_add(struct bgp *bgp, struct connected *ifc,
276 struct prefix *p)
10f9bf3f 277{
d62a17ae 278 struct bgp_addr tmp;
279 struct bgp_addr *addr;
f4c2fb93
DS
280 struct listnode *node;
281 char *name;
10f9bf3f 282
2ec802d1 283 tmp.p = *p;
949b0f24 284
2ec802d1
DS
285 if (tmp.p.family == AF_INET)
286 tmp.p.prefixlen = IPV4_MAX_BITLEN;
287 else if (tmp.p.family == AF_INET6)
288 tmp.p.prefixlen = IPV6_MAX_BITLEN;
10f9bf3f 289
d62a17ae 290 addr = hash_get(bgp->address_hash, &tmp, bgp_address_hash_alloc);
5ce10e92 291
f4c2fb93
DS
292 for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
293 if (strcmp(ifc->ifp->name, name) == 0)
294 break;
295 }
296 if (!node) {
330cec3d 297 name = XSTRDUP(MTYPE_MARTIAN_STRING, ifc->ifp->name);
f4c2fb93
DS
298 listnode_add(addr->ifp_name_list, name);
299 }
10f9bf3f
JBD
300}
301
f4c2fb93
DS
302static void bgp_address_del(struct bgp *bgp, struct connected *ifc,
303 struct prefix *p)
10f9bf3f 304{
d62a17ae 305 struct bgp_addr tmp;
306 struct bgp_addr *addr;
f4c2fb93
DS
307 struct listnode *node;
308 char *name;
10f9bf3f 309
2ec802d1 310 tmp.p = *p;
949b0f24 311
2ec802d1
DS
312 if (tmp.p.family == AF_INET)
313 tmp.p.prefixlen = IPV4_MAX_BITLEN;
314 else if (tmp.p.family == AF_INET6)
315 tmp.p.prefixlen = IPV6_MAX_BITLEN;
10f9bf3f 316
d62a17ae 317 addr = hash_lookup(bgp->address_hash, &tmp);
318 /* may have been deleted earlier by bgp_interface_down() */
319 if (addr == NULL)
320 return;
9e47abd8 321
f4c2fb93
DS
322 for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
323 if (strcmp(ifc->ifp->name, name) == 0)
324 break;
325 }
10f9bf3f 326
b9129915 327 if (node) {
f4c2fb93 328 list_delete_node(addr->ifp_name_list, node);
b9129915
DS
329 XFREE(MTYPE_MARTIAN_STRING, name);
330 }
f4c2fb93
DS
331
332 if (addr->ifp_name_list->count == 0) {
d62a17ae 333 hash_release(bgp->address_hash, addr);
6a154c88 334 list_delete(&addr->ifp_name_list);
d62a17ae 335 XFREE(MTYPE_BGP_ADDR, addr);
336 }
10f9bf3f
JBD
337}
338
6b0655a2 339
d62a17ae 340struct bgp_connected_ref {
341 unsigned int refcnt;
718e3744 342};
343
d62a17ae 344void bgp_connected_add(struct bgp *bgp, struct connected *ifc)
718e3744 345{
d62a17ae 346 struct prefix p;
347 struct prefix *addr;
348 struct bgp_node *rn;
349 struct bgp_connected_ref *bc;
350 struct listnode *node, *nnode;
351 struct peer *peer;
352
353 addr = ifc->address;
354
355 p = *(CONNECTED_PREFIX(ifc));
356 if (addr->family == AF_INET) {
357 apply_mask_ipv4((struct prefix_ipv4 *)&p);
358
359 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
360 return;
361
f4c2fb93 362 bgp_address_add(bgp, ifc, addr);
d62a17ae 363
364 rn = bgp_node_get(bgp->connected_table[AFI_IP],
365 (struct prefix *)&p);
cb8c85ab 366 bc = bgp_node_get_bgp_connected_ref_info(rn);
3d9dbdbe 367 if (bc)
d62a17ae 368 bc->refcnt++;
3d9dbdbe 369 else {
d62a17ae 370 bc = XCALLOC(MTYPE_BGP_CONN,
371 sizeof(struct bgp_connected_ref));
372 bc->refcnt = 1;
cb8c85ab 373 bgp_node_set_bgp_connected_ref_info(rn, bc);
d62a17ae 374 }
8ffedcea 375
d62a17ae 376 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
377 if (peer->conf_if
378 && (strcmp(peer->conf_if, ifc->ifp->name) == 0)
379 && peer->status != Established
380 && !CHECK_FLAG(peer->flags,
381 PEER_FLAG_IFPEER_V6ONLY)) {
382 if (peer_active(peer))
383 BGP_EVENT_ADD(peer, BGP_Stop);
384 BGP_EVENT_ADD(peer, BGP_Start);
385 }
386 }
387 } else if (addr->family == AF_INET6) {
388 apply_mask_ipv6((struct prefix_ipv6 *)&p);
389
390 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
391 return;
392
393 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
394 return;
395
949b0f24 396 bgp_address_add(bgp, ifc, addr);
397
d62a17ae 398 rn = bgp_node_get(bgp->connected_table[AFI_IP6],
399 (struct prefix *)&p);
3d9dbdbe 400
cb8c85ab 401 bc = bgp_node_get_bgp_connected_ref_info(rn);
3d9dbdbe 402 if (bc)
d62a17ae 403 bc->refcnt++;
3d9dbdbe 404 else {
d62a17ae 405 bc = XCALLOC(MTYPE_BGP_CONN,
406 sizeof(struct bgp_connected_ref));
407 bc->refcnt = 1;
cb8c85ab 408 bgp_node_set_bgp_connected_ref_info(rn, bc);
d62a17ae 409 }
718e3744 410 }
718e3744 411}
412
d62a17ae 413void bgp_connected_delete(struct bgp *bgp, struct connected *ifc)
718e3744 414{
d62a17ae 415 struct prefix p;
416 struct prefix *addr;
f6bdc080 417 struct bgp_node *rn = NULL;
d62a17ae 418 struct bgp_connected_ref *bc;
718e3744 419
d62a17ae 420 addr = ifc->address;
718e3744 421
d62a17ae 422 p = *(CONNECTED_PREFIX(ifc));
f6bdc080 423 apply_mask(&p);
d62a17ae 424 if (addr->family == AF_INET) {
d62a17ae 425 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
426 return;
718e3744 427
f4c2fb93 428 bgp_address_del(bgp, ifc, addr);
10f9bf3f 429
d62a17ae 430 rn = bgp_node_lookup(bgp->connected_table[AFI_IP], &p);
d62a17ae 431 } else if (addr->family == AF_INET6) {
d62a17ae 432 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
433 return;
434
435 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
436 return;
437
949b0f24 438 bgp_address_del(bgp, ifc, addr);
439
c4efd0f4 440 rn = bgp_node_lookup(bgp->connected_table[AFI_IP6], &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;
b54892e0 479 const struct prefix *p = bgp_node_get_prefix(rn);
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) {
b54892e0
DS
492 tmp_addr.p.u.prefix4 = p->u.prefix4;
493 tmp_addr.p.prefixlen = 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) {
b54892e0
DS
513 tmp_addr.p.u.prefix6 = p->u.prefix6;
514 tmp_addr.p.prefixlen = 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
5d76a53d 699static void bgp_show_nexthop_paths(struct vty *vty, struct bgp *bgp,
700 struct bgp_nexthop_cache *bnc)
701{
702 struct bgp_node *rn;
703 struct bgp_path_info *path;
704 int afi;
705 safi_t safi;
706 struct bgp_table *table;
707 struct bgp *bgp_path;
708 char buf1[BUFSIZ];
709
710 vty_out(vty, " Paths:\n");
711 LIST_FOREACH (path, &(bnc->paths), nh_thread) {
712 rn = path->net;
713 assert(rn && bgp_node_table(rn));
714 afi = family2afi(rn->p.family);
715 table = bgp_node_table(rn);
716 safi = table->safi;
717 bgp_path = table->bgp;
718
719 if (rn->prn) {
720 prefix_rd2str((struct prefix_rd *)&rn->prn->p,
721 buf1, sizeof(buf1));
722 vty_out(vty, " %d/%d %pRN RD %s %s flags 0x%x\n",
723 afi, safi, rn, buf1, bgp_path->name_pretty, path->flags);
724 } else
725 vty_out(vty, " %d/%d %pRN %s flags 0x%x\n",
726 afi, safi, rn, bgp_path->name_pretty, path->flags);
727 }
728}
729
996c9314 730static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp,
e22ac3ee
DS
731 struct bgp_nexthop_cache *bnc)
732{
733 char buf[PREFIX2STR_BUFFER];
734 struct nexthop *nexthop;
735
5d76a53d 736 for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next) {
e22ac3ee
DS
737 switch (nexthop->type) {
738 case NEXTHOP_TYPE_IPV6:
739 vty_out(vty, " gate %s\n",
996c9314
LB
740 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
741 sizeof(buf)));
e22ac3ee
DS
742 break;
743 case NEXTHOP_TYPE_IPV6_IFINDEX:
744 vty_out(vty, " gate %s, if %s\n",
996c9314
LB
745 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
746 sizeof(buf)),
747 ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
e22ac3ee
DS
748 break;
749 case NEXTHOP_TYPE_IPV4:
750 vty_out(vty, " gate %s\n",
996c9314
LB
751 inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
752 sizeof(buf)));
e22ac3ee
DS
753 break;
754 case NEXTHOP_TYPE_IFINDEX:
755 vty_out(vty, " if %s\n",
996c9314 756 ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
e22ac3ee
DS
757 break;
758 case NEXTHOP_TYPE_IPV4_IFINDEX:
759 vty_out(vty, " gate %s, if %s\n",
996c9314
LB
760 inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
761 sizeof(buf)),
762 ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
e22ac3ee
DS
763 break;
764 case NEXTHOP_TYPE_BLACKHOLE:
765 vty_out(vty, " blackhole\n");
766 break;
767 default:
996c9314 768 vty_out(vty, " invalid nexthop type %u\n",
e22ac3ee
DS
769 nexthop->type);
770 }
5d76a53d 771 }
e22ac3ee
DS
772}
773
5d76a53d 774static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp,
775 struct bgp_node *rn,
776 struct bgp_nexthop_cache *bnc,
777 bool specific)
fb018d25 778{
d62a17ae 779 char buf[PREFIX2STR_BUFFER];
d62a17ae 780 time_t tbuf;
5d76a53d 781 struct peer *peer;
782 const struct prefix *p = bgp_node_get_prefix(rn);
783
784 peer = (struct peer *)bnc->nht_info;
785
786 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) {
787 vty_out(vty, " %s valid [IGP metric %d], #paths %d",
788 inet_ntop(p->family, &p->u.prefix, buf, sizeof(buf)),
789 bnc->metric, bnc->path_count);
790 if (peer)
791 vty_out(vty, ", peer %s", peer->host);
792 vty_out(vty, "\n");
793 bgp_show_nexthops_detail(vty, bgp, bnc);
794 } else {
795 vty_out(vty, " %s invalid, #paths %d",
796 inet_ntop(p->family, &p->u.prefix, buf, sizeof(buf)),
797 bnc->path_count);
798 if (peer)
799 vty_out(vty, ", peer %s", peer->host);
800 vty_out(vty, "\n");
801 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
802 vty_out(vty, " Must be Connected\n");
803 if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
804 vty_out(vty, " Is not Registered\n");
805 }
806 tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
807 vty_out(vty, " Last update: %s", ctime(&tbuf));
808 vty_out(vty, "\n");
809
810 /* show paths dependent on nexthop, if needed. */
811 if (specific)
812 bgp_show_nexthop_paths(vty, bgp, bnc);
813}
814
815static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp,
816 bool import_table)
817{
818 struct bgp_node *rn;
819 struct bgp_nexthop_cache *bnc;
d62a17ae 820 afi_t afi;
05e47722 821 struct bgp_table **table;
d62a17ae 822
05e47722
PG
823 if (import_table)
824 vty_out(vty, "Current BGP import check cache:\n");
825 else
826 vty_out(vty, "Current BGP nexthop cache:\n");
827 if (import_table)
828 table = bgp->import_check_table;
829 else
830 table = bgp->nexthop_cache_table;
d62a17ae 831 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
05e47722 832 if (!table || !table[afi])
d62a17ae 833 continue;
05e47722 834 for (rn = bgp_table_top(table[afi]); rn;
d62a17ae 835 rn = bgp_route_next(rn)) {
5b8d32bd 836 bnc = bgp_node_get_bgp_nexthop_info(rn);
14315f2d
DS
837 if (!bnc)
838 continue;
5d76a53d 839 bgp_show_nexthop(vty, bgp, rn, bnc, false);
da11a696 840 }
fb018d25 841 }
f186de26 842}
843
d62a17ae 844static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name,
5d76a53d 845 const char *nhopip_str,
846 bool import_table)
f186de26 847{
d62a17ae 848 struct bgp *bgp;
849
850 if (name)
851 bgp = bgp_lookup_by_name(name);
852 else
853 bgp = bgp_get_default();
854 if (!bgp) {
855 vty_out(vty, "%% No such BGP instance exist\n");
856 return CMD_WARNING;
857 }
f186de26 858
5d76a53d 859 if (nhopip_str) {
860 struct prefix nhop;
861 struct bgp_table **table;
862 struct bgp_node *rn;
863 struct bgp_nexthop_cache *bnc;
864
865 if (!str2prefix(nhopip_str, &nhop)) {
866 vty_out(vty, "nexthop address is malformed\n");
867 return CMD_WARNING;
868 }
869 table = import_table ? \
870 bgp->import_check_table : bgp->nexthop_cache_table;
871 rn = bgp_node_lookup(table[family2afi(nhop.family)], &nhop);
872 if (!rn) {
873 vty_out(vty, "specified nexthop is not found\n");
874 return CMD_SUCCESS;
875 }
876 bnc = bgp_node_get_bgp_nexthop_info(rn);
877 if (!bnc) {
878 vty_out(vty, "specified nexthop does not have entry\n");
879 return CMD_SUCCESS;
880 }
881 bgp_show_nexthop(vty, bgp, rn, bnc, true);
882 } else
883 bgp_show_nexthops(vty, bgp, import_table);
f186de26 884
d62a17ae 885 return CMD_SUCCESS;
fb018d25
DS
886}
887
d62a17ae 888static void bgp_show_all_instances_nexthops_vty(struct vty *vty)
f186de26 889{
d62a17ae 890 struct listnode *node, *nnode;
891 struct bgp *bgp;
892
893 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
894 vty_out(vty, "\nInstance %s:\n",
895 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 896 ? VRF_DEFAULT_NAME
d62a17ae 897 : bgp->name);
5d76a53d 898 bgp_show_nexthops(vty, bgp, false);
d62a17ae 899 }
f186de26 900}
901
fb018d25
DS
902DEFUN (show_ip_bgp_nexthop,
903 show_ip_bgp_nexthop_cmd,
5d76a53d 904 "show [ip] bgp [<view|vrf> VIEWVRFNAME] nexthop [<A.B.C.D|X:X::X:X>] [detail]",
50ef26d4 905 SHOW_STR
906 IP_STR
907 BGP_STR
8386ac43 908 BGP_INSTANCE_HELP_STR
3a2d747c 909 "BGP nexthop table\n"
5d76a53d 910 "IPv4 nexthop address\n"
911 "IPv6 nexthop address\n"
3a2d747c 912 "Show detailed information\n")
50ef26d4 913{
d62a17ae 914 int idx = 0;
5d76a53d 915 int nh_idx = 0;
b7ada628 916 char *vrf = NULL;
5d76a53d 917 char *nhop_ip = NULL;
b7ada628
DS
918
919 if (argv_find(argv, argc, "view", &idx)
920 || argv_find(argv, argc, "vrf", &idx))
921 vrf = argv[++idx]->arg;
05e47722 922
5d76a53d 923 if (argv_find(argv, argc, "A.B.C.D", &nh_idx)
924 || argv_find(argv, argc, "X:X::X:X", &nh_idx))
925 nhop_ip = argv[nh_idx]->arg;
926
927 return show_ip_bgp_nexthop_table(vty, vrf, nhop_ip, false);
05e47722
PG
928}
929
930DEFUN (show_ip_bgp_import_check,
931 show_ip_bgp_import_check_cmd,
932 "show [ip] bgp [<view|vrf> VIEWVRFNAME] import-check-table [detail]",
933 SHOW_STR
934 IP_STR
935 BGP_STR
936 BGP_INSTANCE_HELP_STR
937 "BGP import check table\n"
938 "Show detailed information\n")
939{
940 int idx = 0;
941 char *vrf = NULL;
942
943 if (argv_find(argv, argc, "view", &idx)
944 || argv_find(argv, argc, "vrf", &idx))
945 vrf = argv[++idx]->arg;
5d76a53d 946
947 return show_ip_bgp_nexthop_table(vty, vrf, NULL, true);
50ef26d4 948}
949
f186de26 950DEFUN (show_ip_bgp_instance_all_nexthop,
951 show_ip_bgp_instance_all_nexthop_cmd,
bec37ba5 952 "show [ip] bgp <view|vrf> all nexthop",
f186de26 953 SHOW_STR
954 IP_STR
955 BGP_STR
956 BGP_INSTANCE_ALL_HELP_STR
957 "BGP nexthop table\n")
958{
d62a17ae 959 bgp_show_all_instances_nexthops_vty(vty);
960 return CMD_SUCCESS;
f186de26 961}
962
d62a17ae 963void bgp_scan_init(struct bgp *bgp)
718e3744 964{
d62a17ae 965 afi_t afi;
966
967 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
968 bgp->nexthop_cache_table[afi] =
960035b2
PZ
969 bgp_table_init(bgp, afi, SAFI_UNICAST);
970 bgp->connected_table[afi] = bgp_table_init(bgp, afi,
971 SAFI_UNICAST);
d62a17ae 972 bgp->import_check_table[afi] =
960035b2 973 bgp_table_init(bgp, afi, SAFI_UNICAST);
d62a17ae 974 }
fc9a856f
DS
975}
976
d62a17ae 977void bgp_scan_vty_init(void)
fc9a856f 978{
d62a17ae 979 install_element(VIEW_NODE, &show_ip_bgp_nexthop_cmd);
05e47722 980 install_element(VIEW_NODE, &show_ip_bgp_import_check_cmd);
d62a17ae 981 install_element(VIEW_NODE, &show_ip_bgp_instance_all_nexthop_cmd);
718e3744 982}
228da428 983
d62a17ae 984void bgp_scan_finish(struct bgp *bgp)
228da428 985{
d62a17ae 986 afi_t afi;
6c88b44d 987
d62a17ae 988 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
989 /* Only the current one needs to be reset. */
990 bgp_nexthop_cache_reset(bgp->nexthop_cache_table[afi]);
991 bgp_table_unlock(bgp->nexthop_cache_table[afi]);
992 bgp->nexthop_cache_table[afi] = NULL;
228da428 993
3292693b
DS
994 bgp->connected_table[afi]->route_table->cleanup =
995 bgp_connected_cleanup;
d62a17ae 996 bgp_table_unlock(bgp->connected_table[afi]);
997 bgp->connected_table[afi] = NULL;
078430f6 998
d62a17ae 999 bgp_table_unlock(bgp->import_check_table[afi]);
1000 bgp->import_check_table[afi] = NULL;
1001 }
228da428 1002}