]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_nexthop.c
lib: allow all characters in WORD tokens
[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"
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
116static unsigned int
117bgp_address_hash_key_make (void *p)
118{
119 const struct bgp_addr *addr = p;
120
121 return jhash_1word(addr->addr.s_addr, 0);
122}
123
124static int
125bgp_address_hash_cmp (const void *p1, const void *p2)
126{
127 const struct bgp_addr *addr1 = p1;
128 const struct bgp_addr *addr2 = p2;
129
130 return addr1->addr.s_addr == addr2->addr.s_addr;
131}
132
133void
6aeb9e78 134bgp_address_init (struct bgp *bgp)
10f9bf3f 135{
6aeb9e78 136 bgp->address_hash = hash_create (bgp_address_hash_key_make,
10f9bf3f
JBD
137 bgp_address_hash_cmp);
138}
139
bb86c601
LB
140void
141bgp_address_destroy (struct bgp *bgp)
142{
005b6bc0
LB
143 if (bgp->address_hash == NULL)
144 return;
bb86c601
LB
145 hash_clean(bgp->address_hash, NULL);
146 hash_free(bgp->address_hash);
147 bgp->address_hash = NULL;
148}
149
10f9bf3f 150static void
6aeb9e78 151bgp_address_add (struct bgp *bgp, struct prefix *p)
10f9bf3f
JBD
152{
153 struct bgp_addr tmp;
154 struct bgp_addr *addr;
155
156 tmp.addr = p->u.prefix4;
157
6aeb9e78 158 addr = hash_get (bgp->address_hash, &tmp, bgp_address_hash_alloc);
5ce10e92
DS
159 if (!addr)
160 return;
161
10f9bf3f
JBD
162 addr->refcnt++;
163}
164
165static void
6aeb9e78 166bgp_address_del (struct bgp *bgp, struct prefix *p)
10f9bf3f
JBD
167{
168 struct bgp_addr tmp;
169 struct bgp_addr *addr;
170
171 tmp.addr = p->u.prefix4;
172
6aeb9e78 173 addr = hash_lookup (bgp->address_hash, &tmp);
9e47abd8
RG
174 /* may have been deleted earlier by bgp_interface_down() */
175 if (addr == NULL)
176 return;
177
10f9bf3f
JBD
178 addr->refcnt--;
179
180 if (addr->refcnt == 0)
181 {
6aeb9e78 182 hash_release (bgp->address_hash, addr);
10f9bf3f
JBD
183 XFREE (MTYPE_BGP_ADDR, addr);
184 }
185}
186
6b0655a2 187
5932020b 188struct bgp_connected_ref
718e3744 189{
190 unsigned int refcnt;
191};
192
193void
6aeb9e78 194bgp_connected_add (struct bgp *bgp, struct connected *ifc)
718e3744 195{
196 struct prefix p;
197 struct prefix *addr;
718e3744 198 struct bgp_node *rn;
5932020b 199 struct bgp_connected_ref *bc;
6aeb9e78 200 struct listnode *node, *nnode;
8ffedcea 201 struct peer *peer;
718e3744 202
718e3744 203 addr = ifc->address;
718e3744 204
4608cb43 205 p = *(CONNECTED_PREFIX(ifc));
718e3744 206 if (addr->family == AF_INET)
207 {
718e3744 208 apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
209
210 if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
211 return;
212
6aeb9e78 213 bgp_address_add (bgp, addr);
10f9bf3f 214
6aeb9e78 215 rn = bgp_node_get (bgp->connected_table[AFI_IP], (struct prefix *) &p);
718e3744 216 if (rn->info)
217 {
218 bc = rn->info;
219 bc->refcnt++;
220 }
221 else
222 {
6c88b44d 223 bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
718e3744 224 bc->refcnt = 1;
225 rn->info = bc;
226 }
8ffedcea 227
6aeb9e78
DS
228 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
229 {
230 if (peer->conf_if && (strcmp (peer->conf_if, ifc->ifp->name) == 0) &&
e5d1e72d 231 peer->status != Established &&
6aeb9e78
DS
232 !CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
233 {
234 if (peer_active(peer))
235 BGP_EVENT_ADD (peer, BGP_Stop);
236 BGP_EVENT_ADD (peer, BGP_Start);
237 }
238 }
718e3744 239 }
240#ifdef HAVE_IPV6
e4529636 241 else if (addr->family == AF_INET6)
718e3744 242 {
718e3744 243 apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
244
245 if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
246 return;
247
248 if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
249 return;
250
6aeb9e78 251 rn = bgp_node_get (bgp->connected_table[AFI_IP6], (struct prefix *) &p);
718e3744 252 if (rn->info)
253 {
254 bc = rn->info;
255 bc->refcnt++;
256 }
257 else
258 {
6c88b44d 259 bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
718e3744 260 bc->refcnt = 1;
261 rn->info = bc;
262 }
263 }
264#endif /* HAVE_IPV6 */
265}
266
267void
6aeb9e78 268bgp_connected_delete (struct bgp *bgp, struct connected *ifc)
718e3744 269{
270 struct prefix p;
271 struct prefix *addr;
718e3744 272 struct bgp_node *rn;
5932020b 273 struct bgp_connected_ref *bc;
718e3744 274
718e3744 275 addr = ifc->address;
718e3744 276
4608cb43 277 p = *(CONNECTED_PREFIX(ifc));
718e3744 278 if (addr->family == AF_INET)
279 {
718e3744 280 apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
281
282 if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
283 return;
284
6aeb9e78 285 bgp_address_del (bgp, addr);
10f9bf3f 286
6aeb9e78 287 rn = bgp_node_lookup (bgp->connected_table[AFI_IP], &p);
718e3744 288 if (! rn)
289 return;
290
291 bc = rn->info;
292 bc->refcnt--;
293 if (bc->refcnt == 0)
294 {
6c88b44d 295 XFREE (MTYPE_BGP_CONN, bc);
718e3744 296 rn->info = NULL;
297 }
298 bgp_unlock_node (rn);
299 bgp_unlock_node (rn);
300 }
301#ifdef HAVE_IPV6
302 else if (addr->family == AF_INET6)
303 {
718e3744 304 apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
305
306 if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
307 return;
308
309 if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
310 return;
311
6aeb9e78 312 rn = bgp_node_lookup (bgp->connected_table[AFI_IP6], (struct prefix *) &p);
718e3744 313 if (! rn)
314 return;
315
316 bc = rn->info;
317 bc->refcnt--;
318 if (bc->refcnt == 0)
319 {
6c88b44d 320 XFREE (MTYPE_BGP_CONN, bc);
718e3744 321 rn->info = NULL;
322 }
323 bgp_unlock_node (rn);
324 bgp_unlock_node (rn);
325 }
326#endif /* HAVE_IPV6 */
327}
328
329int
6aeb9e78 330bgp_nexthop_self (struct bgp *bgp, struct attr *attr)
718e3744 331{
10f9bf3f 332 struct bgp_addr tmp, *addr;
718e3744 333
10f9bf3f
JBD
334 tmp.addr = attr->nexthop;
335
6aeb9e78 336 addr = hash_lookup (bgp->address_hash, &tmp);
10f9bf3f
JBD
337 if (addr)
338 return 1;
718e3744 339
718e3744 340 return 0;
341}
6b0655a2 342
718e3744 343int
fc9a856f 344bgp_multiaccess_check_v4 (struct in_addr nexthop, struct peer *peer)
718e3744 345{
346 struct bgp_node *rn1;
347 struct bgp_node *rn2;
fc9a856f 348 struct prefix p;
718e3744 349 int ret;
350
fc9a856f
DS
351 p.family = AF_INET;
352 p.prefixlen = IPV4_MAX_BITLEN;
353 p.u.prefix4 = nexthop;
718e3744 354
6aeb9e78 355 rn1 = bgp_node_match (peer->bgp->connected_table[AFI_IP], &p);
fc9a856f 356 if (!rn1)
718e3744 357 return 0;
718e3744 358
fc9a856f
DS
359 p.family = AF_INET;
360 p.prefixlen = IPV4_MAX_BITLEN;
361 p.u.prefix4 = peer->su.sin.sin_addr;
718e3744 362
6aeb9e78 363 rn2 = bgp_node_match (peer->bgp->connected_table[AFI_IP], &p);
fc9a856f 364 if (!rn2)
718e3744 365 {
fc9a856f
DS
366 bgp_unlock_node(rn1);
367 return 0;
718e3744 368 }
369
fc9a856f 370 ret = (rn1 == rn2) ? 1 : 0;
718e3744 371
fc9a856f
DS
372 bgp_unlock_node(rn1);
373 bgp_unlock_node(rn2);
718e3744 374
fc9a856f 375 return (ret);
718e3744 376}
377
f186de26 378static void
379bgp_show_nexthops (struct vty *vty, struct bgp *bgp, int detail)
fb018d25
DS
380{
381 struct bgp_node *rn;
382 struct bgp_nexthop_cache *bnc;
da11a696 383 char buf[PREFIX2STR_BUFFER];
77217fd4 384 struct nexthop *nexthop;
fb018d25 385 time_t tbuf;
da11a696 386 afi_t afi;
fb018d25
DS
387
388 vty_out (vty, "Current BGP nexthop cache:%s", VTY_NEWLINE);
da11a696
DS
389 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
390 {
5f753f56
PJ
391 if (!bgp->nexthop_cache_table[afi])
392 continue;
393
6aeb9e78 394 for (rn = bgp_table_top (bgp->nexthop_cache_table[afi]); rn; rn = bgp_route_next (rn))
fb018d25 395 {
da11a696
DS
396 if ((bnc = rn->info) != NULL)
397 {
398 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))
77217fd4 399 {
da11a696
DS
400 vty_out (vty, " %s valid [IGP metric %d], #paths %d%s",
401 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, sizeof (buf)),
402 bnc->metric, bnc->path_count, VTY_NEWLINE);
403 if (detail)
404 for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next)
405 switch (nexthop->type)
406 {
407 case NEXTHOP_TYPE_IPV6:
408 vty_out (vty, " gate %s%s",
409 inet_ntop (AF_INET6, &nexthop->gate.ipv6,
410 buf, sizeof (buf)), VTY_NEWLINE);
411 break;
412 case NEXTHOP_TYPE_IPV6_IFINDEX:
413 vty_out(vty, " gate %s, if %s%s",
414 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
415 sizeof (buf)),
416 ifindex2ifname(nexthop->ifindex),
417 VTY_NEWLINE);
418 break;
419 case NEXTHOP_TYPE_IPV4:
420 vty_out (vty, " gate %s%s",
421 inet_ntop (AF_INET, &nexthop->gate.ipv4, buf,
422 sizeof (buf)), VTY_NEWLINE);
423 break;
424 case NEXTHOP_TYPE_IFINDEX:
425 vty_out (vty, " if %s%s",
426 ifindex2ifname(nexthop->ifindex), VTY_NEWLINE);
427 break;
428 case NEXTHOP_TYPE_IPV4_IFINDEX:
429 vty_out (vty, " gate %s, if %s%s",
430 inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
431 sizeof (buf)),
432 ifindex2ifname(nexthop->ifindex), VTY_NEWLINE);
433 break;
434 default:
435 vty_out (vty, " invalid nexthop type %u%s",
436 nexthop->type, VTY_NEWLINE);
437 }
438 }
439 else
440 {
441 vty_out (vty, " %s invalid%s",
442 inet_ntop (rn->p.family, &rn->p.u.prefix,
443 buf, sizeof (buf)), VTY_NEWLINE);
444 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
445 vty_out (vty, " Must be Connected%s", VTY_NEWLINE);
77217fd4 446 }
fb018d25 447#ifdef HAVE_CLOCK_MONOTONIC
da11a696
DS
448 tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
449 vty_out (vty, " Last update: %s", ctime(&tbuf));
fb018d25 450#else
da11a696 451 vty_out (vty, " Last update: %s", ctime(&bnc->uptime));
fb018d25 452#endif /* HAVE_CLOCK_MONOTONIC */
da11a696
DS
453 vty_out(vty, "%s", VTY_NEWLINE);
454 }
fb018d25 455 }
da11a696 456 }
f186de26 457}
458
459static int
460show_ip_bgp_nexthop_table (struct vty *vty, const char *name, int detail)
461{
462 struct bgp *bgp;
463
464 if (name)
465 bgp = bgp_lookup_by_name (name);
466 else
467 bgp = bgp_get_default ();
468 if (!bgp)
469 {
470 vty_out (vty, "%% No such BGP instance exist%s", VTY_NEWLINE);
471 return CMD_WARNING;
472 }
473
474 bgp_show_nexthops (vty, bgp, detail);
475
fb018d25
DS
476 return CMD_SUCCESS;
477}
478
f186de26 479static void
480bgp_show_all_instances_nexthops_vty (struct vty *vty)
481{
482 struct listnode *node, *nnode;
483 struct bgp *bgp;
484
485 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
486 {
487 vty_out (vty, "%sInstance %s:%s",
488 VTY_NEWLINE,
489 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) ? "Default" : bgp->name,
490 VTY_NEWLINE);
491 bgp_show_nexthops (vty, bgp, 0);
492 }
493}
494
fb018d25
DS
495DEFUN (show_ip_bgp_nexthop,
496 show_ip_bgp_nexthop_cmd,
bec37ba5 497 "show [ip] bgp [<view|vrf> VRFNAME] nexthop [detail]",
50ef26d4 498 SHOW_STR
499 IP_STR
500 BGP_STR
8386ac43 501 BGP_INSTANCE_HELP_STR
50ef26d4 502 "BGP nexthop table\n")
503{
bec37ba5
QY
504 int idx = 0;
505 char *vrf = argv_find (argv, argc, "VRFNAME", &idx) ? argv[idx]->arg : NULL;
506 int detail = argv_find (argv, argc, "detail", &idx) ? 1 : 0;
507 return show_ip_bgp_nexthop_table (vty, vrf, detail);
50ef26d4 508}
509
f186de26 510DEFUN (show_ip_bgp_instance_all_nexthop,
511 show_ip_bgp_instance_all_nexthop_cmd,
bec37ba5 512 "show [ip] bgp <view|vrf> all nexthop",
f186de26 513 SHOW_STR
514 IP_STR
515 BGP_STR
516 BGP_INSTANCE_ALL_HELP_STR
517 "BGP nexthop table\n")
518{
519 bgp_show_all_instances_nexthops_vty (vty);
520 return CMD_SUCCESS;
521}
522
718e3744 523void
6aeb9e78 524bgp_scan_init (struct bgp *bgp)
718e3744 525{
6aeb9e78
DS
526 bgp->nexthop_cache_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
527 bgp->connected_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
528 bgp->import_check_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
718e3744 529
6aeb9e78
DS
530 bgp->nexthop_cache_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
531 bgp->connected_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
532 bgp->import_check_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
718e3744 533
0adfc788
DS
534 bgp->nexthop_cache_table[AFI_ETHER] = bgp_table_init (AFI_ETHER, SAFI_UNICAST);
535 bgp->connected_table[AFI_ETHER] = bgp_table_init (AFI_ETHER, SAFI_UNICAST);
536 bgp->import_check_table[AFI_ETHER] = bgp_table_init (AFI_ETHER, SAFI_UNICAST);
fc9a856f
DS
537}
538
539void
ffd0c037 540bgp_scan_vty_init (void)
fc9a856f 541{
fb018d25 542 install_element (VIEW_NODE, &show_ip_bgp_nexthop_cmd);
f186de26 543 install_element (VIEW_NODE, &show_ip_bgp_instance_all_nexthop_cmd);
718e3744 544}
228da428
CC
545
546void
6aeb9e78 547bgp_scan_finish (struct bgp *bgp)
228da428 548{
6c88b44d 549 /* Only the current one needs to be reset. */
6aeb9e78 550 bgp_nexthop_cache_reset (bgp->nexthop_cache_table[AFI_IP]);
6c88b44d 551
6aeb9e78
DS
552 bgp_table_unlock (bgp->nexthop_cache_table[AFI_IP]);
553 bgp->nexthop_cache_table[AFI_IP] = NULL;
228da428 554
6aeb9e78
DS
555 bgp_table_unlock (bgp->connected_table[AFI_IP]);
556 bgp->connected_table[AFI_IP] = NULL;
228da428 557
6aeb9e78
DS
558 bgp_table_unlock (bgp->import_check_table[AFI_IP]);
559 bgp->import_check_table[AFI_IP] = NULL;
078430f6 560
228da428 561#ifdef HAVE_IPV6
6c88b44d 562 /* Only the current one needs to be reset. */
6aeb9e78 563 bgp_nexthop_cache_reset (bgp->nexthop_cache_table[AFI_IP6]);
6c88b44d 564
6aeb9e78
DS
565 bgp_table_unlock (bgp->nexthop_cache_table[AFI_IP6]);
566 bgp->nexthop_cache_table[AFI_IP6] = NULL;
228da428 567
6aeb9e78
DS
568 bgp_table_unlock (bgp->connected_table[AFI_IP6]);
569 bgp->connected_table[AFI_IP6] = NULL;
078430f6 570
6aeb9e78
DS
571 bgp_table_unlock (bgp->import_check_table[AFI_IP6]);
572 bgp->import_check_table[AFI_IP6] = NULL;
228da428
CC
573#endif /* HAVE_IPV6 */
574}