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