]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_nexthop.c
The peer-groups parser is missing advertisement-interval and 'timers connect'
[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"
718e3744 34
35#include "bgpd/bgpd.h"
36#include "bgpd/bgp_table.h"
37#include "bgpd/bgp_route.h"
38#include "bgpd/bgp_attr.h"
39#include "bgpd/bgp_nexthop.h"
fb018d25 40#include "bgpd/bgp_nht.h"
718e3744 41#include "bgpd/bgp_debug.h"
42#include "bgpd/bgp_damp.h"
43#include "zebra/rib.h"
44#include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
45
fb018d25
DS
46extern struct zclient *zclient;
47
718e3744 48struct bgp_nexthop_cache *zlookup_query (struct in_addr);
49#ifdef HAVE_IPV6
50struct bgp_nexthop_cache *zlookup_query_ipv6 (struct in6_addr *);
51#endif /* HAVE_IPV6 */
6b0655a2 52
718e3744 53/* Only one BGP scan thread are activated at the same time. */
00d252cb 54static struct thread *bgp_scan_thread = NULL;
718e3744 55
56/* BGP import thread */
00d252cb 57static struct thread *bgp_import_thread = NULL;
718e3744 58
59/* BGP scan interval. */
00d252cb 60static int bgp_scan_interval;
718e3744 61
62/* BGP import interval. */
00d252cb 63static int bgp_import_interval;
718e3744 64
65/* Route table for next-hop lookup cache. */
fb018d25 66struct bgp_table *bgp_nexthop_cache_table[AFI_MAX];
00d252cb 67static struct bgp_table *cache1_table[AFI_MAX];
68static struct bgp_table *cache2_table[AFI_MAX];
718e3744 69
70/* Route table for connected route. */
00d252cb 71static struct bgp_table *bgp_connected_table[AFI_MAX];
718e3744 72
73/* BGP nexthop lookup query client. */
228da428 74struct zclient *zlookup = NULL;
6b0655a2 75
fb018d25
DS
76char *
77bnc_str (struct bgp_nexthop_cache *bnc, char *buf, int size)
78{
79 prefix2str(&(bnc->node->p), buf, size);
80 return buf;
81}
82
718e3744 83/* Add nexthop to the end of the list. */
94f2b392 84static void
718e3744 85bnc_nexthop_add (struct bgp_nexthop_cache *bnc, struct nexthop *nexthop)
86{
87 struct nexthop *last;
88
89 for (last = bnc->nexthop; last && last->next; last = last->next)
90 ;
91 if (last)
92 last->next = nexthop;
93 else
94 bnc->nexthop = nexthop;
95 nexthop->prev = last;
96}
97
fb018d25 98void
718e3744 99bnc_nexthop_free (struct bgp_nexthop_cache *bnc)
100{
101 struct nexthop *nexthop;
102 struct nexthop *next = NULL;
103
104 for (nexthop = bnc->nexthop; nexthop; nexthop = next)
105 {
106 next = nexthop->next;
107 XFREE (MTYPE_NEXTHOP, nexthop);
108 }
109}
110
fb018d25
DS
111struct bgp_nexthop_cache *
112bnc_new ()
718e3744 113{
fb018d25
DS
114 struct bgp_nexthop_cache *bnc;
115
116 bnc = XCALLOC (MTYPE_BGP_NEXTHOP_CACHE, sizeof (struct bgp_nexthop_cache));
117 LIST_INIT(&(bnc->paths));
118 return bnc;
718e3744 119}
120
fb018d25 121void
718e3744 122bnc_free (struct bgp_nexthop_cache *bnc)
123{
124 bnc_nexthop_free (bnc);
125 XFREE (MTYPE_BGP_NEXTHOP_CACHE, bnc);
126}
6b0655a2 127
94f2b392 128static int
8e80bdf2 129bgp_nexthop_cache_different (struct bgp_nexthop_cache *bnc1,
718e3744 130 struct bgp_nexthop_cache *bnc2)
131{
132 int i;
133 struct nexthop *next1, *next2;
134
135 if (bnc1->nexthop_num != bnc2->nexthop_num)
136 return 1;
137
138 next1 = bnc1->nexthop;
139 next2 = bnc2->nexthop;
140
141 for (i = 0; i < bnc1->nexthop_num; i++)
142 {
fb018d25 143 if (! nexthop_same_no_recurse (next1, next2))
718e3744 144 return 1;
145
146 next1 = next1->next;
147 next2 = next2->next;
148 }
149 return 0;
150}
151
152/* If nexthop exists on connected network return 1. */
153int
8e80bdf2 154bgp_nexthop_onlink (afi_t afi, struct attr *attr)
718e3744 155{
156 struct bgp_node *rn;
fc98d16e
PJ
157
158 /* If zebra is not enabled return */
159 if (zlookup->sock < 0)
160 return 1;
161
718e3744 162 /* Lookup the address is onlink or not. */
163 if (afi == AFI_IP)
164 {
5932020b 165 rn = bgp_node_match_ipv4 (bgp_connected_table[AFI_IP], &attr->nexthop);
718e3744 166 if (rn)
167 {
168 bgp_unlock_node (rn);
169 return 1;
170 }
171 }
172#ifdef HAVE_IPV6
173 else if (afi == AFI_IP6)
174 {
fb982c25 175 if (attr->extra->mp_nexthop_len == 32)
718e3744 176 return 1;
fb982c25 177 else if (attr->extra->mp_nexthop_len == 16)
718e3744 178 {
fb982c25 179 if (IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
718e3744 180 return 1;
181
5932020b 182 rn = bgp_node_match_ipv6 (bgp_connected_table[AFI_IP6],
fb982c25 183 &attr->extra->mp_nexthop_global);
718e3744 184 if (rn)
185 {
186 bgp_unlock_node (rn);
187 return 1;
188 }
189 }
190 }
191#endif /* HAVE_IPV6 */
192 return 0;
193}
194
195#ifdef HAVE_IPV6
196/* Check specified next-hop is reachable or not. */
94f2b392 197static int
718e3744 198bgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp_info *ri, int *changed,
199 int *metricchanged)
200{
201 struct bgp_node *rn;
202 struct prefix p;
203 struct bgp_nexthop_cache *bnc;
204 struct attr *attr;
fc98d16e
PJ
205
206 /* If lookup is not enabled, return valid. */
207 if (zlookup->sock < 0)
208 {
209 if (ri->extra)
210 ri->extra->igpmetric = 0;
211 return 1;
212 }
213
718e3744 214 /* Only check IPv6 global address only nexthop. */
215 attr = ri->attr;
216
fb982c25
PJ
217 if (attr->extra->mp_nexthop_len != 16
218 || IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
718e3744 219 return 1;
220
221 memset (&p, 0, sizeof (struct prefix));
222 p.family = AF_INET6;
223 p.prefixlen = IPV6_MAX_BITLEN;
fb982c25 224 p.u.prefix6 = attr->extra->mp_nexthop_global;
718e3744 225
226 /* IBGP or ebgp-multihop */
5932020b 227 rn = bgp_node_get (bgp_nexthop_cache_table[AFI_IP6], &p);
718e3744 228
229 if (rn->info)
230 {
231 bnc = rn->info;
232 bgp_unlock_node (rn);
233 }
234 else
235 {
b64bfc1c
DO
236 if (NULL == (bnc = zlookup_query_ipv6 (&attr->extra->mp_nexthop_global)))
237 bnc = bnc_new ();
238 else
718e3744 239 {
718e3744 240 if (changed)
241 {
8e80bdf2
DO
242 struct bgp_table *old;
243 struct bgp_node *oldrn;
244
5932020b 245 if (bgp_nexthop_cache_table[AFI_IP6] == cache1_table[AFI_IP6])
246 old = cache2_table[AFI_IP6];
718e3744 247 else
5932020b 248 old = cache1_table[AFI_IP6];
718e3744 249
250 oldrn = bgp_node_lookup (old, &p);
251 if (oldrn)
252 {
8e80bdf2 253 struct bgp_nexthop_cache *oldbnc = oldrn->info;
718e3744 254
8e80bdf2 255 bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc);
718e3744 256
257 if (bnc->metric != oldbnc->metric)
258 bnc->metricchanged = 1;
6c88b44d
CC
259
260 bgp_unlock_node (oldrn);
718e3744 261 }
262 }
263 }
718e3744 264 rn->info = bnc;
265 }
266
267 if (changed)
268 *changed = bnc->changed;
269
270 if (metricchanged)
271 *metricchanged = bnc->metricchanged;
272
fb982c25
PJ
273 if (bnc->valid && bnc->metric)
274 (bgp_info_extra_get (ri))->igpmetric = bnc->metric;
275 else if (ri->extra)
276 ri->extra->igpmetric = 0;
718e3744 277
278 return bnc->valid;
279}
280#endif /* HAVE_IPV6 */
281
282/* Check specified next-hop is reachable or not. */
283int
284bgp_nexthop_lookup (afi_t afi, struct peer *peer, struct bgp_info *ri,
285 int *changed, int *metricchanged)
286{
287 struct bgp_node *rn;
288 struct prefix p;
289 struct bgp_nexthop_cache *bnc;
290 struct in_addr addr;
fc98d16e
PJ
291
292 /* If lookup is not enabled, return valid. */
293 if (zlookup->sock < 0)
294 {
295 if (ri->extra)
296 ri->extra->igpmetric = 0;
297 return 1;
298 }
299
718e3744 300#ifdef HAVE_IPV6
301 if (afi == AFI_IP6)
302 return bgp_nexthop_lookup_ipv6 (peer, ri, changed, metricchanged);
303#endif /* HAVE_IPV6 */
304
305 addr = ri->attr->nexthop;
306
307 memset (&p, 0, sizeof (struct prefix));
308 p.family = AF_INET;
309 p.prefixlen = IPV4_MAX_BITLEN;
310 p.u.prefix4 = addr;
311
312 /* IBGP or ebgp-multihop */
5932020b 313 rn = bgp_node_get (bgp_nexthop_cache_table[AFI_IP], &p);
718e3744 314
315 if (rn->info)
316 {
317 bnc = rn->info;
318 bgp_unlock_node (rn);
319 }
320 else
321 {
b64bfc1c
DO
322 if (NULL == (bnc = zlookup_query (addr)))
323 bnc = bnc_new ();
324 else
718e3744 325 {
718e3744 326 if (changed)
327 {
8e80bdf2
DO
328 struct bgp_table *old;
329 struct bgp_node *oldrn;
330
5932020b 331 if (bgp_nexthop_cache_table[AFI_IP] == cache1_table[AFI_IP])
332 old = cache2_table[AFI_IP];
718e3744 333 else
5932020b 334 old = cache1_table[AFI_IP];
718e3744 335
336 oldrn = bgp_node_lookup (old, &p);
337 if (oldrn)
338 {
8e80bdf2 339 struct bgp_nexthop_cache *oldbnc = oldrn->info;
718e3744 340
8e80bdf2 341 bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc);
718e3744 342
343 if (bnc->metric != oldbnc->metric)
344 bnc->metricchanged = 1;
6c88b44d
CC
345
346 bgp_unlock_node (oldrn);
718e3744 347 }
348 }
349 }
718e3744 350 rn->info = bnc;
351 }
352
353 if (changed)
354 *changed = bnc->changed;
355
356 if (metricchanged)
357 *metricchanged = bnc->metricchanged;
358
fb982c25
PJ
359 if (bnc->valid && bnc->metric)
360 (bgp_info_extra_get(ri))->igpmetric = bnc->metric;
361 else if (ri->extra)
362 ri->extra->igpmetric = 0;
718e3744 363
364 return bnc->valid;
365}
366
367/* Reset and free all BGP nexthop cache. */
94f2b392 368static void
718e3744 369bgp_nexthop_cache_reset (struct bgp_table *table)
370{
371 struct bgp_node *rn;
372 struct bgp_nexthop_cache *bnc;
373
374 for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
375 if ((bnc = rn->info) != NULL)
376 {
377 bnc_free (bnc);
378 rn->info = NULL;
379 bgp_unlock_node (rn);
380 }
381}
382
94f2b392 383static void
5932020b 384bgp_scan (afi_t afi, safi_t safi)
718e3744 385{
386 struct bgp_node *rn;
387 struct bgp *bgp;
388 struct bgp_info *bi;
389 struct bgp_info *next;
390 struct peer *peer;
1eb8ef25 391 struct listnode *node, *nnode;
fb018d25 392#if BGP_SCAN_NEXTHOP
718e3744 393 int valid;
394 int current;
395 int changed;
396 int metricchanged;
397
398 /* Change cache. */
5932020b 399 if (bgp_nexthop_cache_table[afi] == cache1_table[afi])
400 bgp_nexthop_cache_table[afi] = cache2_table[afi];
718e3744 401 else
5932020b 402 bgp_nexthop_cache_table[afi] = cache1_table[afi];
fb018d25 403#endif
718e3744 404
405 /* Get default bgp. */
406 bgp = bgp_get_default ();
407 if (bgp == NULL)
408 return;
409
410 /* Maximum prefix check */
1eb8ef25 411 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 412 {
413 if (peer->status != Established)
414 continue;
415
5932020b 416 if (peer->afc[afi][SAFI_UNICAST])
417 bgp_maximum_prefix_overflow (peer, afi, SAFI_UNICAST, 1);
418 if (peer->afc[afi][SAFI_MULTICAST])
419 bgp_maximum_prefix_overflow (peer, afi, SAFI_MULTICAST, 1);
420 if (peer->afc[afi][SAFI_MPLS_VPN])
421 bgp_maximum_prefix_overflow (peer, afi, SAFI_MPLS_VPN, 1);
718e3744 422 }
423
5932020b 424 for (rn = bgp_table_top (bgp->rib[afi][SAFI_UNICAST]); rn;
718e3744 425 rn = bgp_route_next (rn))
426 {
427 for (bi = rn->info; bi; bi = next)
428 {
429 next = bi->next;
430
431 if (bi->type == ZEBRA_ROUTE_BGP && bi->sub_type == BGP_ROUTE_NORMAL)
432 {
fb018d25 433#if BGP_SCAN_NEXTHOP
718e3744 434 changed = 0;
435 metricchanged = 0;
436
a0f6ce5b
CF
437 if (bi->peer->sort == BGP_PEER_EBGP && bi->peer->ttl == 1
438 && !CHECK_FLAG(bi->peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
8e80bdf2 439 valid = bgp_nexthop_onlink (afi, bi->attr);
718e3744 440 else
5932020b 441 valid = bgp_nexthop_lookup (afi, bi->peer, bi,
718e3744 442 &changed, &metricchanged);
443
444 current = CHECK_FLAG (bi->flags, BGP_INFO_VALID) ? 1 : 0;
445
446 if (changed)
447 SET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED);
448 else
449 UNSET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED);
450
451 if (valid != current)
452 {
453 if (CHECK_FLAG (bi->flags, BGP_INFO_VALID))
454 {
455 bgp_aggregate_decrement (bgp, &rn->p, bi,
5932020b 456 afi, SAFI_UNICAST);
1a392d46 457 bgp_info_unset_flag (rn, bi, BGP_INFO_VALID);
718e3744 458 }
459 else
460 {
1a392d46 461 bgp_info_set_flag (rn, bi, BGP_INFO_VALID);
718e3744 462 bgp_aggregate_increment (bgp, &rn->p, bi,
5932020b 463 afi, SAFI_UNICAST);
718e3744 464 }
465 }
fb018d25 466#endif
718e3744 467
5932020b 468 if (CHECK_FLAG (bgp->af_flags[afi][SAFI_UNICAST],
718e3744 469 BGP_CONFIG_DAMPENING)
fb982c25 470 && bi->extra && bi->extra->damp_info )
5932020b 471 if (bgp_damp_scan (bi, afi, SAFI_UNICAST))
718e3744 472 bgp_aggregate_increment (bgp, &rn->p, bi,
5932020b 473 afi, SAFI_UNICAST);
718e3744 474 }
475 }
5932020b 476 bgp_process (bgp, rn, afi, SAFI_UNICAST);
718e3744 477 }
478
fb018d25 479#if BGP_SCAN_NEXTHOP
718e3744 480 /* Flash old cache. */
5932020b 481 if (bgp_nexthop_cache_table[afi] == cache1_table[afi])
482 bgp_nexthop_cache_reset (cache2_table[afi]);
718e3744 483 else
5932020b 484 bgp_nexthop_cache_reset (cache1_table[afi]);
fb018d25 485#endif
f418446b 486
487 if (BGP_DEBUG (events, EVENTS))
488 {
489 if (afi == AFI_IP)
490 zlog_debug ("scanning IPv4 Unicast routing tables");
491 else if (afi == AFI_IP6)
492 zlog_debug ("scanning IPv6 Unicast routing tables");
493 }
dcab1bb8
CF
494
495 /* Reevaluate default-originate route-maps and announce/withdraw
496 * default route if neccesary. */
497 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
498 {
499 if (peer->status == Established
500 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
501 && peer->default_rmap[afi][safi].name)
502 bgp_default_originate (peer, afi, safi, 0);
503 }
718e3744 504}
718e3744 505
506/* BGP scan thread. This thread check nexthop reachability. */
94f2b392 507static int
5932020b 508bgp_scan_timer (struct thread *t)
718e3744 509{
510 bgp_scan_thread =
5932020b 511 thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval);
718e3744 512
f418446b 513 if (BGP_DEBUG (events, EVENTS))
478ba054 514 zlog_debug ("Performing BGP general scanning");
718e3744 515
5932020b 516 bgp_scan (AFI_IP, SAFI_UNICAST);
718e3744 517
518#ifdef HAVE_IPV6
5932020b 519 bgp_scan (AFI_IP6, SAFI_UNICAST);
718e3744 520#endif /* HAVE_IPV6 */
521
522 return 0;
523}
10f9bf3f
JBD
524
525/* BGP own address structure */
526struct bgp_addr
527{
528 struct in_addr addr;
529 int refcnt;
530};
531
532static struct hash *bgp_address_hash;
533
534static void *
535bgp_address_hash_alloc (void *p)
536{
537 struct in_addr *val = p;
538 struct bgp_addr *addr;
539
540 addr = XMALLOC (MTYPE_BGP_ADDR, sizeof (struct bgp_addr));
541 addr->refcnt = 0;
542 addr->addr.s_addr = val->s_addr;
543
544 return addr;
545}
546
547static unsigned int
548bgp_address_hash_key_make (void *p)
549{
550 const struct bgp_addr *addr = p;
551
552 return jhash_1word(addr->addr.s_addr, 0);
553}
554
555static int
556bgp_address_hash_cmp (const void *p1, const void *p2)
557{
558 const struct bgp_addr *addr1 = p1;
559 const struct bgp_addr *addr2 = p2;
560
561 return addr1->addr.s_addr == addr2->addr.s_addr;
562}
563
564void
565bgp_address_init (void)
566{
567 bgp_address_hash = hash_create (bgp_address_hash_key_make,
568 bgp_address_hash_cmp);
569}
570
571static void
572bgp_address_add (struct prefix *p)
573{
574 struct bgp_addr tmp;
575 struct bgp_addr *addr;
576
577 tmp.addr = p->u.prefix4;
578
579 addr = hash_get (bgp_address_hash, &tmp, bgp_address_hash_alloc);
580 addr->refcnt++;
581}
582
583static void
584bgp_address_del (struct prefix *p)
585{
586 struct bgp_addr tmp;
587 struct bgp_addr *addr;
588
589 tmp.addr = p->u.prefix4;
590
591 addr = hash_lookup (bgp_address_hash, &tmp);
9e47abd8
RG
592 /* may have been deleted earlier by bgp_interface_down() */
593 if (addr == NULL)
594 return;
595
10f9bf3f
JBD
596 addr->refcnt--;
597
598 if (addr->refcnt == 0)
599 {
600 hash_release (bgp_address_hash, addr);
601 XFREE (MTYPE_BGP_ADDR, addr);
602 }
603}
604
6b0655a2 605
5932020b 606struct bgp_connected_ref
718e3744 607{
608 unsigned int refcnt;
609};
610
611void
612bgp_connected_add (struct connected *ifc)
613{
614 struct prefix p;
615 struct prefix *addr;
718e3744 616 struct interface *ifp;
617 struct bgp_node *rn;
5932020b 618 struct bgp_connected_ref *bc;
718e3744 619
620 ifp = ifc->ifp;
621
622 if (! ifp)
623 return;
624
625 if (if_is_loopback (ifp))
626 return;
627
628 addr = ifc->address;
718e3744 629
630 if (addr->family == AF_INET)
631 {
e4529636 632 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
718e3744 633 apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
634
635 if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
636 return;
637
10f9bf3f
JBD
638 bgp_address_add (addr);
639
5932020b 640 rn = bgp_node_get (bgp_connected_table[AFI_IP], (struct prefix *) &p);
718e3744 641 if (rn->info)
642 {
643 bc = rn->info;
644 bc->refcnt++;
645 }
646 else
647 {
6c88b44d 648 bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
718e3744 649 bc->refcnt = 1;
650 rn->info = bc;
651 }
652 }
653#ifdef HAVE_IPV6
e4529636 654 else if (addr->family == AF_INET6)
718e3744 655 {
e4529636 656 PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
718e3744 657 apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
658
659 if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
660 return;
661
662 if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
663 return;
664
5932020b 665 rn = bgp_node_get (bgp_connected_table[AFI_IP6], (struct prefix *) &p);
718e3744 666 if (rn->info)
667 {
668 bc = rn->info;
669 bc->refcnt++;
670 }
671 else
672 {
6c88b44d 673 bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
718e3744 674 bc->refcnt = 1;
675 rn->info = bc;
676 }
677 }
678#endif /* HAVE_IPV6 */
679}
680
681void
682bgp_connected_delete (struct connected *ifc)
683{
684 struct prefix p;
685 struct prefix *addr;
718e3744 686 struct interface *ifp;
687 struct bgp_node *rn;
5932020b 688 struct bgp_connected_ref *bc;
718e3744 689
690 ifp = ifc->ifp;
691
692 if (if_is_loopback (ifp))
693 return;
694
695 addr = ifc->address;
718e3744 696
697 if (addr->family == AF_INET)
698 {
e4529636 699 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
718e3744 700 apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
701
702 if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
703 return;
704
10f9bf3f
JBD
705 bgp_address_del (addr);
706
5932020b 707 rn = bgp_node_lookup (bgp_connected_table[AFI_IP], &p);
718e3744 708 if (! rn)
709 return;
710
711 bc = rn->info;
712 bc->refcnt--;
713 if (bc->refcnt == 0)
714 {
6c88b44d 715 XFREE (MTYPE_BGP_CONN, bc);
718e3744 716 rn->info = NULL;
717 }
718 bgp_unlock_node (rn);
719 bgp_unlock_node (rn);
720 }
721#ifdef HAVE_IPV6
722 else if (addr->family == AF_INET6)
723 {
e4529636 724 PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
718e3744 725 apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
726
727 if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
728 return;
729
730 if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
731 return;
732
5932020b 733 rn = bgp_node_lookup (bgp_connected_table[AFI_IP6], (struct prefix *) &p);
718e3744 734 if (! rn)
735 return;
736
737 bc = rn->info;
738 bc->refcnt--;
739 if (bc->refcnt == 0)
740 {
6c88b44d 741 XFREE (MTYPE_BGP_CONN, bc);
718e3744 742 rn->info = NULL;
743 }
744 bgp_unlock_node (rn);
745 bgp_unlock_node (rn);
746 }
747#endif /* HAVE_IPV6 */
748}
749
750int
10f9bf3f 751bgp_nexthop_self (struct attr *attr)
718e3744 752{
10f9bf3f 753 struct bgp_addr tmp, *addr;
718e3744 754
10f9bf3f
JBD
755 tmp.addr = attr->nexthop;
756
757 addr = hash_lookup (bgp_address_hash, &tmp);
758 if (addr)
759 return 1;
718e3744 760
718e3744 761 return 0;
762}
6b0655a2 763
94f2b392 764static struct bgp_nexthop_cache *
66e5cd87 765zlookup_read (void)
718e3744 766{
767 struct stream *s;
d3092e7f 768 uint16_t length;
769 u_char marker;
770 u_char version;
771 uint16_t command;
718e3744 772 int nbytes;
773 struct in_addr raddr;
d3092e7f 774 uint32_t metric;
718e3744 775 int i;
776 u_char nexthop_num;
777 struct nexthop *nexthop;
778 struct bgp_nexthop_cache *bnc;
779
780 s = zlookup->ibuf;
781 stream_reset (s);
782
783 nbytes = stream_read (s, zlookup->sock, 2);
784 length = stream_getw (s);
785
786 nbytes = stream_read (s, zlookup->sock, length - 2);
d3092e7f 787 marker = stream_getc (s);
788 version = stream_getc (s);
789
790 if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER)
791 {
792 zlog_err("%s: socket %d version mismatch, marker %d, version %d",
793 __func__, zlookup->sock, marker, version);
794 return NULL;
795 }
796
797 command = stream_getw (s);
798
718e3744 799 raddr.s_addr = stream_get_ipv4 (s);
800 metric = stream_getl (s);
801 nexthop_num = stream_getc (s);
802
803 if (nexthop_num)
804 {
805 bnc = bnc_new ();
806 bnc->valid = 1;
807 bnc->metric = metric;
808 bnc->nexthop_num = nexthop_num;
809
810 for (i = 0; i < nexthop_num; i++)
811 {
393deb9b 812 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
718e3744 813 nexthop->type = stream_getc (s);
814 switch (nexthop->type)
815 {
816 case ZEBRA_NEXTHOP_IPV4:
817 nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
818 break;
bb97e462
CF
819 case ZEBRA_NEXTHOP_IPV4_IFINDEX:
820 nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
821 nexthop->ifindex = stream_getl (s);
822 break;
718e3744 823 case ZEBRA_NEXTHOP_IFINDEX:
824 case ZEBRA_NEXTHOP_IFNAME:
825 nexthop->ifindex = stream_getl (s);
826 break;
fa2b17e3 827 default:
828 /* do nothing */
829 break;
718e3744 830 }
831 bnc_nexthop_add (bnc, nexthop);
832 }
833 }
834 else
835 return NULL;
836
837 return bnc;
838}
839
840struct bgp_nexthop_cache *
841zlookup_query (struct in_addr addr)
842{
843 int ret;
844 struct stream *s;
845
846 /* Check socket. */
847 if (zlookup->sock < 0)
848 return NULL;
849
850 s = zlookup->obuf;
851 stream_reset (s);
d3092e7f 852 zclient_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP);
718e3744 853 stream_put_in_addr (s, &addr);
d3092e7f 854
855 stream_putw_at (s, 0, stream_get_endp (s));
856
857 ret = writen (zlookup->sock, s->data, stream_get_endp (s));
718e3744 858 if (ret < 0)
859 {
860 zlog_err ("can't write to zlookup->sock");
861 close (zlookup->sock);
862 zlookup->sock = -1;
863 return NULL;
864 }
865 if (ret == 0)
866 {
867 zlog_err ("zlookup->sock connection closed");
868 close (zlookup->sock);
869 zlookup->sock = -1;
870 return NULL;
871 }
872
873 return zlookup_read ();
874}
875
876#ifdef HAVE_IPV6
94f2b392 877static struct bgp_nexthop_cache *
66e5cd87 878zlookup_read_ipv6 (void)
718e3744 879{
880 struct stream *s;
d3092e7f 881 uint16_t length;
882 u_char version, marker;
883 uint16_t command;
718e3744 884 int nbytes;
885 struct in6_addr raddr;
d3092e7f 886 uint32_t metric;
718e3744 887 int i;
888 u_char nexthop_num;
889 struct nexthop *nexthop;
890 struct bgp_nexthop_cache *bnc;
891
892 s = zlookup->ibuf;
893 stream_reset (s);
894
895 nbytes = stream_read (s, zlookup->sock, 2);
896 length = stream_getw (s);
897
898 nbytes = stream_read (s, zlookup->sock, length - 2);
d3092e7f 899 marker = stream_getc (s);
900 version = stream_getc (s);
901
902 if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER)
903 {
904 zlog_err("%s: socket %d version mismatch, marker %d, version %d",
905 __func__, zlookup->sock, marker, version);
906 return NULL;
907 }
908
909 command = stream_getw (s);
910
718e3744 911 stream_get (&raddr, s, 16);
912
913 metric = stream_getl (s);
914 nexthop_num = stream_getc (s);
915
916 if (nexthop_num)
917 {
918 bnc = bnc_new ();
919 bnc->valid = 1;
920 bnc->metric = metric;
921 bnc->nexthop_num = nexthop_num;
922
923 for (i = 0; i < nexthop_num; i++)
924 {
393deb9b 925 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
718e3744 926 nexthop->type = stream_getc (s);
927 switch (nexthop->type)
928 {
929 case ZEBRA_NEXTHOP_IPV6:
930 stream_get (&nexthop->gate.ipv6, s, 16);
931 break;
932 case ZEBRA_NEXTHOP_IPV6_IFINDEX:
933 case ZEBRA_NEXTHOP_IPV6_IFNAME:
934 stream_get (&nexthop->gate.ipv6, s, 16);
935 nexthop->ifindex = stream_getl (s);
936 break;
937 case ZEBRA_NEXTHOP_IFINDEX:
938 case ZEBRA_NEXTHOP_IFNAME:
939 nexthop->ifindex = stream_getl (s);
940 break;
fa2b17e3 941 default:
942 /* do nothing */
943 break;
718e3744 944 }
945 bnc_nexthop_add (bnc, nexthop);
946 }
947 }
948 else
949 return NULL;
950
951 return bnc;
952}
953
954struct bgp_nexthop_cache *
955zlookup_query_ipv6 (struct in6_addr *addr)
956{
957 int ret;
958 struct stream *s;
959
960 /* Check socket. */
961 if (zlookup->sock < 0)
962 return NULL;
963
964 s = zlookup->obuf;
965 stream_reset (s);
d3092e7f 966 zclient_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP);
718e3744 967 stream_put (s, addr, 16);
d3092e7f 968 stream_putw_at (s, 0, stream_get_endp (s));
969
970 ret = writen (zlookup->sock, s->data, stream_get_endp (s));
718e3744 971 if (ret < 0)
972 {
973 zlog_err ("can't write to zlookup->sock");
974 close (zlookup->sock);
975 zlookup->sock = -1;
976 return NULL;
977 }
978 if (ret == 0)
979 {
980 zlog_err ("zlookup->sock connection closed");
981 close (zlookup->sock);
982 zlookup->sock = -1;
983 return NULL;
984 }
985
986 return zlookup_read_ipv6 ();
987}
988#endif /* HAVE_IPV6 */
989
94f2b392 990static int
991bgp_import_check (struct prefix *p, u_int32_t *igpmetric,
992 struct in_addr *igpnexthop)
718e3744 993{
994 struct stream *s;
995 int ret;
d3092e7f 996 u_int16_t length, command;
997 u_char version, marker;
718e3744 998 int nbytes;
999 struct in_addr addr;
1000 struct in_addr nexthop;
1001 u_int32_t metric = 0;
1002 u_char nexthop_num;
1003 u_char nexthop_type;
1004
1005 /* If lookup connection is not available return valid. */
1006 if (zlookup->sock < 0)
1007 {
1008 if (igpmetric)
1009 *igpmetric = 0;
1010 return 1;
1011 }
1012
1013 /* Send query to the lookup connection */
1014 s = zlookup->obuf;
1015 stream_reset (s);
d3092e7f 1016 zclient_create_header (s, ZEBRA_IPV4_IMPORT_LOOKUP);
1017
718e3744 1018 stream_putc (s, p->prefixlen);
1019 stream_put_in_addr (s, &p->u.prefix4);
d3092e7f 1020
1021 stream_putw_at (s, 0, stream_get_endp (s));
1022
718e3744 1023 /* Write the packet. */
d3092e7f 1024 ret = writen (zlookup->sock, s->data, stream_get_endp (s));
718e3744 1025
1026 if (ret < 0)
1027 {
1028 zlog_err ("can't write to zlookup->sock");
1029 close (zlookup->sock);
1030 zlookup->sock = -1;
1031 return 1;
1032 }
1033 if (ret == 0)
1034 {
1035 zlog_err ("zlookup->sock connection closed");
1036 close (zlookup->sock);
1037 zlookup->sock = -1;
1038 return 1;
1039 }
1040
1041 /* Get result. */
1042 stream_reset (s);
1043
1044 /* Fetch length. */
1045 nbytes = stream_read (s, zlookup->sock, 2);
1046 length = stream_getw (s);
1047
1048 /* Fetch whole data. */
1049 nbytes = stream_read (s, zlookup->sock, length - 2);
d3092e7f 1050 marker = stream_getc (s);
1051 version = stream_getc (s);
1052
1053 if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER)
1054 {
1055 zlog_err("%s: socket %d version mismatch, marker %d, version %d",
1056 __func__, zlookup->sock, marker, version);
1057 return 0;
1058 }
1059
1060 command = stream_getw (s);
1061
718e3744 1062 addr.s_addr = stream_get_ipv4 (s);
1063 metric = stream_getl (s);
1064 nexthop_num = stream_getc (s);
1065
1066 /* Set IGP metric value. */
1067 if (igpmetric)
1068 *igpmetric = metric;
1069
1070 /* If there is nexthop then this is active route. */
1071 if (nexthop_num)
1072 {
1073 nexthop.s_addr = 0;
1074 nexthop_type = stream_getc (s);
a12afd5e 1075 switch (nexthop_type)
718e3744 1076 {
a12afd5e 1077 case ZEBRA_NEXTHOP_IPV4:
718e3744 1078 nexthop.s_addr = stream_get_ipv4 (s);
a12afd5e
CF
1079 break;
1080 case ZEBRA_NEXTHOP_IPV4_IFINDEX:
1081 nexthop.s_addr = stream_get_ipv4 (s);
1082 /* ifindex */ (void)stream_getl (s);
1083 break;
1084 default:
1085 /* do nothing */
1086 break;
718e3744 1087 }
a12afd5e 1088 *igpnexthop = nexthop;
718e3744 1089
1090 return 1;
1091 }
1092 else
1093 return 0;
1094}
1095
1096/* Scan all configured BGP route then check the route exists in IGP or
1097 not. */
94f2b392 1098static int
718e3744 1099bgp_import (struct thread *t)
1100{
1101 struct bgp *bgp;
1102 struct bgp_node *rn;
1103 struct bgp_static *bgp_static;
1eb8ef25 1104 struct listnode *node, *nnode;
718e3744 1105 int valid;
1106 u_int32_t metric;
1107 struct in_addr nexthop;
1108 afi_t afi;
1109 safi_t safi;
1110
1111 bgp_import_thread =
1112 thread_add_timer (master, bgp_import, NULL, bgp_import_interval);
1113
f418446b 1114 if (BGP_DEBUG (events, EVENTS))
1115 zlog_debug ("Import timer expired.");
718e3744 1116
1eb8ef25 1117 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
6cbbc3cc 1118 {
1119 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1120 for (safi = SAFI_UNICAST; safi < SAFI_MPLS_VPN; safi++)
1121 for (rn = bgp_table_top (bgp->route[afi][safi]); rn;
1122 rn = bgp_route_next (rn))
1123 if ((bgp_static = rn->info) != NULL)
718e3744 1124 {
6cbbc3cc 1125 if (bgp_static->backdoor)
1126 continue;
718e3744 1127
6cbbc3cc 1128 valid = bgp_static->valid;
1129 metric = bgp_static->igpmetric;
1130 nexthop = bgp_static->igpnexthop;
1131
1132 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK)
1133 && afi == AFI_IP && safi == SAFI_UNICAST)
1134 bgp_static->valid = bgp_import_check (&rn->p, &bgp_static->igpmetric,
1135 &bgp_static->igpnexthop);
718e3744 1136 else
6cbbc3cc 1137 {
1138 bgp_static->valid = 1;
1139 bgp_static->igpmetric = 0;
1140 bgp_static->igpnexthop.s_addr = 0;
1141 }
1142
1143 if (bgp_static->valid != valid)
1144 {
1145 if (bgp_static->valid)
1146 bgp_static_update (bgp, &rn->p, bgp_static, afi, safi);
1147 else
1148 bgp_static_withdraw (bgp, &rn->p, afi, safi);
1149 }
1150 else if (bgp_static->valid)
1151 {
1152 if (bgp_static->igpmetric != metric
1153 || bgp_static->igpnexthop.s_addr != nexthop.s_addr
1154 || bgp_static->rmap.name)
1155 bgp_static_update (bgp, &rn->p, bgp_static, afi, safi);
1156 }
718e3744 1157 }
6cbbc3cc 1158 }
718e3744 1159 return 0;
1160}
1161
1162/* Connect to zebra for nexthop lookup. */
94f2b392 1163static int
718e3744 1164zlookup_connect (struct thread *t)
1165{
1166 struct zclient *zlookup;
1167
1168 zlookup = THREAD_ARG (t);
1169 zlookup->t_connect = NULL;
1170
1171 if (zlookup->sock != -1)
1172 return 0;
1173
b5114685 1174 if (zclient_socket_connect (zlookup) < 0)
718e3744 1175 return -1;
1176
718e3744 1177 return 0;
1178}
1179
1180/* Check specified multiaccess next-hop. */
1181int
1182bgp_multiaccess_check_v4 (struct in_addr nexthop, char *peer)
1183{
1184 struct bgp_node *rn1;
1185 struct bgp_node *rn2;
1186 struct prefix p1;
1187 struct prefix p2;
1188 struct in_addr addr;
1189 int ret;
1190
1191 ret = inet_aton (peer, &addr);
1192 if (! ret)
1193 return 0;
1194
1195 memset (&p1, 0, sizeof (struct prefix));
1196 p1.family = AF_INET;
1197 p1.prefixlen = IPV4_MAX_BITLEN;
1198 p1.u.prefix4 = nexthop;
1199 memset (&p2, 0, sizeof (struct prefix));
1200 p2.family = AF_INET;
1201 p2.prefixlen = IPV4_MAX_BITLEN;
1202 p2.u.prefix4 = addr;
1203
1204 /* If bgp scan is not enabled, return invalid. */
1205 if (zlookup->sock < 0)
1206 return 0;
1207
5932020b 1208 rn1 = bgp_node_match (bgp_connected_table[AFI_IP], &p1);
718e3744 1209 if (! rn1)
1210 return 0;
6c88b44d 1211 bgp_unlock_node (rn1);
718e3744 1212
5932020b 1213 rn2 = bgp_node_match (bgp_connected_table[AFI_IP], &p2);
718e3744 1214 if (! rn2)
1215 return 0;
6c88b44d 1216 bgp_unlock_node (rn2);
718e3744 1217
6c88b44d
CC
1218 /* This is safe, even with above unlocks, since we are just
1219 comparing pointers to the objects, not the objects themselves. */
718e3744 1220 if (rn1 == rn2)
1221 return 1;
1222
1223 return 0;
1224}
6b0655a2 1225
718e3744 1226DEFUN (bgp_scan_time,
1227 bgp_scan_time_cmd,
1228 "bgp scan-time <5-60>",
1229 "BGP specific commands\n"
1230 "Configure background scanner interval\n"
1231 "Scanner interval (seconds)\n")
1232{
1233 bgp_scan_interval = atoi (argv[0]);
1234
1235 if (bgp_scan_thread)
1236 {
1237 thread_cancel (bgp_scan_thread);
1238 bgp_scan_thread =
5932020b 1239 thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval);
718e3744 1240 }
1241
1242 return CMD_SUCCESS;
1243}
1244
1245DEFUN (no_bgp_scan_time,
1246 no_bgp_scan_time_cmd,
1247 "no bgp scan-time",
1248 NO_STR
1249 "BGP specific commands\n"
1250 "Configure background scanner interval\n")
1251{
1252 bgp_scan_interval = BGP_SCAN_INTERVAL_DEFAULT;
1253
1254 if (bgp_scan_thread)
1255 {
1256 thread_cancel (bgp_scan_thread);
1257 bgp_scan_thread =
5932020b 1258 thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval);
718e3744 1259 }
1260
1261 return CMD_SUCCESS;
1262}
1263
1264ALIAS (no_bgp_scan_time,
1265 no_bgp_scan_time_val_cmd,
1266 "no bgp scan-time <5-60>",
1267 NO_STR
1268 "BGP specific commands\n"
1269 "Configure background scanner interval\n"
1270 "Scanner interval (seconds)\n")
1271
318f0d8a
DO
1272static int
1273show_ip_bgp_scan_tables (struct vty *vty, const char detail)
718e3744 1274{
1275 struct bgp_node *rn;
318f0d8a 1276 char buf[INET6_ADDRSTRLEN];
718e3744 1277
1278 if (bgp_scan_thread)
1279 vty_out (vty, "BGP scan is running%s", VTY_NEWLINE);
1280 else
1281 vty_out (vty, "BGP scan is not running%s", VTY_NEWLINE);
1282 vty_out (vty, "BGP scan interval is %d%s", bgp_scan_interval, VTY_NEWLINE);
1283
fb018d25 1284#if BGP_SCAN_NEXTHOP
718e3744 1285 vty_out (vty, "Current BGP nexthop cache:%s", VTY_NEWLINE);
5932020b 1286 for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP]); rn; rn = bgp_route_next (rn))
718e3744 1287 if ((bnc = rn->info) != NULL)
1288 {
1289 if (bnc->valid)
318f0d8a 1290 {
718e3744 1291 vty_out (vty, " %s valid [IGP metric %d]%s",
318f0d8a
DO
1292 inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), bnc->metric, VTY_NEWLINE);
1293 if (detail)
1294 for (i = 0; i < bnc->nexthop_num; i++)
0e8032d6
DO
1295 switch (bnc->nexthop[i].type)
1296 {
1297 case NEXTHOP_TYPE_IPV4:
1298 vty_out (vty, " gate %s%s", inet_ntop (AF_INET, &bnc->nexthop[i].gate.ipv4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
1299 break;
bb97e462
CF
1300 case NEXTHOP_TYPE_IPV4_IFINDEX:
1301 vty_out (vty, " gate %s", inet_ntop (AF_INET, &bnc->nexthop[i].gate.ipv4, buf, INET6_ADDRSTRLEN));
1302 vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE);
1303 break;
0e8032d6
DO
1304 case NEXTHOP_TYPE_IFINDEX:
1305 vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE);
1306 break;
1307 default:
1308 vty_out (vty, " invalid nexthop type %u%s", bnc->nexthop[i].type, VTY_NEWLINE);
1309 }
318f0d8a 1310 }
718e3744 1311 else
1312 vty_out (vty, " %s invalid%s",
318f0d8a 1313 inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
718e3744 1314 }
1315
1316#ifdef HAVE_IPV6
1317 {
5932020b 1318 for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP6]);
1319 rn;
1320 rn = bgp_route_next (rn))
718e3744 1321 if ((bnc = rn->info) != NULL)
1322 {
1323 if (bnc->valid)
318f0d8a 1324 {
718e3744 1325 vty_out (vty, " %s valid [IGP metric %d]%s",
318f0d8a 1326 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
718e3744 1327 bnc->metric, VTY_NEWLINE);
318f0d8a
DO
1328 if (detail)
1329 for (i = 0; i < bnc->nexthop_num; i++)
0e8032d6
DO
1330 switch (bnc->nexthop[i].type)
1331 {
1332 case NEXTHOP_TYPE_IPV6:
1333 vty_out (vty, " gate %s%s", inet_ntop (AF_INET6, &bnc->nexthop[i].gate.ipv6, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
1334 break;
1335 case NEXTHOP_TYPE_IFINDEX:
1336 vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE);
1337 break;
1338 default:
1339 vty_out (vty, " invalid nexthop type %u%s", bnc->nexthop[i].type, VTY_NEWLINE);
1340 }
318f0d8a 1341 }
718e3744 1342 else
1343 vty_out (vty, " %s invalid%s",
318f0d8a 1344 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
718e3744 1345 VTY_NEWLINE);
1346 }
1347 }
1348#endif /* HAVE_IPV6 */
fb018d25
DS
1349#else
1350 vty_out (vty, "BGP next-hop tracking is on%s", VTY_NEWLINE);
1351#endif
718e3744 1352 vty_out (vty, "BGP connected route:%s", VTY_NEWLINE);
5932020b 1353 for (rn = bgp_table_top (bgp_connected_table[AFI_IP]);
1354 rn;
1355 rn = bgp_route_next (rn))
718e3744 1356 if (rn->info != NULL)
1357 vty_out (vty, " %s/%d%s", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
1358 VTY_NEWLINE);
1359
1360#ifdef HAVE_IPV6
1361 {
5932020b 1362 for (rn = bgp_table_top (bgp_connected_table[AFI_IP6]);
1363 rn;
1364 rn = bgp_route_next (rn))
718e3744 1365 if (rn->info != NULL)
1366 vty_out (vty, " %s/%d%s",
318f0d8a 1367 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
718e3744 1368 rn->p.prefixlen,
1369 VTY_NEWLINE);
1370 }
1371#endif /* HAVE_IPV6 */
1372
1373 return CMD_SUCCESS;
1374}
1375
fb018d25
DS
1376static int
1377show_ip_bgp_nexthop_table (struct vty *vty, int detail)
1378{
1379 struct bgp_node *rn;
1380 struct bgp_nexthop_cache *bnc;
1381 char buf[INET6_ADDRSTRLEN];
1382 time_t tbuf;
1383 u_char i;
1384
1385 vty_out (vty, "Current BGP nexthop cache:%s", VTY_NEWLINE);
1386 for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP]); rn; rn = bgp_route_next (rn))
1387 if ((bnc = rn->info) != NULL)
1388 {
1389 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))
1390 {
1391 vty_out (vty, " %s valid [IGP metric %d], #paths %d%s",
1392 inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN),
1393 bnc->metric, bnc->path_count, VTY_NEWLINE);
1394 if (detail)
1395 for (i = 0; i < bnc->nexthop_num; i++)
1396 switch (bnc->nexthop[i].type)
1397 {
1398 case NEXTHOP_TYPE_IPV4:
1399 vty_out (vty, " gate %s%s",
1400 inet_ntop (AF_INET, &bnc->nexthop[i].gate.ipv4, buf,
1401 INET6_ADDRSTRLEN), VTY_NEWLINE);
1402 break;
1403 case NEXTHOP_TYPE_IFINDEX:
1404 vty_out (vty, " if %s%s",
1405 ifindex2ifname(bnc->nexthop[i].ifindex), VTY_NEWLINE);
1406 break;
1407 case NEXTHOP_TYPE_IPV4_IFINDEX:
1408 vty_out (vty, " gate %s, if %s%s",
1409 inet_ntop(AF_INET, &bnc->nexthop[i].gate.ipv4, buf,
1410 INET6_ADDRSTRLEN),
1411 ifindex2ifname(bnc->nexthop[i].ifindex), VTY_NEWLINE);
1412 break;
1413 default:
1414 vty_out (vty, " invalid nexthop type %u%s",
1415 bnc->nexthop[i].type, VTY_NEWLINE);
1416 }
1417 }
1418 else
1419 vty_out (vty, " %s invalid%s",
1420 inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
1421#ifdef HAVE_CLOCK_MONOTONIC
1422 tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
1423 vty_out (vty, " Last update: %s", ctime(&tbuf));
1424#else
1425 vty_out (vty, " Last update: %s", ctime(&bnc->uptime));
1426#endif /* HAVE_CLOCK_MONOTONIC */
1427
1428 vty_out(vty, "%s", VTY_NEWLINE);
1429 }
1430
1431#ifdef HAVE_IPV6
1432 {
1433 for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP6]);
1434 rn;
1435 rn = bgp_route_next (rn))
1436 if ((bnc = rn->info) != NULL)
1437 {
1438 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))
1439 {
1440 vty_out (vty, " %s valid [IGP metric %d]%s",
1441 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf,
1442 INET6_ADDRSTRLEN),
1443 bnc->metric, VTY_NEWLINE);
1444 if (detail)
1445 for (i = 0; i < bnc->nexthop_num; i++)
1446 switch (bnc->nexthop[i].type)
1447 {
1448 case NEXTHOP_TYPE_IPV6:
1449 vty_out (vty, " gate %s%s",
1450 inet_ntop (AF_INET6, &bnc->nexthop[i].gate.ipv6,
1451 buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
1452 break;
1453 case NEXTHOP_TYPE_IPV6_IFINDEX:
1454 vty_out(vty, " gate %s, if %s%s",
1455 inet_ntop(AF_INET6, &bnc->nexthop[i].gate.ipv6, buf,
1456 INET6_ADDRSTRLEN),
1457 ifindex2ifname(bnc->nexthop[i].ifindex),
1458 VTY_NEWLINE);
1459 break;
1460 case NEXTHOP_TYPE_IFINDEX:
1461 vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex,
1462 VTY_NEWLINE);
1463 break;
1464 default:
1465 vty_out (vty, " invalid nexthop type %u%s",
1466 bnc->nexthop[i].type, VTY_NEWLINE);
1467 }
1468 }
1469 else
1470 vty_out (vty, " %s invalid%s",
1471 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
1472 VTY_NEWLINE);
1473#ifdef HAVE_CLOCK_MONOTONIC
1474 tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
1475 vty_out (vty, " Last update: %s", ctime(&tbuf));
1476#else
1477 vty_out (vty, " Last update: %s", ctime(&bnc->uptime));
1478#endif /* HAVE_CLOCK_MONOTONIC */
1479
1480 vty_out(vty, "%s", VTY_NEWLINE);
1481 }
1482 }
1483#endif /* HAVE_IPV6 */
1484 return CMD_SUCCESS;
1485}
1486
318f0d8a
DO
1487DEFUN (show_ip_bgp_scan,
1488 show_ip_bgp_scan_cmd,
1489 "show ip bgp scan",
1490 SHOW_STR
1491 IP_STR
1492 BGP_STR
1493 "BGP scan status\n")
1494{
1495 return show_ip_bgp_scan_tables (vty, 0);
1496}
1497
1498DEFUN (show_ip_bgp_scan_detail,
1499 show_ip_bgp_scan_detail_cmd,
1500 "show ip bgp scan detail",
1501 SHOW_STR
1502 IP_STR
1503 BGP_STR
1504 "BGP scan status\n"
1505 "More detailed output\n")
1506{
1507 return show_ip_bgp_scan_tables (vty, 1);
1508}
1509
fb018d25
DS
1510DEFUN (show_ip_bgp_nexthop,
1511 show_ip_bgp_nexthop_cmd,
1512 "show ip bgp nexthop",
1513 SHOW_STR
1514 IP_STR
1515 BGP_STR
1516 "BGP nexthop table\n")
1517{
1518 return show_ip_bgp_nexthop_table (vty, 0);
1519}
1520
1521DEFUN (show_ip_bgp_nexthop_detail,
1522 show_ip_bgp_nexthop_detail_cmd,
1523 "show ip bgp nexthop detail",
1524 SHOW_STR
1525 IP_STR
1526 BGP_STR
1527 "BGP nexthop table\n")
1528{
1529 return show_ip_bgp_nexthop_table (vty, 1);
1530}
1531
718e3744 1532int
1533bgp_config_write_scan_time (struct vty *vty)
1534{
1535 if (bgp_scan_interval != BGP_SCAN_INTERVAL_DEFAULT)
1536 vty_out (vty, " bgp scan-time %d%s", bgp_scan_interval, VTY_NEWLINE);
1537 return CMD_SUCCESS;
1538}
1539
1540void
66e5cd87 1541bgp_scan_init (void)
718e3744 1542{
1543 zlookup = zclient_new ();
1544 zlookup->sock = -1;
718e3744 1545 zlookup->t_connect = thread_add_event (master, zlookup_connect, zlookup, 0);
1546
1547 bgp_scan_interval = BGP_SCAN_INTERVAL_DEFAULT;
1548 bgp_import_interval = BGP_IMPORT_INTERVAL_DEFAULT;
1549
64e580a7
PJ
1550 cache1_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
1551 cache2_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
5932020b 1552 bgp_nexthop_cache_table[AFI_IP] = cache1_table[AFI_IP];
718e3744 1553
64e580a7 1554 bgp_connected_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
718e3744 1555
1556#ifdef HAVE_IPV6
64e580a7
PJ
1557 cache1_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
1558 cache2_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
5932020b 1559 bgp_nexthop_cache_table[AFI_IP6] = cache1_table[AFI_IP6];
64e580a7 1560 bgp_connected_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
718e3744 1561#endif /* HAVE_IPV6 */
1562
1563 /* Make BGP scan thread. */
5932020b 1564 bgp_scan_thread = thread_add_timer (master, bgp_scan_timer,
1565 NULL, bgp_scan_interval);
6cbbc3cc 1566 /* Make BGP import there. */
1567 bgp_import_thread = thread_add_timer (master, bgp_import, NULL, 0);
718e3744 1568
1569 install_element (BGP_NODE, &bgp_scan_time_cmd);
1570 install_element (BGP_NODE, &no_bgp_scan_time_cmd);
1571 install_element (BGP_NODE, &no_bgp_scan_time_val_cmd);
1572 install_element (VIEW_NODE, &show_ip_bgp_scan_cmd);
318f0d8a 1573 install_element (VIEW_NODE, &show_ip_bgp_scan_detail_cmd);
fb018d25
DS
1574 install_element (VIEW_NODE, &show_ip_bgp_nexthop_cmd);
1575 install_element (VIEW_NODE, &show_ip_bgp_nexthop_detail_cmd);
62687ff1 1576 install_element (RESTRICTED_NODE, &show_ip_bgp_scan_cmd);
718e3744 1577 install_element (ENABLE_NODE, &show_ip_bgp_scan_cmd);
fb018d25
DS
1578 install_element (ENABLE_NODE, &show_ip_bgp_nexthop_cmd);
1579 install_element (ENABLE_NODE, &show_ip_bgp_nexthop_detail_cmd);
318f0d8a 1580 install_element (ENABLE_NODE, &show_ip_bgp_scan_detail_cmd);
718e3744 1581}
228da428
CC
1582
1583void
1584bgp_scan_finish (void)
1585{
6c88b44d
CC
1586 /* Only the current one needs to be reset. */
1587 bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP]);
1588
228da428
CC
1589 bgp_table_unlock (cache1_table[AFI_IP]);
1590 cache1_table[AFI_IP] = NULL;
1591
1592 bgp_table_unlock (cache2_table[AFI_IP]);
1593 cache2_table[AFI_IP] = NULL;
1594
1595 bgp_table_unlock (bgp_connected_table[AFI_IP]);
1596 bgp_connected_table[AFI_IP] = NULL;
1597
1598#ifdef HAVE_IPV6
6c88b44d
CC
1599 /* Only the current one needs to be reset. */
1600 bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP6]);
1601
228da428
CC
1602 bgp_table_unlock (cache1_table[AFI_IP6]);
1603 cache1_table[AFI_IP6] = NULL;
1604
1605 bgp_table_unlock (cache2_table[AFI_IP6]);
1606 cache2_table[AFI_IP6] = NULL;
1607
1608 bgp_table_unlock (bgp_connected_table[AFI_IP6]);
1609 bgp_connected_table[AFI_IP6] = NULL;
1610#endif /* HAVE_IPV6 */
1611}