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