]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_nexthop.c
Merge pull request #1078 from dwalton76/ospfd-network-cmd-warning
[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#include "zebra/rib.h"
d62a17ae 48#include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
718e3744 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
83 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
84 if ((bnc = rn->info) != NULL) {
85 bnc_free(bnc);
86 rn->info = NULL;
87 bgp_unlock_node(rn);
88 }
718e3744 89}
90
db0e1937
MK
91static void *bgp_tip_hash_alloc(void *p)
92{
0291c246
MK
93 const struct in_addr *val = (const struct in_addr *)p;
94 struct tip_addr *addr;
db0e1937
MK
95
96 addr = XMALLOC(MTYPE_TIP_ADDR, sizeof(struct tip_addr));
97 addr->refcnt = 0;
98 addr->addr.s_addr = val->s_addr;
99
100 return addr;
101}
102
103static void bgp_tip_hash_free(void *addr)
104{
105 XFREE(MTYPE_TIP_ADDR, addr);
106}
107
108static unsigned int bgp_tip_hash_key_make(void *p)
109{
0291c246 110 const struct tip_addr *addr = p;
db0e1937
MK
111
112 return jhash_1word(addr->addr.s_addr, 0);
113}
114
115static int bgp_tip_hash_cmp(const void *p1, const void *p2)
116{
0291c246
MK
117 const struct tip_addr *addr1 = p1;
118 const struct tip_addr *addr2 = p2;
db0e1937
MK
119
120 return addr1->addr.s_addr == addr2->addr.s_addr;
121}
122
123void bgp_tip_hash_init(struct bgp *bgp)
124{
60466a63
QY
125 bgp->tip_hash =
126 hash_create(bgp_tip_hash_key_make, bgp_tip_hash_cmp, NULL);
db0e1937
MK
127}
128
129void bgp_tip_hash_destroy(struct bgp *bgp)
130{
131 if (bgp->tip_hash == NULL)
132 return;
133 hash_clean(bgp->tip_hash, bgp_tip_hash_free);
134 hash_free(bgp->tip_hash);
135 bgp->tip_hash = NULL;
136}
137
138void bgp_tip_add(struct bgp *bgp, struct in_addr *tip)
139{
0291c246
MK
140 struct tip_addr tmp;
141 struct tip_addr *addr;
db0e1937
MK
142
143 tmp.addr = *tip;
144
145 addr = hash_get(bgp->tip_hash, &tmp, bgp_tip_hash_alloc);
146 if (!addr)
147 return;
148
149 addr->refcnt++;
150}
151
152void bgp_tip_del(struct bgp *bgp, struct in_addr *tip)
153{
0291c246
MK
154 struct tip_addr tmp;
155 struct tip_addr *addr;
db0e1937
MK
156
157 tmp.addr = *tip;
158
159 addr = hash_lookup(bgp->tip_hash, &tmp);
160 /* may have been deleted earlier by bgp_interface_down() */
161 if (addr == NULL)
162 return;
163
164 addr->refcnt--;
165
166 if (addr->refcnt == 0) {
167 hash_release(bgp->tip_hash, addr);
168 XFREE(MTYPE_TIP_ADDR, addr);
169 }
170}
10f9bf3f 171
d62a17ae 172static void *bgp_address_hash_alloc(void *p)
10f9bf3f 173{
d62a17ae 174 const struct in_addr *val = (const struct in_addr *)p;
175 struct bgp_addr *addr;
10f9bf3f 176
d62a17ae 177 addr = XMALLOC(MTYPE_BGP_ADDR, sizeof(struct bgp_addr));
178 addr->refcnt = 0;
179 addr->addr.s_addr = val->s_addr;
10f9bf3f 180
d62a17ae 181 return addr;
10f9bf3f
JBD
182}
183
d62a17ae 184static void bgp_address_hash_free(void *addr)
37d361e7 185{
d62a17ae 186 XFREE(MTYPE_BGP_ADDR, addr);
37d361e7
RW
187}
188
d62a17ae 189static unsigned int bgp_address_hash_key_make(void *p)
10f9bf3f 190{
d62a17ae 191 const struct bgp_addr *addr = p;
10f9bf3f 192
d62a17ae 193 return jhash_1word(addr->addr.s_addr, 0);
10f9bf3f
JBD
194}
195
d62a17ae 196static int bgp_address_hash_cmp(const void *p1, const void *p2)
10f9bf3f 197{
d62a17ae 198 const struct bgp_addr *addr1 = p1;
199 const struct bgp_addr *addr2 = p2;
10f9bf3f 200
d62a17ae 201 return addr1->addr.s_addr == addr2->addr.s_addr;
10f9bf3f
JBD
202}
203
d62a17ae 204void bgp_address_init(struct bgp *bgp)
10f9bf3f 205{
d62a17ae 206 bgp->address_hash = hash_create(bgp_address_hash_key_make,
207 bgp_address_hash_cmp, NULL);
10f9bf3f
JBD
208}
209
d62a17ae 210void bgp_address_destroy(struct bgp *bgp)
bb86c601 211{
d62a17ae 212 if (bgp->address_hash == NULL)
213 return;
214 hash_clean(bgp->address_hash, bgp_address_hash_free);
215 hash_free(bgp->address_hash);
216 bgp->address_hash = NULL;
bb86c601
LB
217}
218
d62a17ae 219static void bgp_address_add(struct bgp *bgp, struct prefix *p)
10f9bf3f 220{
d62a17ae 221 struct bgp_addr tmp;
222 struct bgp_addr *addr;
10f9bf3f 223
d62a17ae 224 tmp.addr = p->u.prefix4;
10f9bf3f 225
d62a17ae 226 addr = hash_get(bgp->address_hash, &tmp, bgp_address_hash_alloc);
227 if (!addr)
228 return;
5ce10e92 229
d62a17ae 230 addr->refcnt++;
10f9bf3f
JBD
231}
232
d62a17ae 233static void bgp_address_del(struct bgp *bgp, struct prefix *p)
10f9bf3f 234{
d62a17ae 235 struct bgp_addr tmp;
236 struct bgp_addr *addr;
10f9bf3f 237
d62a17ae 238 tmp.addr = p->u.prefix4;
10f9bf3f 239
d62a17ae 240 addr = hash_lookup(bgp->address_hash, &tmp);
241 /* may have been deleted earlier by bgp_interface_down() */
242 if (addr == NULL)
243 return;
9e47abd8 244
d62a17ae 245 addr->refcnt--;
10f9bf3f 246
d62a17ae 247 if (addr->refcnt == 0) {
248 hash_release(bgp->address_hash, addr);
249 XFREE(MTYPE_BGP_ADDR, addr);
250 }
10f9bf3f
JBD
251}
252
6b0655a2 253
d62a17ae 254struct bgp_connected_ref {
255 unsigned int refcnt;
718e3744 256};
257
d62a17ae 258void bgp_connected_add(struct bgp *bgp, struct connected *ifc)
718e3744 259{
d62a17ae 260 struct prefix p;
261 struct prefix *addr;
262 struct bgp_node *rn;
263 struct bgp_connected_ref *bc;
264 struct listnode *node, *nnode;
265 struct peer *peer;
266
267 addr = ifc->address;
268
269 p = *(CONNECTED_PREFIX(ifc));
270 if (addr->family == AF_INET) {
271 apply_mask_ipv4((struct prefix_ipv4 *)&p);
272
273 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
274 return;
275
276 bgp_address_add(bgp, addr);
277
278 rn = bgp_node_get(bgp->connected_table[AFI_IP],
279 (struct prefix *)&p);
280 if (rn->info) {
281 bc = rn->info;
282 bc->refcnt++;
283 } else {
284 bc = XCALLOC(MTYPE_BGP_CONN,
285 sizeof(struct bgp_connected_ref));
286 bc->refcnt = 1;
287 rn->info = bc;
288 }
8ffedcea 289
d62a17ae 290 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
291 if (peer->conf_if
292 && (strcmp(peer->conf_if, ifc->ifp->name) == 0)
293 && peer->status != Established
294 && !CHECK_FLAG(peer->flags,
295 PEER_FLAG_IFPEER_V6ONLY)) {
296 if (peer_active(peer))
297 BGP_EVENT_ADD(peer, BGP_Stop);
298 BGP_EVENT_ADD(peer, BGP_Start);
299 }
300 }
301 } else if (addr->family == AF_INET6) {
302 apply_mask_ipv6((struct prefix_ipv6 *)&p);
303
304 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
305 return;
306
307 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
308 return;
309
310 rn = bgp_node_get(bgp->connected_table[AFI_IP6],
311 (struct prefix *)&p);
312 if (rn->info) {
313 bc = rn->info;
314 bc->refcnt++;
315 } else {
316 bc = XCALLOC(MTYPE_BGP_CONN,
317 sizeof(struct bgp_connected_ref));
318 bc->refcnt = 1;
319 rn->info = bc;
320 }
718e3744 321 }
718e3744 322}
323
d62a17ae 324void bgp_connected_delete(struct bgp *bgp, struct connected *ifc)
718e3744 325{
d62a17ae 326 struct prefix p;
327 struct prefix *addr;
328 struct bgp_node *rn;
329 struct bgp_connected_ref *bc;
718e3744 330
d62a17ae 331 addr = ifc->address;
718e3744 332
d62a17ae 333 p = *(CONNECTED_PREFIX(ifc));
334 if (addr->family == AF_INET) {
335 apply_mask_ipv4((struct prefix_ipv4 *)&p);
718e3744 336
d62a17ae 337 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
338 return;
718e3744 339
d62a17ae 340 bgp_address_del(bgp, addr);
10f9bf3f 341
d62a17ae 342 rn = bgp_node_lookup(bgp->connected_table[AFI_IP], &p);
343 if (!rn)
344 return;
718e3744 345
d62a17ae 346 bc = rn->info;
347 bc->refcnt--;
348 if (bc->refcnt == 0) {
349 XFREE(MTYPE_BGP_CONN, bc);
350 rn->info = NULL;
351 }
352 bgp_unlock_node(rn);
353 bgp_unlock_node(rn);
354 } else if (addr->family == AF_INET6) {
355 apply_mask_ipv6((struct prefix_ipv6 *)&p);
356
357 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
358 return;
359
360 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
361 return;
362
363 rn = bgp_node_lookup(bgp->connected_table[AFI_IP6],
364 (struct prefix *)&p);
365 if (!rn)
366 return;
367
368 bc = rn->info;
369 bc->refcnt--;
370 if (bc->refcnt == 0) {
371 XFREE(MTYPE_BGP_CONN, bc);
372 rn->info = NULL;
373 }
374 bgp_unlock_node(rn);
375 bgp_unlock_node(rn);
718e3744 376 }
718e3744 377}
378
d62a17ae 379int bgp_nexthop_self(struct bgp *bgp, struct in_addr nh_addr)
718e3744 380{
d62a17ae 381 struct bgp_addr tmp, *addr;
db0e1937 382 struct tip_addr tmp_tip, *tip;
718e3744 383
d62a17ae 384 tmp.addr = nh_addr;
10f9bf3f 385
d62a17ae 386 addr = hash_lookup(bgp->address_hash, &tmp);
387 if (addr)
388 return 1;
718e3744 389
db0e1937
MK
390 tmp_tip.addr = nh_addr;
391 tip = hash_lookup(bgp->tip_hash, &tmp_tip);
392 if (tip)
393 return 1;
394
d62a17ae 395 return 0;
718e3744 396}
6b0655a2 397
d62a17ae 398int bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer)
718e3744 399{
d62a17ae 400 struct bgp_node *rn1;
401 struct bgp_node *rn2;
402 struct prefix p;
403 int ret;
404
405 p.family = AF_INET;
406 p.prefixlen = IPV4_MAX_BITLEN;
407 p.u.prefix4 = nexthop;
408
409 rn1 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
410 if (!rn1)
411 return 0;
412
413 p.family = AF_INET;
414 p.prefixlen = IPV4_MAX_BITLEN;
415 p.u.prefix4 = peer->su.sin.sin_addr;
416
417 rn2 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
418 if (!rn2) {
419 bgp_unlock_node(rn1);
420 return 0;
421 }
718e3744 422
d62a17ae 423 ret = (rn1 == rn2) ? 1 : 0;
718e3744 424
d62a17ae 425 bgp_unlock_node(rn1);
426 bgp_unlock_node(rn2);
718e3744 427
d62a17ae 428 return (ret);
718e3744 429}
430
d62a17ae 431static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail)
fb018d25 432{
d62a17ae 433 struct bgp_node *rn;
434 struct bgp_nexthop_cache *bnc;
435 char buf[PREFIX2STR_BUFFER];
436 struct nexthop *nexthop;
437 time_t tbuf;
438 afi_t afi;
439
440 vty_out(vty, "Current BGP nexthop cache:\n");
441 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
442 if (!bgp->nexthop_cache_table[afi])
443 continue;
444
445 for (rn = bgp_table_top(bgp->nexthop_cache_table[afi]); rn;
446 rn = bgp_route_next(rn)) {
447 if ((bnc = rn->info) != NULL) {
448 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) {
449 vty_out(vty,
450 " %s valid [IGP metric %d], #paths %d\n",
451 inet_ntop(rn->p.family,
452 &rn->p.u.prefix, buf,
453 sizeof(buf)),
454 bnc->metric, bnc->path_count);
455 if (detail)
456 for (nexthop = bnc->nexthop;
457 nexthop;
458 nexthop = nexthop->next)
459 switch (nexthop->type) {
460 case NEXTHOP_TYPE_IPV6:
461 vty_out(vty,
462 " gate %s\n",
463 inet_ntop(
464 AF_INET6,
465 &nexthop->gate
466 .ipv6,
467 buf,
468 sizeof(buf)));
469 break;
470 case NEXTHOP_TYPE_IPV6_IFINDEX:
471 vty_out(vty,
472 " gate %s, if %s\n",
473 inet_ntop(
474 AF_INET6,
475 &nexthop->gate
476 .ipv6,
477 buf,
478 sizeof(buf)),
479 ifindex2ifname(
480 nexthop->ifindex,
481 bgp->vrf_id));
482 break;
483 case NEXTHOP_TYPE_IPV4:
484 vty_out(vty,
485 " gate %s\n",
486 inet_ntop(
487 AF_INET,
488 &nexthop->gate
489 .ipv4,
490 buf,
491 sizeof(buf)));
492 break;
493 case NEXTHOP_TYPE_IFINDEX:
494 vty_out(vty,
495 " if %s\n",
496 ifindex2ifname(
497 nexthop->ifindex,
498 bgp->vrf_id));
499 break;
500 case NEXTHOP_TYPE_IPV4_IFINDEX:
501 vty_out(vty,
502 " gate %s, if %s\n",
503 inet_ntop(
504 AF_INET,
505 &nexthop->gate
506 .ipv4,
507 buf,
508 sizeof(buf)),
509 ifindex2ifname(
510 nexthop->ifindex,
511 bgp->vrf_id));
512 break;
513 default:
514 vty_out(vty,
515 " invalid nexthop type %u\n",
516 nexthop->type);
517 }
518 } else {
519 vty_out(vty, " %s invalid\n",
520 inet_ntop(rn->p.family,
521 &rn->p.u.prefix, buf,
522 sizeof(buf)));
523 if (CHECK_FLAG(bnc->flags,
524 BGP_NEXTHOP_CONNECTED))
525 vty_out(vty,
526 " Must be Connected\n");
527 }
528 tbuf = time(NULL)
529 - (bgp_clock() - bnc->last_update);
530 vty_out(vty, " Last update: %s", ctime(&tbuf));
531 vty_out(vty, "\n");
da11a696
DS
532 }
533 }
fb018d25 534 }
f186de26 535}
536
d62a17ae 537static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name,
538 int detail)
f186de26 539{
d62a17ae 540 struct bgp *bgp;
541
542 if (name)
543 bgp = bgp_lookup_by_name(name);
544 else
545 bgp = bgp_get_default();
546 if (!bgp) {
547 vty_out(vty, "%% No such BGP instance exist\n");
548 return CMD_WARNING;
549 }
f186de26 550
d62a17ae 551 bgp_show_nexthops(vty, bgp, detail);
f186de26 552
d62a17ae 553 return CMD_SUCCESS;
fb018d25
DS
554}
555
d62a17ae 556static void bgp_show_all_instances_nexthops_vty(struct vty *vty)
f186de26 557{
d62a17ae 558 struct listnode *node, *nnode;
559 struct bgp *bgp;
560
561 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
562 vty_out(vty, "\nInstance %s:\n",
563 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
564 ? "Default"
565 : bgp->name);
566 bgp_show_nexthops(vty, bgp, 0);
567 }
f186de26 568}
569
fb018d25
DS
570DEFUN (show_ip_bgp_nexthop,
571 show_ip_bgp_nexthop_cmd,
18c57037 572 "show [ip] bgp [<view|vrf> VIEWVRFNAME] nexthop [detail]",
50ef26d4 573 SHOW_STR
574 IP_STR
575 BGP_STR
8386ac43 576 BGP_INSTANCE_HELP_STR
3a2d747c
QY
577 "BGP nexthop table\n"
578 "Show detailed information\n")
50ef26d4 579{
d62a17ae 580 int idx = 0;
581 char *vrf = argv_find(argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL;
582 int detail = argv_find(argv, argc, "detail", &idx) ? 1 : 0;
583 return show_ip_bgp_nexthop_table(vty, vrf, detail);
50ef26d4 584}
585
f186de26 586DEFUN (show_ip_bgp_instance_all_nexthop,
587 show_ip_bgp_instance_all_nexthop_cmd,
bec37ba5 588 "show [ip] bgp <view|vrf> all nexthop",
f186de26 589 SHOW_STR
590 IP_STR
591 BGP_STR
592 BGP_INSTANCE_ALL_HELP_STR
593 "BGP nexthop table\n")
594{
d62a17ae 595 bgp_show_all_instances_nexthops_vty(vty);
596 return CMD_SUCCESS;
f186de26 597}
598
d62a17ae 599void bgp_scan_init(struct bgp *bgp)
718e3744 600{
d62a17ae 601 afi_t afi;
602
603 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
604 bgp->nexthop_cache_table[afi] =
605 bgp_table_init(afi, SAFI_UNICAST);
606 bgp->connected_table[afi] = bgp_table_init(afi, SAFI_UNICAST);
607 bgp->import_check_table[afi] =
608 bgp_table_init(afi, SAFI_UNICAST);
609 }
fc9a856f
DS
610}
611
d62a17ae 612void bgp_scan_vty_init(void)
fc9a856f 613{
d62a17ae 614 install_element(VIEW_NODE, &show_ip_bgp_nexthop_cmd);
615 install_element(VIEW_NODE, &show_ip_bgp_instance_all_nexthop_cmd);
718e3744 616}
228da428 617
d62a17ae 618void bgp_scan_finish(struct bgp *bgp)
228da428 619{
d62a17ae 620 afi_t afi;
6c88b44d 621
d62a17ae 622 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
623 /* Only the current one needs to be reset. */
624 bgp_nexthop_cache_reset(bgp->nexthop_cache_table[afi]);
625 bgp_table_unlock(bgp->nexthop_cache_table[afi]);
626 bgp->nexthop_cache_table[afi] = NULL;
228da428 627
d62a17ae 628 bgp_table_unlock(bgp->connected_table[afi]);
629 bgp->connected_table[afi] = NULL;
078430f6 630
d62a17ae 631 bgp_table_unlock(bgp->import_check_table[afi]);
632 bgp->import_check_table[afi] = NULL;
633 }
228da428 634}