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