]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_nexthop.c
*: Add vrf autocompletion for commands
[mirror_frr.git] / bgpd / bgp_nexthop.c
CommitLineData
718e3744 1/* BGP nexthop scan
896014f4
DL
2 * Copyright (C) 2000 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
718e3744 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"
039f3a34 35#include "filter.h"
718e3744 36
37#include "bgpd/bgpd.h"
38#include "bgpd/bgp_table.h"
39#include "bgpd/bgp_route.h"
40#include "bgpd/bgp_attr.h"
41#include "bgpd/bgp_nexthop.h"
fb018d25 42#include "bgpd/bgp_nht.h"
718e3744 43#include "bgpd/bgp_debug.h"
44#include "bgpd/bgp_damp.h"
8ffedcea 45#include "bgpd/bgp_fsm.h"
8386ac43 46#include "bgpd/bgp_vty.h"
718e3744 47#include "zebra/rib.h"
48#include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
49
fb018d25
DS
50char *
51bnc_str (struct bgp_nexthop_cache *bnc, char *buf, int size)
52{
53 prefix2str(&(bnc->node->p), buf, size);
54 return buf;
55}
56
fb018d25 57void
718e3744 58bnc_nexthop_free (struct bgp_nexthop_cache *bnc)
59{
4a1ab8e4 60 nexthops_free(bnc->nexthop);
718e3744 61}
62
fb018d25 63struct bgp_nexthop_cache *
ffd0c037 64bnc_new (void)
718e3744 65{
fb018d25
DS
66 struct bgp_nexthop_cache *bnc;
67
68 bnc = XCALLOC (MTYPE_BGP_NEXTHOP_CACHE, sizeof (struct bgp_nexthop_cache));
69 LIST_INIT(&(bnc->paths));
70 return bnc;
718e3744 71}
72
fb018d25 73void
718e3744 74bnc_free (struct bgp_nexthop_cache *bnc)
75{
76 bnc_nexthop_free (bnc);
77 XFREE (MTYPE_BGP_NEXTHOP_CACHE, bnc);
78}
6b0655a2 79
718e3744 80/* Reset and free all BGP nexthop cache. */
94f2b392 81static void
718e3744 82bgp_nexthop_cache_reset (struct bgp_table *table)
83{
84 struct bgp_node *rn;
85 struct bgp_nexthop_cache *bnc;
86
87 for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
88 if ((bnc = rn->info) != NULL)
89 {
90 bnc_free (bnc);
91 rn->info = NULL;
92 bgp_unlock_node (rn);
93 }
94}
95
10f9bf3f
JBD
96/* BGP own address structure */
97struct bgp_addr
98{
99 struct in_addr addr;
100 int refcnt;
101};
102
10f9bf3f
JBD
103static void *
104bgp_address_hash_alloc (void *p)
105{
ffd0c037 106 const struct in_addr *val = (const struct in_addr *)p;
10f9bf3f
JBD
107 struct bgp_addr *addr;
108
109 addr = XMALLOC (MTYPE_BGP_ADDR, sizeof (struct bgp_addr));
110 addr->refcnt = 0;
111 addr->addr.s_addr = val->s_addr;
112
113 return addr;
114}
115
37d361e7
RW
116static void
117bgp_address_hash_free (void *addr)
118{
119 XFREE (MTYPE_BGP_ADDR, addr);
120}
121
10f9bf3f
JBD
122static unsigned int
123bgp_address_hash_key_make (void *p)
124{
125 const struct bgp_addr *addr = p;
126
127 return jhash_1word(addr->addr.s_addr, 0);
128}
129
130static int
131bgp_address_hash_cmp (const void *p1, const void *p2)
132{
133 const struct bgp_addr *addr1 = p1;
134 const struct bgp_addr *addr2 = p2;
135
136 return addr1->addr.s_addr == addr2->addr.s_addr;
137}
138
139void
6aeb9e78 140bgp_address_init (struct bgp *bgp)
10f9bf3f 141{
6aeb9e78 142 bgp->address_hash = hash_create (bgp_address_hash_key_make,
10f9bf3f
JBD
143 bgp_address_hash_cmp);
144}
145
bb86c601
LB
146void
147bgp_address_destroy (struct bgp *bgp)
148{
005b6bc0
LB
149 if (bgp->address_hash == NULL)
150 return;
37d361e7 151 hash_clean(bgp->address_hash, bgp_address_hash_free);
bb86c601
LB
152 hash_free(bgp->address_hash);
153 bgp->address_hash = NULL;
154}
155
10f9bf3f 156static void
6aeb9e78 157bgp_address_add (struct bgp *bgp, struct prefix *p)
10f9bf3f
JBD
158{
159 struct bgp_addr tmp;
160 struct bgp_addr *addr;
161
162 tmp.addr = p->u.prefix4;
163
6aeb9e78 164 addr = hash_get (bgp->address_hash, &tmp, bgp_address_hash_alloc);
5ce10e92
DS
165 if (!addr)
166 return;
167
10f9bf3f
JBD
168 addr->refcnt++;
169}
170
171static void
6aeb9e78 172bgp_address_del (struct bgp *bgp, struct prefix *p)
10f9bf3f
JBD
173{
174 struct bgp_addr tmp;
175 struct bgp_addr *addr;
176
177 tmp.addr = p->u.prefix4;
178
6aeb9e78 179 addr = hash_lookup (bgp->address_hash, &tmp);
9e47abd8
RG
180 /* may have been deleted earlier by bgp_interface_down() */
181 if (addr == NULL)
182 return;
183
10f9bf3f
JBD
184 addr->refcnt--;
185
186 if (addr->refcnt == 0)
187 {
6aeb9e78 188 hash_release (bgp->address_hash, addr);
10f9bf3f
JBD
189 XFREE (MTYPE_BGP_ADDR, addr);
190 }
191}
192
6b0655a2 193
5932020b 194struct bgp_connected_ref
718e3744 195{
196 unsigned int refcnt;
197};
198
199void
6aeb9e78 200bgp_connected_add (struct bgp *bgp, struct connected *ifc)
718e3744 201{
202 struct prefix p;
203 struct prefix *addr;
718e3744 204 struct bgp_node *rn;
5932020b 205 struct bgp_connected_ref *bc;
6aeb9e78 206 struct listnode *node, *nnode;
8ffedcea 207 struct peer *peer;
718e3744 208
718e3744 209 addr = ifc->address;
718e3744 210
4608cb43 211 p = *(CONNECTED_PREFIX(ifc));
718e3744 212 if (addr->family == AF_INET)
213 {
718e3744 214 apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
215
216 if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
217 return;
218
6aeb9e78 219 bgp_address_add (bgp, addr);
10f9bf3f 220
6aeb9e78 221 rn = bgp_node_get (bgp->connected_table[AFI_IP], (struct prefix *) &p);
718e3744 222 if (rn->info)
223 {
224 bc = rn->info;
225 bc->refcnt++;
226 }
227 else
228 {
6c88b44d 229 bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
718e3744 230 bc->refcnt = 1;
231 rn->info = bc;
232 }
8ffedcea 233
6aeb9e78
DS
234 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
235 {
236 if (peer->conf_if && (strcmp (peer->conf_if, ifc->ifp->name) == 0) &&
e5d1e72d 237 peer->status != Established &&
6aeb9e78
DS
238 !CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
239 {
240 if (peer_active(peer))
241 BGP_EVENT_ADD (peer, BGP_Stop);
242 BGP_EVENT_ADD (peer, BGP_Start);
243 }
244 }
718e3744 245 }
e4529636 246 else if (addr->family == AF_INET6)
718e3744 247 {
718e3744 248 apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
249
250 if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
251 return;
252
253 if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
254 return;
255
6aeb9e78 256 rn = bgp_node_get (bgp->connected_table[AFI_IP6], (struct prefix *) &p);
718e3744 257 if (rn->info)
258 {
259 bc = rn->info;
260 bc->refcnt++;
261 }
262 else
263 {
6c88b44d 264 bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
718e3744 265 bc->refcnt = 1;
266 rn->info = bc;
267 }
268 }
718e3744 269}
270
271void
6aeb9e78 272bgp_connected_delete (struct bgp *bgp, struct connected *ifc)
718e3744 273{
274 struct prefix p;
275 struct prefix *addr;
718e3744 276 struct bgp_node *rn;
5932020b 277 struct bgp_connected_ref *bc;
718e3744 278
718e3744 279 addr = ifc->address;
718e3744 280
4608cb43 281 p = *(CONNECTED_PREFIX(ifc));
718e3744 282 if (addr->family == AF_INET)
283 {
718e3744 284 apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
285
286 if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
287 return;
288
6aeb9e78 289 bgp_address_del (bgp, addr);
10f9bf3f 290
6aeb9e78 291 rn = bgp_node_lookup (bgp->connected_table[AFI_IP], &p);
718e3744 292 if (! rn)
293 return;
294
295 bc = rn->info;
296 bc->refcnt--;
297 if (bc->refcnt == 0)
298 {
6c88b44d 299 XFREE (MTYPE_BGP_CONN, bc);
718e3744 300 rn->info = NULL;
301 }
302 bgp_unlock_node (rn);
303 bgp_unlock_node (rn);
304 }
718e3744 305 else if (addr->family == AF_INET6)
306 {
718e3744 307 apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
308
309 if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
310 return;
311
312 if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
313 return;
314
6aeb9e78 315 rn = bgp_node_lookup (bgp->connected_table[AFI_IP6], (struct prefix *) &p);
718e3744 316 if (! rn)
317 return;
318
319 bc = rn->info;
320 bc->refcnt--;
321 if (bc->refcnt == 0)
322 {
6c88b44d 323 XFREE (MTYPE_BGP_CONN, bc);
718e3744 324 rn->info = NULL;
325 }
326 bgp_unlock_node (rn);
327 bgp_unlock_node (rn);
328 }
718e3744 329}
330
331int
6aeb9e78 332bgp_nexthop_self (struct bgp *bgp, struct attr *attr)
718e3744 333{
10f9bf3f 334 struct bgp_addr tmp, *addr;
718e3744 335
10f9bf3f
JBD
336 tmp.addr = attr->nexthop;
337
6aeb9e78 338 addr = hash_lookup (bgp->address_hash, &tmp);
10f9bf3f
JBD
339 if (addr)
340 return 1;
718e3744 341
718e3744 342 return 0;
343}
6b0655a2 344
718e3744 345int
fc9a856f 346bgp_multiaccess_check_v4 (struct in_addr nexthop, struct peer *peer)
718e3744 347{
348 struct bgp_node *rn1;
349 struct bgp_node *rn2;
fc9a856f 350 struct prefix p;
718e3744 351 int ret;
352
fc9a856f
DS
353 p.family = AF_INET;
354 p.prefixlen = IPV4_MAX_BITLEN;
355 p.u.prefix4 = nexthop;
718e3744 356
6aeb9e78 357 rn1 = bgp_node_match (peer->bgp->connected_table[AFI_IP], &p);
fc9a856f 358 if (!rn1)
718e3744 359 return 0;
718e3744 360
fc9a856f
DS
361 p.family = AF_INET;
362 p.prefixlen = IPV4_MAX_BITLEN;
363 p.u.prefix4 = peer->su.sin.sin_addr;
718e3744 364
6aeb9e78 365 rn2 = bgp_node_match (peer->bgp->connected_table[AFI_IP], &p);
fc9a856f 366 if (!rn2)
718e3744 367 {
fc9a856f
DS
368 bgp_unlock_node(rn1);
369 return 0;
718e3744 370 }
371
fc9a856f 372 ret = (rn1 == rn2) ? 1 : 0;
718e3744 373
fc9a856f
DS
374 bgp_unlock_node(rn1);
375 bgp_unlock_node(rn2);
718e3744 376
fc9a856f 377 return (ret);
718e3744 378}
379
f186de26 380static void
381bgp_show_nexthops (struct vty *vty, struct bgp *bgp, int detail)
fb018d25
DS
382{
383 struct bgp_node *rn;
384 struct bgp_nexthop_cache *bnc;
da11a696 385 char buf[PREFIX2STR_BUFFER];
77217fd4 386 struct nexthop *nexthop;
fb018d25 387 time_t tbuf;
da11a696 388 afi_t afi;
fb018d25
DS
389
390 vty_out (vty, "Current BGP nexthop cache:%s", VTY_NEWLINE);
da11a696
DS
391 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
392 {
5f753f56
PJ
393 if (!bgp->nexthop_cache_table[afi])
394 continue;
395
6aeb9e78 396 for (rn = bgp_table_top (bgp->nexthop_cache_table[afi]); rn; rn = bgp_route_next (rn))
fb018d25 397 {
da11a696
DS
398 if ((bnc = rn->info) != NULL)
399 {
400 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))
77217fd4 401 {
da11a696
DS
402 vty_out (vty, " %s valid [IGP metric %d], #paths %d%s",
403 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, sizeof (buf)),
404 bnc->metric, bnc->path_count, VTY_NEWLINE);
405 if (detail)
406 for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next)
407 switch (nexthop->type)
408 {
409 case NEXTHOP_TYPE_IPV6:
410 vty_out (vty, " gate %s%s",
411 inet_ntop (AF_INET6, &nexthop->gate.ipv6,
412 buf, sizeof (buf)), VTY_NEWLINE);
413 break;
414 case NEXTHOP_TYPE_IPV6_IFINDEX:
415 vty_out(vty, " gate %s, if %s%s",
416 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
417 sizeof (buf)),
631eb2fa 418 ifindex2ifname(nexthop->ifindex, bgp->vrf_id),
da11a696
DS
419 VTY_NEWLINE);
420 break;
421 case NEXTHOP_TYPE_IPV4:
422 vty_out (vty, " gate %s%s",
423 inet_ntop (AF_INET, &nexthop->gate.ipv4, buf,
424 sizeof (buf)), VTY_NEWLINE);
425 break;
426 case NEXTHOP_TYPE_IFINDEX:
427 vty_out (vty, " if %s%s",
631eb2fa 428 ifindex2ifname(nexthop->ifindex, bgp->vrf_id), VTY_NEWLINE);
da11a696
DS
429 break;
430 case NEXTHOP_TYPE_IPV4_IFINDEX:
431 vty_out (vty, " gate %s, if %s%s",
432 inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
433 sizeof (buf)),
631eb2fa 434 ifindex2ifname(nexthop->ifindex, bgp->vrf_id), VTY_NEWLINE);
da11a696
DS
435 break;
436 default:
437 vty_out (vty, " invalid nexthop type %u%s",
438 nexthop->type, VTY_NEWLINE);
439 }
440 }
441 else
442 {
443 vty_out (vty, " %s invalid%s",
444 inet_ntop (rn->p.family, &rn->p.u.prefix,
445 buf, sizeof (buf)), VTY_NEWLINE);
446 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
447 vty_out (vty, " Must be Connected%s", VTY_NEWLINE);
77217fd4 448 }
da11a696
DS
449 tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
450 vty_out (vty, " Last update: %s", ctime(&tbuf));
da11a696
DS
451 vty_out(vty, "%s", VTY_NEWLINE);
452 }
fb018d25 453 }
da11a696 454 }
f186de26 455}
456
457static int
458show_ip_bgp_nexthop_table (struct vty *vty, const char *name, int detail)
459{
460 struct bgp *bgp;
461
462 if (name)
463 bgp = bgp_lookup_by_name (name);
464 else
465 bgp = bgp_get_default ();
466 if (!bgp)
467 {
468 vty_out (vty, "%% No such BGP instance exist%s", VTY_NEWLINE);
469 return CMD_WARNING;
470 }
471
472 bgp_show_nexthops (vty, bgp, detail);
473
fb018d25
DS
474 return CMD_SUCCESS;
475}
476
f186de26 477static void
478bgp_show_all_instances_nexthops_vty (struct vty *vty)
479{
480 struct listnode *node, *nnode;
481 struct bgp *bgp;
482
483 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
484 {
485 vty_out (vty, "%sInstance %s:%s",
486 VTY_NEWLINE,
487 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) ? "Default" : bgp->name,
488 VTY_NEWLINE);
489 bgp_show_nexthops (vty, bgp, 0);
490 }
491}
492
fb018d25
DS
493DEFUN (show_ip_bgp_nexthop,
494 show_ip_bgp_nexthop_cmd,
f2a8972b 495 "show [ip] bgp [<view|vrf> WORD] nexthop [detail]",
50ef26d4 496 SHOW_STR
497 IP_STR
498 BGP_STR
8386ac43 499 BGP_INSTANCE_HELP_STR
3a2d747c
QY
500 "BGP nexthop table\n"
501 "Show detailed information\n")
50ef26d4 502{
bec37ba5 503 int idx = 0;
f2a8972b 504 char *vrf = argv_find (argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL;
bec37ba5
QY
505 int detail = argv_find (argv, argc, "detail", &idx) ? 1 : 0;
506 return show_ip_bgp_nexthop_table (vty, vrf, detail);
50ef26d4 507}
508
f186de26 509DEFUN (show_ip_bgp_instance_all_nexthop,
510 show_ip_bgp_instance_all_nexthop_cmd,
bec37ba5 511 "show [ip] bgp <view|vrf> all nexthop",
f186de26 512 SHOW_STR
513 IP_STR
514 BGP_STR
515 BGP_INSTANCE_ALL_HELP_STR
516 "BGP nexthop table\n")
517{
518 bgp_show_all_instances_nexthops_vty (vty);
519 return CMD_SUCCESS;
520}
521
718e3744 522void
6aeb9e78 523bgp_scan_init (struct bgp *bgp)
718e3744 524{
46e6bac7 525 afi_t afi;
718e3744 526
46e6bac7
RW
527 for (afi = AFI_IP; afi < AFI_MAX; afi++)
528 {
529 bgp->nexthop_cache_table[afi] = bgp_table_init (afi, SAFI_UNICAST);
530 bgp->connected_table[afi] = bgp_table_init (afi, SAFI_UNICAST);
531 bgp->import_check_table[afi] = bgp_table_init (afi, SAFI_UNICAST);
532 }
fc9a856f
DS
533}
534
535void
ffd0c037 536bgp_scan_vty_init (void)
fc9a856f 537{
fb018d25 538 install_element (VIEW_NODE, &show_ip_bgp_nexthop_cmd);
f186de26 539 install_element (VIEW_NODE, &show_ip_bgp_instance_all_nexthop_cmd);
718e3744 540}
228da428
CC
541
542void
6aeb9e78 543bgp_scan_finish (struct bgp *bgp)
228da428 544{
46e6bac7 545 afi_t afi;
6c88b44d 546
46e6bac7
RW
547 for (afi = AFI_IP; afi < AFI_MAX; afi++)
548 {
549 /* Only the current one needs to be reset. */
550 bgp_nexthop_cache_reset (bgp->nexthop_cache_table[afi]);
551 bgp_table_unlock (bgp->nexthop_cache_table[afi]);
552 bgp->nexthop_cache_table[afi] = NULL;
228da428 553
46e6bac7
RW
554 bgp_table_unlock (bgp->connected_table[afi]);
555 bgp->connected_table[afi] = NULL;
078430f6 556
46e6bac7
RW
557 bgp_table_unlock (bgp->import_check_table[afi]);
558 bgp->import_check_table[afi] = NULL;
559 }
228da428 560}