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