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