]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_nexthop.c
bgpd-interface-ipv4-cmd.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"
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;
211 u_int32_t saddr;
718e3744 212
718e3744 213 addr = ifc->address;
718e3744 214
215 if (addr->family == AF_INET)
216 {
e4529636 217 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
718e3744 218 apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
219
220 if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
221 return;
222
10f9bf3f
JBD
223 bgp_address_add (addr);
224
5932020b 225 rn = bgp_node_get (bgp_connected_table[AFI_IP], (struct prefix *) &p);
718e3744 226 if (rn->info)
227 {
228 bc = rn->info;
229 bc->refcnt++;
230 }
231 else
232 {
6c88b44d 233 bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
718e3744 234 bc->refcnt = 1;
235 rn->info = bc;
236 }
8ffedcea
DS
237
238 for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
239 {
240 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
241 {
242 if (peer->conf_if && (strcmp (peer->conf_if, ifc->ifp->name) == 0) &&
243 !CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
244 {
245 if (peer_active(peer))
246 BGP_EVENT_ADD (peer, BGP_Stop);
247 BGP_EVENT_ADD (peer, BGP_Start);
248 }
249 }
250 }
718e3744 251 }
252#ifdef HAVE_IPV6
e4529636 253 else if (addr->family == AF_INET6)
718e3744 254 {
e4529636 255 PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
718e3744 256 apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
257
258 if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
259 return;
260
261 if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
262 return;
263
5932020b 264 rn = bgp_node_get (bgp_connected_table[AFI_IP6], (struct prefix *) &p);
718e3744 265 if (rn->info)
266 {
267 bc = rn->info;
268 bc->refcnt++;
269 }
270 else
271 {
6c88b44d 272 bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
718e3744 273 bc->refcnt = 1;
274 rn->info = bc;
275 }
276 }
277#endif /* HAVE_IPV6 */
278}
279
280void
281bgp_connected_delete (struct connected *ifc)
282{
283 struct prefix p;
284 struct prefix *addr;
718e3744 285 struct bgp_node *rn;
5932020b 286 struct bgp_connected_ref *bc;
718e3744 287
718e3744 288 addr = ifc->address;
718e3744 289
290 if (addr->family == AF_INET)
291 {
e4529636 292 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
718e3744 293 apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
294
295 if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
296 return;
297
10f9bf3f
JBD
298 bgp_address_del (addr);
299
5932020b 300 rn = bgp_node_lookup (bgp_connected_table[AFI_IP], &p);
718e3744 301 if (! rn)
302 return;
303
304 bc = rn->info;
305 bc->refcnt--;
306 if (bc->refcnt == 0)
307 {
6c88b44d 308 XFREE (MTYPE_BGP_CONN, bc);
718e3744 309 rn->info = NULL;
310 }
311 bgp_unlock_node (rn);
312 bgp_unlock_node (rn);
313 }
314#ifdef HAVE_IPV6
315 else if (addr->family == AF_INET6)
316 {
e4529636 317 PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
718e3744 318 apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
319
320 if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
321 return;
322
323 if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
324 return;
325
5932020b 326 rn = bgp_node_lookup (bgp_connected_table[AFI_IP6], (struct prefix *) &p);
718e3744 327 if (! rn)
328 return;
329
330 bc = rn->info;
331 bc->refcnt--;
332 if (bc->refcnt == 0)
333 {
6c88b44d 334 XFREE (MTYPE_BGP_CONN, bc);
718e3744 335 rn->info = NULL;
336 }
337 bgp_unlock_node (rn);
338 bgp_unlock_node (rn);
339 }
340#endif /* HAVE_IPV6 */
341}
342
343int
10f9bf3f 344bgp_nexthop_self (struct attr *attr)
718e3744 345{
10f9bf3f 346 struct bgp_addr tmp, *addr;
718e3744 347
10f9bf3f
JBD
348 tmp.addr = attr->nexthop;
349
350 addr = hash_lookup (bgp_address_hash, &tmp);
351 if (addr)
352 return 1;
718e3744 353
718e3744 354 return 0;
355}
6b0655a2 356
718e3744 357
718e3744 358int
fc9a856f 359bgp_multiaccess_check_v4 (struct in_addr nexthop, struct peer *peer)
718e3744 360{
361 struct bgp_node *rn1;
362 struct bgp_node *rn2;
fc9a856f 363 struct prefix p;
718e3744 364 int ret;
365
fc9a856f
DS
366 p.family = AF_INET;
367 p.prefixlen = IPV4_MAX_BITLEN;
368 p.u.prefix4 = nexthop;
718e3744 369
fc9a856f
DS
370 rn1 = bgp_node_match (bgp_connected_table[AFI_IP], &p);
371 if (!rn1)
718e3744 372 return 0;
718e3744 373
fc9a856f
DS
374 p.family = AF_INET;
375 p.prefixlen = IPV4_MAX_BITLEN;
376 p.u.prefix4 = peer->su.sin.sin_addr;
718e3744 377
fc9a856f
DS
378 rn2 = bgp_node_match (bgp_connected_table[AFI_IP], &p);
379 if (!rn2)
718e3744 380 {
fc9a856f
DS
381 bgp_unlock_node(rn1);
382 return 0;
718e3744 383 }
384
fc9a856f 385 ret = (rn1 == rn2) ? 1 : 0;
718e3744 386
fc9a856f
DS
387 bgp_unlock_node(rn1);
388 bgp_unlock_node(rn2);
718e3744 389
fc9a856f 390 return (ret);
718e3744 391}
392
fb018d25
DS
393static int
394show_ip_bgp_nexthop_table (struct vty *vty, int detail)
395{
396 struct bgp_node *rn;
397 struct bgp_nexthop_cache *bnc;
398 char buf[INET6_ADDRSTRLEN];
77217fd4 399 struct nexthop *nexthop;
fb018d25 400 time_t tbuf;
fb018d25
DS
401
402 vty_out (vty, "Current BGP nexthop cache:%s", VTY_NEWLINE);
403 for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP]); rn; rn = bgp_route_next (rn))
404 if ((bnc = rn->info) != NULL)
405 {
406 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))
407 {
408 vty_out (vty, " %s valid [IGP metric %d], #paths %d%s",
409 inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN),
410 bnc->metric, bnc->path_count, VTY_NEWLINE);
411 if (detail)
77217fd4
DS
412 for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next)
413 switch (nexthop->type)
414 {
415 case NEXTHOP_TYPE_IPV4:
416 vty_out (vty, " gate %s%s",
417 inet_ntop (AF_INET, &nexthop->gate.ipv4, buf,
418 INET6_ADDRSTRLEN), VTY_NEWLINE);
419 break;
420 case NEXTHOP_TYPE_IFINDEX:
421 vty_out (vty, " if %s%s",
422 ifindex2ifname(nexthop->ifindex), VTY_NEWLINE);
423 break;
424 case NEXTHOP_TYPE_IPV4_IFINDEX:
425 vty_out (vty, " gate %s, if %s%s",
426 inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
427 INET6_ADDRSTRLEN),
428 ifindex2ifname(nexthop->ifindex), VTY_NEWLINE);
429 break;
430 default:
431 vty_out (vty, " invalid nexthop type %u%s",
432 nexthop->type, VTY_NEWLINE);
433 }
fb018d25
DS
434 }
435 else
8d73e1db
DS
436 {
437 vty_out (vty, " %s invalid%s",
438 inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
439
440 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
441 vty_out (vty, " Must be Connected%s", VTY_NEWLINE);
442 }
fb018d25
DS
443#ifdef HAVE_CLOCK_MONOTONIC
444 tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
445 vty_out (vty, " Last update: %s", ctime(&tbuf));
446#else
447 vty_out (vty, " Last update: %s", ctime(&bnc->uptime));
448#endif /* HAVE_CLOCK_MONOTONIC */
449
450 vty_out(vty, "%s", VTY_NEWLINE);
451 }
452
453#ifdef HAVE_IPV6
454 {
455 for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP6]);
456 rn;
457 rn = bgp_route_next (rn))
458 if ((bnc = rn->info) != NULL)
459 {
460 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))
461 {
462 vty_out (vty, " %s valid [IGP metric %d]%s",
463 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf,
464 INET6_ADDRSTRLEN),
465 bnc->metric, VTY_NEWLINE);
466 if (detail)
77217fd4
DS
467 for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next)
468 switch (nexthop->type)
469 {
470 case NEXTHOP_TYPE_IPV6:
471 vty_out (vty, " gate %s%s",
472 inet_ntop (AF_INET6, &nexthop->gate.ipv6,
473 buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
474 break;
475 case NEXTHOP_TYPE_IPV6_IFINDEX:
476 vty_out(vty, " gate %s, if %s%s",
477 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
478 INET6_ADDRSTRLEN),
479 ifindex2ifname(nexthop->ifindex),
480 VTY_NEWLINE);
481 break;
482 case NEXTHOP_TYPE_IFINDEX:
483 vty_out (vty, " ifidx %u%s", nexthop->ifindex,
484 VTY_NEWLINE);
485 break;
486 default:
487 vty_out (vty, " invalid nexthop type %u%s",
488 nexthop->type, VTY_NEWLINE);
489 }
fb018d25
DS
490 }
491 else
8d73e1db
DS
492 {
493 vty_out (vty, " %s invalid%s",
494 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
495 VTY_NEWLINE);
496
497 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
498 vty_out (vty, " Must be Connected%s", VTY_NEWLINE);
499 }
fb018d25
DS
500#ifdef HAVE_CLOCK_MONOTONIC
501 tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
502 vty_out (vty, " Last update: %s", ctime(&tbuf));
503#else
504 vty_out (vty, " Last update: %s", ctime(&bnc->uptime));
505#endif /* HAVE_CLOCK_MONOTONIC */
506
507 vty_out(vty, "%s", VTY_NEWLINE);
508 }
509 }
510#endif /* HAVE_IPV6 */
511 return CMD_SUCCESS;
512}
513
fb018d25
DS
514DEFUN (show_ip_bgp_nexthop,
515 show_ip_bgp_nexthop_cmd,
516 "show ip bgp nexthop",
517 SHOW_STR
518 IP_STR
519 BGP_STR
520 "BGP nexthop table\n")
521{
522 return show_ip_bgp_nexthop_table (vty, 0);
523}
524
525DEFUN (show_ip_bgp_nexthop_detail,
526 show_ip_bgp_nexthop_detail_cmd,
527 "show ip bgp nexthop detail",
528 SHOW_STR
529 IP_STR
530 BGP_STR
531 "BGP nexthop table\n")
532{
533 return show_ip_bgp_nexthop_table (vty, 1);
534}
535
718e3744 536void
66e5cd87 537bgp_scan_init (void)
718e3744 538{
078430f6 539 bgp_nexthop_cache_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
64e580a7 540 bgp_connected_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
078430f6 541 bgp_import_check_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
718e3744 542
543#ifdef HAVE_IPV6
078430f6 544 bgp_nexthop_cache_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
64e580a7 545 bgp_connected_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
078430f6 546 bgp_import_check_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
718e3744 547#endif /* HAVE_IPV6 */
548
fc9a856f
DS
549}
550
551void
ffd0c037 552bgp_scan_vty_init (void)
fc9a856f
DS
553{
554 install_element (ENABLE_NODE, &show_ip_bgp_nexthop_cmd);
fb018d25
DS
555 install_element (VIEW_NODE, &show_ip_bgp_nexthop_cmd);
556 install_element (VIEW_NODE, &show_ip_bgp_nexthop_detail_cmd);
fb018d25 557 install_element (ENABLE_NODE, &show_ip_bgp_nexthop_detail_cmd);
718e3744 558}
228da428
CC
559
560void
561bgp_scan_finish (void)
562{
6c88b44d
CC
563 /* Only the current one needs to be reset. */
564 bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP]);
565
078430f6
DS
566 bgp_table_unlock (bgp_nexthop_cache_table[AFI_IP]);
567 bgp_nexthop_cache_table[AFI_IP] = NULL;
228da428 568
228da428
CC
569 bgp_table_unlock (bgp_connected_table[AFI_IP]);
570 bgp_connected_table[AFI_IP] = NULL;
571
078430f6
DS
572 bgp_table_unlock (bgp_import_check_table[AFI_IP]);
573 bgp_import_check_table[AFI_IP] = NULL;
574
228da428 575#ifdef HAVE_IPV6
6c88b44d
CC
576 /* Only the current one needs to be reset. */
577 bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP6]);
578
078430f6
DS
579 bgp_table_unlock (bgp_nexthop_cache_table[AFI_IP6]);
580 bgp_nexthop_cache_table[AFI_IP6] = NULL;
228da428 581
228da428
CC
582 bgp_table_unlock (bgp_connected_table[AFI_IP6]);
583 bgp_connected_table[AFI_IP6] = NULL;
078430f6
DS
584
585 bgp_table_unlock (bgp_import_check_table[AFI_IP6]);
586 bgp_import_check_table[AFI_IP6] = NULL;
228da428
CC
587#endif /* HAVE_IPV6 */
588}