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