]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_nexthop.c
During connection setup, there may be two connections in progress for a BGP
[mirror_frr.git] / bgpd / bgp_nexthop.c
CommitLineData
718e3744 1/* BGP nexthop scan
2 Copyright (C) 2000 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
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"
718e3744 35
36#include "bgpd/bgpd.h"
37#include "bgpd/bgp_table.h"
38#include "bgpd/bgp_route.h"
39#include "bgpd/bgp_attr.h"
40#include "bgpd/bgp_nexthop.h"
fb018d25 41#include "bgpd/bgp_nht.h"
718e3744 42#include "bgpd/bgp_debug.h"
43#include "bgpd/bgp_damp.h"
44#include "zebra/rib.h"
45#include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
46
fb018d25 47
718e3744 48
49/* Route table for next-hop lookup cache. */
fb018d25 50struct bgp_table *bgp_nexthop_cache_table[AFI_MAX];
00d252cb 51static struct bgp_table *cache1_table[AFI_MAX];
718e3744 52
53/* Route table for connected route. */
00d252cb 54static struct bgp_table *bgp_connected_table[AFI_MAX];
718e3744 55
6b0655a2 56
fb018d25
DS
57char *
58bnc_str (struct bgp_nexthop_cache *bnc, char *buf, int size)
59{
60 prefix2str(&(bnc->node->p), buf, size);
61 return buf;
62}
63
fb018d25 64void
718e3744 65bnc_nexthop_free (struct bgp_nexthop_cache *bnc)
66{
67 struct nexthop *nexthop;
68 struct nexthop *next = NULL;
69
70 for (nexthop = bnc->nexthop; nexthop; nexthop = next)
71 {
72 next = nexthop->next;
73 XFREE (MTYPE_NEXTHOP, nexthop);
74 }
75}
76
fb018d25
DS
77struct bgp_nexthop_cache *
78bnc_new ()
718e3744 79{
fb018d25
DS
80 struct bgp_nexthop_cache *bnc;
81
82 bnc = XCALLOC (MTYPE_BGP_NEXTHOP_CACHE, sizeof (struct bgp_nexthop_cache));
83 LIST_INIT(&(bnc->paths));
84 return bnc;
718e3744 85}
86
fb018d25 87void
718e3744 88bnc_free (struct bgp_nexthop_cache *bnc)
89{
90 bnc_nexthop_free (bnc);
91 XFREE (MTYPE_BGP_NEXTHOP_CACHE, bnc);
92}
6b0655a2 93
718e3744 94/* If nexthop exists on connected network return 1. */
95int
8e80bdf2 96bgp_nexthop_onlink (afi_t afi, struct attr *attr)
718e3744 97{
98 struct bgp_node *rn;
fc98d16e 99
718e3744 100 /* Lookup the address is onlink or not. */
101 if (afi == AFI_IP)
102 {
5932020b 103 rn = bgp_node_match_ipv4 (bgp_connected_table[AFI_IP], &attr->nexthop);
718e3744 104 if (rn)
105 {
106 bgp_unlock_node (rn);
107 return 1;
108 }
109 }
110#ifdef HAVE_IPV6
111 else if (afi == AFI_IP6)
112 {
801a9bcc 113 if (attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
718e3744 114 return 1;
801a9bcc 115 else if (attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL)
718e3744 116 {
fb982c25 117 if (IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
718e3744 118 return 1;
119
5932020b 120 rn = bgp_node_match_ipv6 (bgp_connected_table[AFI_IP6],
fb982c25 121 &attr->extra->mp_nexthop_global);
718e3744 122 if (rn)
123 {
124 bgp_unlock_node (rn);
125 return 1;
126 }
127 }
128 }
129#endif /* HAVE_IPV6 */
130 return 0;
131}
132
718e3744 133/* Reset and free all BGP nexthop cache. */
94f2b392 134static void
718e3744 135bgp_nexthop_cache_reset (struct bgp_table *table)
136{
137 struct bgp_node *rn;
138 struct bgp_nexthop_cache *bnc;
139
140 for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
141 if ((bnc = rn->info) != NULL)
142 {
143 bnc_free (bnc);
144 rn->info = NULL;
145 bgp_unlock_node (rn);
146 }
147}
148
10f9bf3f
JBD
149/* BGP own address structure */
150struct bgp_addr
151{
152 struct in_addr addr;
153 int refcnt;
154};
155
156static struct hash *bgp_address_hash;
157
158static void *
159bgp_address_hash_alloc (void *p)
160{
161 struct in_addr *val = p;
162 struct bgp_addr *addr;
163
164 addr = XMALLOC (MTYPE_BGP_ADDR, sizeof (struct bgp_addr));
165 addr->refcnt = 0;
166 addr->addr.s_addr = val->s_addr;
167
168 return addr;
169}
170
171static unsigned int
172bgp_address_hash_key_make (void *p)
173{
174 const struct bgp_addr *addr = p;
175
176 return jhash_1word(addr->addr.s_addr, 0);
177}
178
179static int
180bgp_address_hash_cmp (const void *p1, const void *p2)
181{
182 const struct bgp_addr *addr1 = p1;
183 const struct bgp_addr *addr2 = p2;
184
185 return addr1->addr.s_addr == addr2->addr.s_addr;
186}
187
188void
189bgp_address_init (void)
190{
191 bgp_address_hash = hash_create (bgp_address_hash_key_make,
192 bgp_address_hash_cmp);
193}
194
195static void
196bgp_address_add (struct prefix *p)
197{
198 struct bgp_addr tmp;
199 struct bgp_addr *addr;
200
201 tmp.addr = p->u.prefix4;
202
203 addr = hash_get (bgp_address_hash, &tmp, bgp_address_hash_alloc);
5ce10e92
DS
204 if (!addr)
205 return;
206
10f9bf3f
JBD
207 addr->refcnt++;
208}
209
210static void
211bgp_address_del (struct prefix *p)
212{
213 struct bgp_addr tmp;
214 struct bgp_addr *addr;
215
216 tmp.addr = p->u.prefix4;
217
218 addr = hash_lookup (bgp_address_hash, &tmp);
9e47abd8
RG
219 /* may have been deleted earlier by bgp_interface_down() */
220 if (addr == NULL)
221 return;
222
10f9bf3f
JBD
223 addr->refcnt--;
224
225 if (addr->refcnt == 0)
226 {
227 hash_release (bgp_address_hash, addr);
228 XFREE (MTYPE_BGP_ADDR, addr);
229 }
230}
231
6b0655a2 232
5932020b 233struct bgp_connected_ref
718e3744 234{
235 unsigned int refcnt;
236};
237
238void
239bgp_connected_add (struct connected *ifc)
240{
241 struct prefix p;
242 struct prefix *addr;
718e3744 243 struct interface *ifp;
244 struct bgp_node *rn;
5932020b 245 struct bgp_connected_ref *bc;
718e3744 246
247 ifp = ifc->ifp;
248
249 if (! ifp)
250 return;
251
252 if (if_is_loopback (ifp))
253 return;
254
255 addr = ifc->address;
718e3744 256
257 if (addr->family == AF_INET)
258 {
e4529636 259 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
718e3744 260 apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
261
262 if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
263 return;
264
10f9bf3f
JBD
265 bgp_address_add (addr);
266
5932020b 267 rn = bgp_node_get (bgp_connected_table[AFI_IP], (struct prefix *) &p);
718e3744 268 if (rn->info)
269 {
270 bc = rn->info;
271 bc->refcnt++;
272 }
273 else
274 {
6c88b44d 275 bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
718e3744 276 bc->refcnt = 1;
277 rn->info = bc;
278 }
279 }
280#ifdef HAVE_IPV6
e4529636 281 else if (addr->family == AF_INET6)
718e3744 282 {
e4529636 283 PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
718e3744 284 apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
285
286 if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
287 return;
288
289 if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
290 return;
291
5932020b 292 rn = bgp_node_get (bgp_connected_table[AFI_IP6], (struct prefix *) &p);
718e3744 293 if (rn->info)
294 {
295 bc = rn->info;
296 bc->refcnt++;
297 }
298 else
299 {
6c88b44d 300 bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
718e3744 301 bc->refcnt = 1;
302 rn->info = bc;
303 }
304 }
305#endif /* HAVE_IPV6 */
306}
307
308void
309bgp_connected_delete (struct connected *ifc)
310{
311 struct prefix p;
312 struct prefix *addr;
718e3744 313 struct interface *ifp;
314 struct bgp_node *rn;
5932020b 315 struct bgp_connected_ref *bc;
718e3744 316
317 ifp = ifc->ifp;
318
319 if (if_is_loopback (ifp))
320 return;
321
322 addr = ifc->address;
718e3744 323
324 if (addr->family == AF_INET)
325 {
e4529636 326 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
718e3744 327 apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
328
329 if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
330 return;
331
10f9bf3f
JBD
332 bgp_address_del (addr);
333
5932020b 334 rn = bgp_node_lookup (bgp_connected_table[AFI_IP], &p);
718e3744 335 if (! rn)
336 return;
337
338 bc = rn->info;
339 bc->refcnt--;
340 if (bc->refcnt == 0)
341 {
6c88b44d 342 XFREE (MTYPE_BGP_CONN, bc);
718e3744 343 rn->info = NULL;
344 }
345 bgp_unlock_node (rn);
346 bgp_unlock_node (rn);
347 }
348#ifdef HAVE_IPV6
349 else if (addr->family == AF_INET6)
350 {
e4529636 351 PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
718e3744 352 apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
353
354 if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
355 return;
356
357 if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
358 return;
359
5932020b 360 rn = bgp_node_lookup (bgp_connected_table[AFI_IP6], (struct prefix *) &p);
718e3744 361 if (! rn)
362 return;
363
364 bc = rn->info;
365 bc->refcnt--;
366 if (bc->refcnt == 0)
367 {
6c88b44d 368 XFREE (MTYPE_BGP_CONN, bc);
718e3744 369 rn->info = NULL;
370 }
371 bgp_unlock_node (rn);
372 bgp_unlock_node (rn);
373 }
374#endif /* HAVE_IPV6 */
375}
376
377int
10f9bf3f 378bgp_nexthop_self (struct attr *attr)
718e3744 379{
10f9bf3f 380 struct bgp_addr tmp, *addr;
718e3744 381
10f9bf3f
JBD
382 tmp.addr = attr->nexthop;
383
384 addr = hash_lookup (bgp_address_hash, &tmp);
385 if (addr)
386 return 1;
718e3744 387
718e3744 388 return 0;
389}
6b0655a2 390
718e3744 391
718e3744 392int
fc9a856f 393bgp_multiaccess_check_v4 (struct in_addr nexthop, struct peer *peer)
718e3744 394{
395 struct bgp_node *rn1;
396 struct bgp_node *rn2;
fc9a856f 397 struct prefix p;
718e3744 398 int ret;
399
fc9a856f
DS
400 p.family = AF_INET;
401 p.prefixlen = IPV4_MAX_BITLEN;
402 p.u.prefix4 = nexthop;
718e3744 403
fc9a856f
DS
404 rn1 = bgp_node_match (bgp_connected_table[AFI_IP], &p);
405 if (!rn1)
718e3744 406 return 0;
718e3744 407
fc9a856f
DS
408 p.family = AF_INET;
409 p.prefixlen = IPV4_MAX_BITLEN;
410 p.u.prefix4 = peer->su.sin.sin_addr;
718e3744 411
fc9a856f
DS
412 rn2 = bgp_node_match (bgp_connected_table[AFI_IP], &p);
413 if (!rn2)
718e3744 414 {
fc9a856f
DS
415 bgp_unlock_node(rn1);
416 return 0;
718e3744 417 }
418
fc9a856f 419 ret = (rn1 == rn2) ? 1 : 0;
718e3744 420
fc9a856f
DS
421 bgp_unlock_node(rn1);
422 bgp_unlock_node(rn2);
718e3744 423
fc9a856f 424 return (ret);
718e3744 425}
426
fb018d25
DS
427static int
428show_ip_bgp_nexthop_table (struct vty *vty, int detail)
429{
430 struct bgp_node *rn;
431 struct bgp_nexthop_cache *bnc;
432 char buf[INET6_ADDRSTRLEN];
77217fd4 433 struct nexthop *nexthop;
fb018d25
DS
434 time_t tbuf;
435 u_char i;
436
437 vty_out (vty, "Current BGP nexthop cache:%s", VTY_NEWLINE);
438 for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP]); rn; rn = bgp_route_next (rn))
439 if ((bnc = rn->info) != NULL)
440 {
441 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))
442 {
443 vty_out (vty, " %s valid [IGP metric %d], #paths %d%s",
444 inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN),
445 bnc->metric, bnc->path_count, VTY_NEWLINE);
446 if (detail)
77217fd4
DS
447 for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next)
448 switch (nexthop->type)
449 {
450 case NEXTHOP_TYPE_IPV4:
451 vty_out (vty, " gate %s%s",
452 inet_ntop (AF_INET, &nexthop->gate.ipv4, buf,
453 INET6_ADDRSTRLEN), VTY_NEWLINE);
454 break;
455 case NEXTHOP_TYPE_IFINDEX:
456 vty_out (vty, " if %s%s",
457 ifindex2ifname(nexthop->ifindex), VTY_NEWLINE);
458 break;
459 case NEXTHOP_TYPE_IPV4_IFINDEX:
460 vty_out (vty, " gate %s, if %s%s",
461 inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
462 INET6_ADDRSTRLEN),
463 ifindex2ifname(nexthop->ifindex), VTY_NEWLINE);
464 break;
465 default:
466 vty_out (vty, " invalid nexthop type %u%s",
467 nexthop->type, VTY_NEWLINE);
468 }
fb018d25
DS
469 }
470 else
8d73e1db
DS
471 {
472 vty_out (vty, " %s invalid%s",
473 inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
474
475 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
476 vty_out (vty, " Must be Connected%s", VTY_NEWLINE);
477 }
fb018d25
DS
478#ifdef HAVE_CLOCK_MONOTONIC
479 tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
480 vty_out (vty, " Last update: %s", ctime(&tbuf));
481#else
482 vty_out (vty, " Last update: %s", ctime(&bnc->uptime));
483#endif /* HAVE_CLOCK_MONOTONIC */
484
485 vty_out(vty, "%s", VTY_NEWLINE);
486 }
487
488#ifdef HAVE_IPV6
489 {
490 for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP6]);
491 rn;
492 rn = bgp_route_next (rn))
493 if ((bnc = rn->info) != NULL)
494 {
495 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))
496 {
497 vty_out (vty, " %s valid [IGP metric %d]%s",
498 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf,
499 INET6_ADDRSTRLEN),
500 bnc->metric, VTY_NEWLINE);
501 if (detail)
77217fd4
DS
502 for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next)
503 switch (nexthop->type)
504 {
505 case NEXTHOP_TYPE_IPV6:
506 vty_out (vty, " gate %s%s",
507 inet_ntop (AF_INET6, &nexthop->gate.ipv6,
508 buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
509 break;
510 case NEXTHOP_TYPE_IPV6_IFINDEX:
511 vty_out(vty, " gate %s, if %s%s",
512 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
513 INET6_ADDRSTRLEN),
514 ifindex2ifname(nexthop->ifindex),
515 VTY_NEWLINE);
516 break;
517 case NEXTHOP_TYPE_IFINDEX:
518 vty_out (vty, " ifidx %u%s", nexthop->ifindex,
519 VTY_NEWLINE);
520 break;
521 default:
522 vty_out (vty, " invalid nexthop type %u%s",
523 nexthop->type, VTY_NEWLINE);
524 }
fb018d25
DS
525 }
526 else
8d73e1db
DS
527 {
528 vty_out (vty, " %s invalid%s",
529 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
530 VTY_NEWLINE);
531
532 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
533 vty_out (vty, " Must be Connected%s", VTY_NEWLINE);
534 }
fb018d25
DS
535#ifdef HAVE_CLOCK_MONOTONIC
536 tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
537 vty_out (vty, " Last update: %s", ctime(&tbuf));
538#else
539 vty_out (vty, " Last update: %s", ctime(&bnc->uptime));
540#endif /* HAVE_CLOCK_MONOTONIC */
541
542 vty_out(vty, "%s", VTY_NEWLINE);
543 }
544 }
545#endif /* HAVE_IPV6 */
546 return CMD_SUCCESS;
547}
548
fb018d25
DS
549DEFUN (show_ip_bgp_nexthop,
550 show_ip_bgp_nexthop_cmd,
551 "show ip bgp nexthop",
552 SHOW_STR
553 IP_STR
554 BGP_STR
555 "BGP nexthop table\n")
556{
557 return show_ip_bgp_nexthop_table (vty, 0);
558}
559
560DEFUN (show_ip_bgp_nexthop_detail,
561 show_ip_bgp_nexthop_detail_cmd,
562 "show ip bgp nexthop detail",
563 SHOW_STR
564 IP_STR
565 BGP_STR
566 "BGP nexthop table\n")
567{
568 return show_ip_bgp_nexthop_table (vty, 1);
569}
570
718e3744 571void
66e5cd87 572bgp_scan_init (void)
718e3744 573{
64e580a7 574 cache1_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
5932020b 575 bgp_nexthop_cache_table[AFI_IP] = cache1_table[AFI_IP];
718e3744 576
64e580a7 577 bgp_connected_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
718e3744 578
579#ifdef HAVE_IPV6
64e580a7 580 cache1_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
5932020b 581 bgp_nexthop_cache_table[AFI_IP6] = cache1_table[AFI_IP6];
64e580a7 582 bgp_connected_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
718e3744 583#endif /* HAVE_IPV6 */
584
fc9a856f
DS
585}
586
587void
588bgp_scan_vty_init()
589{
590 install_element (ENABLE_NODE, &show_ip_bgp_nexthop_cmd);
fb018d25
DS
591 install_element (VIEW_NODE, &show_ip_bgp_nexthop_cmd);
592 install_element (VIEW_NODE, &show_ip_bgp_nexthop_detail_cmd);
fb018d25 593 install_element (ENABLE_NODE, &show_ip_bgp_nexthop_detail_cmd);
718e3744 594}
228da428
CC
595
596void
597bgp_scan_finish (void)
598{
6c88b44d
CC
599 /* Only the current one needs to be reset. */
600 bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP]);
601
228da428
CC
602 bgp_table_unlock (cache1_table[AFI_IP]);
603 cache1_table[AFI_IP] = NULL;
604
228da428
CC
605 bgp_table_unlock (bgp_connected_table[AFI_IP]);
606 bgp_connected_table[AFI_IP] = NULL;
607
608#ifdef HAVE_IPV6
6c88b44d
CC
609 /* Only the current one needs to be reset. */
610 bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP6]);
611
228da428
CC
612 bgp_table_unlock (cache1_table[AFI_IP6]);
613 cache1_table[AFI_IP6] = NULL;
614
228da428
CC
615 bgp_table_unlock (bgp_connected_table[AFI_IP6]);
616 bgp_connected_table[AFI_IP6] = NULL;
617#endif /* HAVE_IPV6 */
618}