blob: fdf251b2a872bcd79feff25c9295f1867a53d8d6 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* 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"
31
32#include "bgpd/bgpd.h"
33#include "bgpd/bgp_table.h"
34#include "bgpd/bgp_route.h"
35#include "bgpd/bgp_attr.h"
36#include "bgpd/bgp_nexthop.h"
37#include "bgpd/bgp_debug.h"
38#include "bgpd/bgp_damp.h"
39#include "zebra/rib.h"
40#include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
41
42struct bgp_nexthop_cache *zlookup_query (struct in_addr);
43#ifdef HAVE_IPV6
44struct bgp_nexthop_cache *zlookup_query_ipv6 (struct in6_addr *);
45#endif /* HAVE_IPV6 */
46
47/* Only one BGP scan thread are activated at the same time. */
paul00d252c2005-05-23 14:19:54 +000048static struct thread *bgp_scan_thread = NULL;
paul718e3742002-12-13 20:15:29 +000049
50/* BGP import thread */
paul00d252c2005-05-23 14:19:54 +000051static struct thread *bgp_import_thread = NULL;
paul718e3742002-12-13 20:15:29 +000052
53/* BGP scan interval. */
paul00d252c2005-05-23 14:19:54 +000054static int bgp_scan_interval;
paul718e3742002-12-13 20:15:29 +000055
56/* BGP import interval. */
paul00d252c2005-05-23 14:19:54 +000057static int bgp_import_interval;
paul718e3742002-12-13 20:15:29 +000058
59/* Route table for next-hop lookup cache. */
paul00d252c2005-05-23 14:19:54 +000060static struct bgp_table *bgp_nexthop_cache_table[AFI_MAX];
61static struct bgp_table *cache1_table[AFI_MAX];
62static struct bgp_table *cache2_table[AFI_MAX];
paul718e3742002-12-13 20:15:29 +000063
64/* Route table for connected route. */
paul00d252c2005-05-23 14:19:54 +000065static struct bgp_table *bgp_connected_table[AFI_MAX];
paul718e3742002-12-13 20:15:29 +000066
67/* BGP nexthop lookup query client. */
Chris Caputo228da422009-07-18 05:44:03 +000068struct zclient *zlookup = NULL;
paul718e3742002-12-13 20:15:29 +000069
70/* Add nexthop to the end of the list. */
paul94f2b392005-06-28 12:44:16 +000071static void
paul718e3742002-12-13 20:15:29 +000072bnc_nexthop_add (struct bgp_nexthop_cache *bnc, struct nexthop *nexthop)
73{
74 struct nexthop *last;
75
76 for (last = bnc->nexthop; last && last->next; last = last->next)
77 ;
78 if (last)
79 last->next = nexthop;
80 else
81 bnc->nexthop = nexthop;
82 nexthop->prev = last;
83}
84
paul94f2b392005-06-28 12:44:16 +000085static void
paul718e3742002-12-13 20:15:29 +000086bnc_nexthop_free (struct bgp_nexthop_cache *bnc)
87{
88 struct nexthop *nexthop;
89 struct nexthop *next = NULL;
90
91 for (nexthop = bnc->nexthop; nexthop; nexthop = next)
92 {
93 next = nexthop->next;
94 XFREE (MTYPE_NEXTHOP, nexthop);
95 }
96}
97
paul94f2b392005-06-28 12:44:16 +000098static struct bgp_nexthop_cache *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -080099bnc_new (void)
paul718e3742002-12-13 20:15:29 +0000100{
Stephen Hemminger393deb92008-08-18 14:13:29 -0700101 return XCALLOC (MTYPE_BGP_NEXTHOP_CACHE, sizeof (struct bgp_nexthop_cache));
paul718e3742002-12-13 20:15:29 +0000102}
103
paul94f2b392005-06-28 12:44:16 +0000104static void
paul718e3742002-12-13 20:15:29 +0000105bnc_free (struct bgp_nexthop_cache *bnc)
106{
107 bnc_nexthop_free (bnc);
108 XFREE (MTYPE_BGP_NEXTHOP_CACHE, bnc);
109}
110
paul94f2b392005-06-28 12:44:16 +0000111static int
paul718e3742002-12-13 20:15:29 +0000112bgp_nexthop_same (struct nexthop *next1, struct nexthop *next2)
113{
114 if (next1->type != next2->type)
115 return 0;
116
117 switch (next1->type)
118 {
119 case ZEBRA_NEXTHOP_IPV4:
120 if (! IPV4_ADDR_SAME (&next1->gate.ipv4, &next2->gate.ipv4))
121 return 0;
122 break;
123 case ZEBRA_NEXTHOP_IFINDEX:
124 case ZEBRA_NEXTHOP_IFNAME:
125 if (next1->ifindex != next2->ifindex)
126 return 0;
127 break;
128#ifdef HAVE_IPV6
129 case ZEBRA_NEXTHOP_IPV6:
130 if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6))
131 return 0;
132 break;
133 case ZEBRA_NEXTHOP_IPV6_IFINDEX:
134 case ZEBRA_NEXTHOP_IPV6_IFNAME:
135 if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6))
136 return 0;
137 if (next1->ifindex != next2->ifindex)
138 return 0;
139 break;
140#endif /* HAVE_IPV6 */
hassofa2b17e2004-03-04 17:45:00 +0000141 default:
142 /* do nothing */
143 break;
paul718e3742002-12-13 20:15:29 +0000144 }
145 return 1;
146}
147
paul94f2b392005-06-28 12:44:16 +0000148static int
Denis Ovsienko8e80bdf2011-08-05 18:52:52 +0400149bgp_nexthop_cache_different (struct bgp_nexthop_cache *bnc1,
paul718e3742002-12-13 20:15:29 +0000150 struct bgp_nexthop_cache *bnc2)
151{
152 int i;
153 struct nexthop *next1, *next2;
154
155 if (bnc1->nexthop_num != bnc2->nexthop_num)
156 return 1;
157
158 next1 = bnc1->nexthop;
159 next2 = bnc2->nexthop;
160
161 for (i = 0; i < bnc1->nexthop_num; i++)
162 {
163 if (! bgp_nexthop_same (next1, next2))
164 return 1;
165
166 next1 = next1->next;
167 next2 = next2->next;
168 }
169 return 0;
170}
171
172/* If nexthop exists on connected network return 1. */
173int
Denis Ovsienko8e80bdf2011-08-05 18:52:52 +0400174bgp_nexthop_onlink (afi_t afi, struct attr *attr)
paul718e3742002-12-13 20:15:29 +0000175{
176 struct bgp_node *rn;
Paul Jakmafc98d162012-01-09 11:36:23 +0000177
178 /* If zebra is not enabled return */
179 if (zlookup->sock < 0)
180 return 1;
181
paul718e3742002-12-13 20:15:29 +0000182 /* Lookup the address is onlink or not. */
183 if (afi == AFI_IP)
184 {
paul59320202004-11-09 01:54:03 +0000185 rn = bgp_node_match_ipv4 (bgp_connected_table[AFI_IP], &attr->nexthop);
paul718e3742002-12-13 20:15:29 +0000186 if (rn)
187 {
188 bgp_unlock_node (rn);
189 return 1;
190 }
191 }
192#ifdef HAVE_IPV6
193 else if (afi == AFI_IP6)
194 {
Paul Jakmafb982c22007-05-04 20:15:47 +0000195 if (attr->extra->mp_nexthop_len == 32)
paul718e3742002-12-13 20:15:29 +0000196 return 1;
Paul Jakmafb982c22007-05-04 20:15:47 +0000197 else if (attr->extra->mp_nexthop_len == 16)
paul718e3742002-12-13 20:15:29 +0000198 {
Paul Jakmafb982c22007-05-04 20:15:47 +0000199 if (IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
paul718e3742002-12-13 20:15:29 +0000200 return 1;
201
paul59320202004-11-09 01:54:03 +0000202 rn = bgp_node_match_ipv6 (bgp_connected_table[AFI_IP6],
Paul Jakmafb982c22007-05-04 20:15:47 +0000203 &attr->extra->mp_nexthop_global);
paul718e3742002-12-13 20:15:29 +0000204 if (rn)
205 {
206 bgp_unlock_node (rn);
207 return 1;
208 }
209 }
210 }
211#endif /* HAVE_IPV6 */
212 return 0;
213}
214
215#ifdef HAVE_IPV6
216/* Check specified next-hop is reachable or not. */
paul94f2b392005-06-28 12:44:16 +0000217static int
paul718e3742002-12-13 20:15:29 +0000218bgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp_info *ri, int *changed,
219 int *metricchanged)
220{
221 struct bgp_node *rn;
222 struct prefix p;
223 struct bgp_nexthop_cache *bnc;
224 struct attr *attr;
Paul Jakmafc98d162012-01-09 11:36:23 +0000225
226 /* If lookup is not enabled, return valid. */
227 if (zlookup->sock < 0)
228 {
229 if (ri->extra)
230 ri->extra->igpmetric = 0;
231 return 1;
232 }
233
paul718e3742002-12-13 20:15:29 +0000234 /* Only check IPv6 global address only nexthop. */
235 attr = ri->attr;
236
Paul Jakmafb982c22007-05-04 20:15:47 +0000237 if (attr->extra->mp_nexthop_len != 16
238 || IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
paul718e3742002-12-13 20:15:29 +0000239 return 1;
240
241 memset (&p, 0, sizeof (struct prefix));
242 p.family = AF_INET6;
243 p.prefixlen = IPV6_MAX_BITLEN;
Paul Jakmafb982c22007-05-04 20:15:47 +0000244 p.u.prefix6 = attr->extra->mp_nexthop_global;
paul718e3742002-12-13 20:15:29 +0000245
246 /* IBGP or ebgp-multihop */
paul59320202004-11-09 01:54:03 +0000247 rn = bgp_node_get (bgp_nexthop_cache_table[AFI_IP6], &p);
paul718e3742002-12-13 20:15:29 +0000248
249 if (rn->info)
250 {
251 bnc = rn->info;
252 bgp_unlock_node (rn);
253 }
254 else
255 {
Denis Ovsienkob64bfc12011-08-08 19:36:44 +0400256 if (NULL == (bnc = zlookup_query_ipv6 (&attr->extra->mp_nexthop_global)))
257 bnc = bnc_new ();
258 else
paul718e3742002-12-13 20:15:29 +0000259 {
paul718e3742002-12-13 20:15:29 +0000260 if (changed)
261 {
Denis Ovsienko8e80bdf2011-08-05 18:52:52 +0400262 struct bgp_table *old;
263 struct bgp_node *oldrn;
264
paul59320202004-11-09 01:54:03 +0000265 if (bgp_nexthop_cache_table[AFI_IP6] == cache1_table[AFI_IP6])
266 old = cache2_table[AFI_IP6];
paul718e3742002-12-13 20:15:29 +0000267 else
paul59320202004-11-09 01:54:03 +0000268 old = cache1_table[AFI_IP6];
paul718e3742002-12-13 20:15:29 +0000269
270 oldrn = bgp_node_lookup (old, &p);
271 if (oldrn)
272 {
Denis Ovsienko8e80bdf2011-08-05 18:52:52 +0400273 struct bgp_nexthop_cache *oldbnc = oldrn->info;
paul718e3742002-12-13 20:15:29 +0000274
Denis Ovsienko8e80bdf2011-08-05 18:52:52 +0400275 bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc);
paul718e3742002-12-13 20:15:29 +0000276
277 if (bnc->metric != oldbnc->metric)
278 bnc->metricchanged = 1;
Chris Caputo6c88b442010-07-27 16:28:55 +0000279
280 bgp_unlock_node (oldrn);
paul718e3742002-12-13 20:15:29 +0000281 }
282 }
283 }
paul718e3742002-12-13 20:15:29 +0000284 rn->info = bnc;
285 }
286
287 if (changed)
288 *changed = bnc->changed;
289
290 if (metricchanged)
291 *metricchanged = bnc->metricchanged;
292
Paul Jakmafb982c22007-05-04 20:15:47 +0000293 if (bnc->valid && bnc->metric)
294 (bgp_info_extra_get (ri))->igpmetric = bnc->metric;
295 else if (ri->extra)
296 ri->extra->igpmetric = 0;
paul718e3742002-12-13 20:15:29 +0000297
298 return bnc->valid;
299}
300#endif /* HAVE_IPV6 */
301
302/* Check specified next-hop is reachable or not. */
303int
304bgp_nexthop_lookup (afi_t afi, struct peer *peer, struct bgp_info *ri,
305 int *changed, int *metricchanged)
306{
307 struct bgp_node *rn;
308 struct prefix p;
309 struct bgp_nexthop_cache *bnc;
310 struct in_addr addr;
Paul Jakmafc98d162012-01-09 11:36:23 +0000311
312 /* If lookup is not enabled, return valid. */
313 if (zlookup->sock < 0)
314 {
315 if (ri->extra)
316 ri->extra->igpmetric = 0;
317 return 1;
318 }
319
paul718e3742002-12-13 20:15:29 +0000320#ifdef HAVE_IPV6
321 if (afi == AFI_IP6)
322 return bgp_nexthop_lookup_ipv6 (peer, ri, changed, metricchanged);
323#endif /* HAVE_IPV6 */
324
325 addr = ri->attr->nexthop;
326
327 memset (&p, 0, sizeof (struct prefix));
328 p.family = AF_INET;
329 p.prefixlen = IPV4_MAX_BITLEN;
330 p.u.prefix4 = addr;
331
332 /* IBGP or ebgp-multihop */
paul59320202004-11-09 01:54:03 +0000333 rn = bgp_node_get (bgp_nexthop_cache_table[AFI_IP], &p);
paul718e3742002-12-13 20:15:29 +0000334
335 if (rn->info)
336 {
337 bnc = rn->info;
338 bgp_unlock_node (rn);
339 }
340 else
341 {
Denis Ovsienkob64bfc12011-08-08 19:36:44 +0400342 if (NULL == (bnc = zlookup_query (addr)))
343 bnc = bnc_new ();
344 else
paul718e3742002-12-13 20:15:29 +0000345 {
paul718e3742002-12-13 20:15:29 +0000346 if (changed)
347 {
Denis Ovsienko8e80bdf2011-08-05 18:52:52 +0400348 struct bgp_table *old;
349 struct bgp_node *oldrn;
350
paul59320202004-11-09 01:54:03 +0000351 if (bgp_nexthop_cache_table[AFI_IP] == cache1_table[AFI_IP])
352 old = cache2_table[AFI_IP];
paul718e3742002-12-13 20:15:29 +0000353 else
paul59320202004-11-09 01:54:03 +0000354 old = cache1_table[AFI_IP];
paul718e3742002-12-13 20:15:29 +0000355
356 oldrn = bgp_node_lookup (old, &p);
357 if (oldrn)
358 {
Denis Ovsienko8e80bdf2011-08-05 18:52:52 +0400359 struct bgp_nexthop_cache *oldbnc = oldrn->info;
paul718e3742002-12-13 20:15:29 +0000360
Denis Ovsienko8e80bdf2011-08-05 18:52:52 +0400361 bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc);
paul718e3742002-12-13 20:15:29 +0000362
363 if (bnc->metric != oldbnc->metric)
364 bnc->metricchanged = 1;
Chris Caputo6c88b442010-07-27 16:28:55 +0000365
366 bgp_unlock_node (oldrn);
paul718e3742002-12-13 20:15:29 +0000367 }
368 }
369 }
paul718e3742002-12-13 20:15:29 +0000370 rn->info = bnc;
371 }
372
373 if (changed)
374 *changed = bnc->changed;
375
376 if (metricchanged)
377 *metricchanged = bnc->metricchanged;
378
Paul Jakmafb982c22007-05-04 20:15:47 +0000379 if (bnc->valid && bnc->metric)
380 (bgp_info_extra_get(ri))->igpmetric = bnc->metric;
381 else if (ri->extra)
382 ri->extra->igpmetric = 0;
paul718e3742002-12-13 20:15:29 +0000383
384 return bnc->valid;
385}
386
387/* Reset and free all BGP nexthop cache. */
paul94f2b392005-06-28 12:44:16 +0000388static void
paul718e3742002-12-13 20:15:29 +0000389bgp_nexthop_cache_reset (struct bgp_table *table)
390{
391 struct bgp_node *rn;
392 struct bgp_nexthop_cache *bnc;
393
394 for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
395 if ((bnc = rn->info) != NULL)
396 {
397 bnc_free (bnc);
398 rn->info = NULL;
399 bgp_unlock_node (rn);
400 }
401}
402
paul94f2b392005-06-28 12:44:16 +0000403static void
paul59320202004-11-09 01:54:03 +0000404bgp_scan (afi_t afi, safi_t safi)
paul718e3742002-12-13 20:15:29 +0000405{
406 struct bgp_node *rn;
407 struct bgp *bgp;
408 struct bgp_info *bi;
409 struct bgp_info *next;
410 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000411 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000412 int valid;
413 int current;
414 int changed;
415 int metricchanged;
416
417 /* Change cache. */
paul59320202004-11-09 01:54:03 +0000418 if (bgp_nexthop_cache_table[afi] == cache1_table[afi])
419 bgp_nexthop_cache_table[afi] = cache2_table[afi];
paul718e3742002-12-13 20:15:29 +0000420 else
paul59320202004-11-09 01:54:03 +0000421 bgp_nexthop_cache_table[afi] = cache1_table[afi];
paul718e3742002-12-13 20:15:29 +0000422
423 /* Get default bgp. */
424 bgp = bgp_get_default ();
425 if (bgp == NULL)
426 return;
427
428 /* Maximum prefix check */
paul1eb8ef22005-04-07 07:30:20 +0000429 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000430 {
431 if (peer->status != Established)
432 continue;
433
paul59320202004-11-09 01:54:03 +0000434 if (peer->afc[afi][SAFI_UNICAST])
435 bgp_maximum_prefix_overflow (peer, afi, SAFI_UNICAST, 1);
436 if (peer->afc[afi][SAFI_MULTICAST])
437 bgp_maximum_prefix_overflow (peer, afi, SAFI_MULTICAST, 1);
438 if (peer->afc[afi][SAFI_MPLS_VPN])
439 bgp_maximum_prefix_overflow (peer, afi, SAFI_MPLS_VPN, 1);
paul718e3742002-12-13 20:15:29 +0000440 }
441
paul59320202004-11-09 01:54:03 +0000442 for (rn = bgp_table_top (bgp->rib[afi][SAFI_UNICAST]); rn;
paul718e3742002-12-13 20:15:29 +0000443 rn = bgp_route_next (rn))
444 {
445 for (bi = rn->info; bi; bi = next)
446 {
447 next = bi->next;
448
449 if (bi->type == ZEBRA_ROUTE_BGP && bi->sub_type == BGP_ROUTE_NORMAL)
450 {
451 changed = 0;
452 metricchanged = 0;
453
454 if (peer_sort (bi->peer) == BGP_PEER_EBGP && bi->peer->ttl == 1)
Denis Ovsienko8e80bdf2011-08-05 18:52:52 +0400455 valid = bgp_nexthop_onlink (afi, bi->attr);
paul718e3742002-12-13 20:15:29 +0000456 else
paul59320202004-11-09 01:54:03 +0000457 valid = bgp_nexthop_lookup (afi, bi->peer, bi,
paul718e3742002-12-13 20:15:29 +0000458 &changed, &metricchanged);
459
460 current = CHECK_FLAG (bi->flags, BGP_INFO_VALID) ? 1 : 0;
461
462 if (changed)
463 SET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED);
464 else
465 UNSET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED);
466
467 if (valid != current)
468 {
469 if (CHECK_FLAG (bi->flags, BGP_INFO_VALID))
470 {
471 bgp_aggregate_decrement (bgp, &rn->p, bi,
paul59320202004-11-09 01:54:03 +0000472 afi, SAFI_UNICAST);
Paul Jakma1a392d42006-09-07 00:24:49 +0000473 bgp_info_unset_flag (rn, bi, BGP_INFO_VALID);
paul718e3742002-12-13 20:15:29 +0000474 }
475 else
476 {
Paul Jakma1a392d42006-09-07 00:24:49 +0000477 bgp_info_set_flag (rn, bi, BGP_INFO_VALID);
paul718e3742002-12-13 20:15:29 +0000478 bgp_aggregate_increment (bgp, &rn->p, bi,
paul59320202004-11-09 01:54:03 +0000479 afi, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000480 }
481 }
482
paul59320202004-11-09 01:54:03 +0000483 if (CHECK_FLAG (bgp->af_flags[afi][SAFI_UNICAST],
paul718e3742002-12-13 20:15:29 +0000484 BGP_CONFIG_DAMPENING)
Paul Jakmafb982c22007-05-04 20:15:47 +0000485 && bi->extra && bi->extra->damp_info )
paul59320202004-11-09 01:54:03 +0000486 if (bgp_damp_scan (bi, afi, SAFI_UNICAST))
paul718e3742002-12-13 20:15:29 +0000487 bgp_aggregate_increment (bgp, &rn->p, bi,
paul59320202004-11-09 01:54:03 +0000488 afi, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000489 }
490 }
paul59320202004-11-09 01:54:03 +0000491 bgp_process (bgp, rn, afi, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000492 }
493
494 /* Flash old cache. */
paul59320202004-11-09 01:54:03 +0000495 if (bgp_nexthop_cache_table[afi] == cache1_table[afi])
496 bgp_nexthop_cache_reset (cache2_table[afi]);
paul718e3742002-12-13 20:15:29 +0000497 else
paul59320202004-11-09 01:54:03 +0000498 bgp_nexthop_cache_reset (cache1_table[afi]);
hassof4184462005-02-01 20:13:16 +0000499
500 if (BGP_DEBUG (events, EVENTS))
501 {
502 if (afi == AFI_IP)
503 zlog_debug ("scanning IPv4 Unicast routing tables");
504 else if (afi == AFI_IP6)
505 zlog_debug ("scanning IPv6 Unicast routing tables");
506 }
paul718e3742002-12-13 20:15:29 +0000507}
508
paul718e3742002-12-13 20:15:29 +0000509/* BGP scan thread. This thread check nexthop reachability. */
paul94f2b392005-06-28 12:44:16 +0000510static int
paul59320202004-11-09 01:54:03 +0000511bgp_scan_timer (struct thread *t)
paul718e3742002-12-13 20:15:29 +0000512{
513 bgp_scan_thread =
paul59320202004-11-09 01:54:03 +0000514 thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval);
paul718e3742002-12-13 20:15:29 +0000515
hassof4184462005-02-01 20:13:16 +0000516 if (BGP_DEBUG (events, EVENTS))
ajs478ba052004-12-08 20:41:23 +0000517 zlog_debug ("Performing BGP general scanning");
paul718e3742002-12-13 20:15:29 +0000518
paul59320202004-11-09 01:54:03 +0000519 bgp_scan (AFI_IP, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000520
521#ifdef HAVE_IPV6
paul59320202004-11-09 01:54:03 +0000522 bgp_scan (AFI_IP6, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000523#endif /* HAVE_IPV6 */
524
525 return 0;
526}
527
paul59320202004-11-09 01:54:03 +0000528struct bgp_connected_ref
paul718e3742002-12-13 20:15:29 +0000529{
530 unsigned int refcnt;
531};
532
533void
534bgp_connected_add (struct connected *ifc)
535{
536 struct prefix p;
537 struct prefix *addr;
paul718e3742002-12-13 20:15:29 +0000538 struct interface *ifp;
539 struct bgp_node *rn;
paul59320202004-11-09 01:54:03 +0000540 struct bgp_connected_ref *bc;
paul718e3742002-12-13 20:15:29 +0000541
542 ifp = ifc->ifp;
543
544 if (! ifp)
545 return;
546
547 if (if_is_loopback (ifp))
548 return;
549
550 addr = ifc->address;
paul718e3742002-12-13 20:15:29 +0000551
552 if (addr->family == AF_INET)
553 {
Andrew J. Schorre4529632006-12-12 19:18:21 +0000554 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
paul718e3742002-12-13 20:15:29 +0000555 apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
556
557 if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
558 return;
559
paul59320202004-11-09 01:54:03 +0000560 rn = bgp_node_get (bgp_connected_table[AFI_IP], (struct prefix *) &p);
paul718e3742002-12-13 20:15:29 +0000561 if (rn->info)
562 {
563 bc = rn->info;
564 bc->refcnt++;
565 }
566 else
567 {
Chris Caputo6c88b442010-07-27 16:28:55 +0000568 bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
paul718e3742002-12-13 20:15:29 +0000569 bc->refcnt = 1;
570 rn->info = bc;
571 }
572 }
573#ifdef HAVE_IPV6
Andrew J. Schorre4529632006-12-12 19:18:21 +0000574 else if (addr->family == AF_INET6)
paul718e3742002-12-13 20:15:29 +0000575 {
Andrew J. Schorre4529632006-12-12 19:18:21 +0000576 PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
paul718e3742002-12-13 20:15:29 +0000577 apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
578
579 if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
580 return;
581
582 if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
583 return;
584
paul59320202004-11-09 01:54:03 +0000585 rn = bgp_node_get (bgp_connected_table[AFI_IP6], (struct prefix *) &p);
paul718e3742002-12-13 20:15:29 +0000586 if (rn->info)
587 {
588 bc = rn->info;
589 bc->refcnt++;
590 }
591 else
592 {
Chris Caputo6c88b442010-07-27 16:28:55 +0000593 bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
paul718e3742002-12-13 20:15:29 +0000594 bc->refcnt = 1;
595 rn->info = bc;
596 }
597 }
598#endif /* HAVE_IPV6 */
599}
600
601void
602bgp_connected_delete (struct connected *ifc)
603{
604 struct prefix p;
605 struct prefix *addr;
paul718e3742002-12-13 20:15:29 +0000606 struct interface *ifp;
607 struct bgp_node *rn;
paul59320202004-11-09 01:54:03 +0000608 struct bgp_connected_ref *bc;
paul718e3742002-12-13 20:15:29 +0000609
610 ifp = ifc->ifp;
611
612 if (if_is_loopback (ifp))
613 return;
614
615 addr = ifc->address;
paul718e3742002-12-13 20:15:29 +0000616
617 if (addr->family == AF_INET)
618 {
Andrew J. Schorre4529632006-12-12 19:18:21 +0000619 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
paul718e3742002-12-13 20:15:29 +0000620 apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
621
622 if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
623 return;
624
paul59320202004-11-09 01:54:03 +0000625 rn = bgp_node_lookup (bgp_connected_table[AFI_IP], &p);
paul718e3742002-12-13 20:15:29 +0000626 if (! rn)
627 return;
628
629 bc = rn->info;
630 bc->refcnt--;
631 if (bc->refcnt == 0)
632 {
Chris Caputo6c88b442010-07-27 16:28:55 +0000633 XFREE (MTYPE_BGP_CONN, bc);
paul718e3742002-12-13 20:15:29 +0000634 rn->info = NULL;
635 }
636 bgp_unlock_node (rn);
637 bgp_unlock_node (rn);
638 }
639#ifdef HAVE_IPV6
640 else if (addr->family == AF_INET6)
641 {
Andrew J. Schorre4529632006-12-12 19:18:21 +0000642 PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
paul718e3742002-12-13 20:15:29 +0000643 apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
644
645 if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
646 return;
647
648 if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
649 return;
650
paul59320202004-11-09 01:54:03 +0000651 rn = bgp_node_lookup (bgp_connected_table[AFI_IP6], (struct prefix *) &p);
paul718e3742002-12-13 20:15:29 +0000652 if (! rn)
653 return;
654
655 bc = rn->info;
656 bc->refcnt--;
657 if (bc->refcnt == 0)
658 {
Chris Caputo6c88b442010-07-27 16:28:55 +0000659 XFREE (MTYPE_BGP_CONN, bc);
paul718e3742002-12-13 20:15:29 +0000660 rn->info = NULL;
661 }
662 bgp_unlock_node (rn);
663 bgp_unlock_node (rn);
664 }
665#endif /* HAVE_IPV6 */
666}
667
668int
669bgp_nexthop_self (afi_t afi, struct attr *attr)
670{
hasso52dc7ee2004-09-23 19:18:23 +0000671 struct listnode *node;
672 struct listnode *node2;
paul718e3742002-12-13 20:15:29 +0000673 struct interface *ifp;
674 struct connected *ifc;
675 struct prefix *p;
676
paul1eb8ef22005-04-07 07:30:20 +0000677 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +0000678 {
paul1eb8ef22005-04-07 07:30:20 +0000679 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc))
paul718e3742002-12-13 20:15:29 +0000680 {
paul718e3742002-12-13 20:15:29 +0000681 p = ifc->address;
682
683 if (p && p->family == AF_INET
684 && IPV4_ADDR_SAME (&p->u.prefix4, &attr->nexthop))
685 return 1;
686 }
687 }
688 return 0;
689}
690
paul94f2b392005-06-28 12:44:16 +0000691static struct bgp_nexthop_cache *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800692zlookup_read (void)
paul718e3742002-12-13 20:15:29 +0000693{
694 struct stream *s;
pauld3092e72006-01-17 17:33:46 +0000695 uint16_t length;
696 u_char marker;
697 u_char version;
698 uint16_t command;
paul718e3742002-12-13 20:15:29 +0000699 int nbytes;
700 struct in_addr raddr;
pauld3092e72006-01-17 17:33:46 +0000701 uint32_t metric;
paul718e3742002-12-13 20:15:29 +0000702 int i;
703 u_char nexthop_num;
704 struct nexthop *nexthop;
705 struct bgp_nexthop_cache *bnc;
706
707 s = zlookup->ibuf;
708 stream_reset (s);
709
710 nbytes = stream_read (s, zlookup->sock, 2);
711 length = stream_getw (s);
712
713 nbytes = stream_read (s, zlookup->sock, length - 2);
pauld3092e72006-01-17 17:33:46 +0000714 marker = stream_getc (s);
715 version = stream_getc (s);
716
717 if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER)
718 {
719 zlog_err("%s: socket %d version mismatch, marker %d, version %d",
720 __func__, zlookup->sock, marker, version);
721 return NULL;
722 }
723
724 command = stream_getw (s);
725
paul718e3742002-12-13 20:15:29 +0000726 raddr.s_addr = stream_get_ipv4 (s);
727 metric = stream_getl (s);
728 nexthop_num = stream_getc (s);
729
730 if (nexthop_num)
731 {
732 bnc = bnc_new ();
733 bnc->valid = 1;
734 bnc->metric = metric;
735 bnc->nexthop_num = nexthop_num;
736
737 for (i = 0; i < nexthop_num; i++)
738 {
Stephen Hemminger393deb92008-08-18 14:13:29 -0700739 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000740 nexthop->type = stream_getc (s);
741 switch (nexthop->type)
742 {
743 case ZEBRA_NEXTHOP_IPV4:
744 nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
745 break;
746 case ZEBRA_NEXTHOP_IFINDEX:
747 case ZEBRA_NEXTHOP_IFNAME:
748 nexthop->ifindex = stream_getl (s);
749 break;
hassofa2b17e2004-03-04 17:45:00 +0000750 default:
751 /* do nothing */
752 break;
paul718e3742002-12-13 20:15:29 +0000753 }
754 bnc_nexthop_add (bnc, nexthop);
755 }
756 }
757 else
758 return NULL;
759
760 return bnc;
761}
762
763struct bgp_nexthop_cache *
764zlookup_query (struct in_addr addr)
765{
766 int ret;
767 struct stream *s;
768
769 /* Check socket. */
770 if (zlookup->sock < 0)
771 return NULL;
772
773 s = zlookup->obuf;
774 stream_reset (s);
pauld3092e72006-01-17 17:33:46 +0000775 zclient_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP);
paul718e3742002-12-13 20:15:29 +0000776 stream_put_in_addr (s, &addr);
pauld3092e72006-01-17 17:33:46 +0000777
778 stream_putw_at (s, 0, stream_get_endp (s));
779
780 ret = writen (zlookup->sock, s->data, stream_get_endp (s));
paul718e3742002-12-13 20:15:29 +0000781 if (ret < 0)
782 {
783 zlog_err ("can't write to zlookup->sock");
784 close (zlookup->sock);
785 zlookup->sock = -1;
786 return NULL;
787 }
788 if (ret == 0)
789 {
790 zlog_err ("zlookup->sock connection closed");
791 close (zlookup->sock);
792 zlookup->sock = -1;
793 return NULL;
794 }
795
796 return zlookup_read ();
797}
798
799#ifdef HAVE_IPV6
paul94f2b392005-06-28 12:44:16 +0000800static struct bgp_nexthop_cache *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800801zlookup_read_ipv6 (void)
paul718e3742002-12-13 20:15:29 +0000802{
803 struct stream *s;
pauld3092e72006-01-17 17:33:46 +0000804 uint16_t length;
805 u_char version, marker;
806 uint16_t command;
paul718e3742002-12-13 20:15:29 +0000807 int nbytes;
808 struct in6_addr raddr;
pauld3092e72006-01-17 17:33:46 +0000809 uint32_t metric;
paul718e3742002-12-13 20:15:29 +0000810 int i;
811 u_char nexthop_num;
812 struct nexthop *nexthop;
813 struct bgp_nexthop_cache *bnc;
814
815 s = zlookup->ibuf;
816 stream_reset (s);
817
818 nbytes = stream_read (s, zlookup->sock, 2);
819 length = stream_getw (s);
820
821 nbytes = stream_read (s, zlookup->sock, length - 2);
pauld3092e72006-01-17 17:33:46 +0000822 marker = stream_getc (s);
823 version = stream_getc (s);
824
825 if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER)
826 {
827 zlog_err("%s: socket %d version mismatch, marker %d, version %d",
828 __func__, zlookup->sock, marker, version);
829 return NULL;
830 }
831
832 command = stream_getw (s);
833
paul718e3742002-12-13 20:15:29 +0000834 stream_get (&raddr, s, 16);
835
836 metric = stream_getl (s);
837 nexthop_num = stream_getc (s);
838
839 if (nexthop_num)
840 {
841 bnc = bnc_new ();
842 bnc->valid = 1;
843 bnc->metric = metric;
844 bnc->nexthop_num = nexthop_num;
845
846 for (i = 0; i < nexthop_num; i++)
847 {
Stephen Hemminger393deb92008-08-18 14:13:29 -0700848 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000849 nexthop->type = stream_getc (s);
850 switch (nexthop->type)
851 {
852 case ZEBRA_NEXTHOP_IPV6:
853 stream_get (&nexthop->gate.ipv6, s, 16);
854 break;
855 case ZEBRA_NEXTHOP_IPV6_IFINDEX:
856 case ZEBRA_NEXTHOP_IPV6_IFNAME:
857 stream_get (&nexthop->gate.ipv6, s, 16);
858 nexthop->ifindex = stream_getl (s);
859 break;
860 case ZEBRA_NEXTHOP_IFINDEX:
861 case ZEBRA_NEXTHOP_IFNAME:
862 nexthop->ifindex = stream_getl (s);
863 break;
hassofa2b17e2004-03-04 17:45:00 +0000864 default:
865 /* do nothing */
866 break;
paul718e3742002-12-13 20:15:29 +0000867 }
868 bnc_nexthop_add (bnc, nexthop);
869 }
870 }
871 else
872 return NULL;
873
874 return bnc;
875}
876
877struct bgp_nexthop_cache *
878zlookup_query_ipv6 (struct in6_addr *addr)
879{
880 int ret;
881 struct stream *s;
882
883 /* Check socket. */
884 if (zlookup->sock < 0)
885 return NULL;
886
887 s = zlookup->obuf;
888 stream_reset (s);
pauld3092e72006-01-17 17:33:46 +0000889 zclient_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP);
paul718e3742002-12-13 20:15:29 +0000890 stream_put (s, addr, 16);
pauld3092e72006-01-17 17:33:46 +0000891 stream_putw_at (s, 0, stream_get_endp (s));
892
893 ret = writen (zlookup->sock, s->data, stream_get_endp (s));
paul718e3742002-12-13 20:15:29 +0000894 if (ret < 0)
895 {
896 zlog_err ("can't write to zlookup->sock");
897 close (zlookup->sock);
898 zlookup->sock = -1;
899 return NULL;
900 }
901 if (ret == 0)
902 {
903 zlog_err ("zlookup->sock connection closed");
904 close (zlookup->sock);
905 zlookup->sock = -1;
906 return NULL;
907 }
908
909 return zlookup_read_ipv6 ();
910}
911#endif /* HAVE_IPV6 */
912
paul94f2b392005-06-28 12:44:16 +0000913static int
914bgp_import_check (struct prefix *p, u_int32_t *igpmetric,
915 struct in_addr *igpnexthop)
paul718e3742002-12-13 20:15:29 +0000916{
917 struct stream *s;
918 int ret;
pauld3092e72006-01-17 17:33:46 +0000919 u_int16_t length, command;
920 u_char version, marker;
paul718e3742002-12-13 20:15:29 +0000921 int nbytes;
922 struct in_addr addr;
923 struct in_addr nexthop;
924 u_int32_t metric = 0;
925 u_char nexthop_num;
926 u_char nexthop_type;
927
928 /* If lookup connection is not available return valid. */
929 if (zlookup->sock < 0)
930 {
931 if (igpmetric)
932 *igpmetric = 0;
933 return 1;
934 }
935
936 /* Send query to the lookup connection */
937 s = zlookup->obuf;
938 stream_reset (s);
pauld3092e72006-01-17 17:33:46 +0000939 zclient_create_header (s, ZEBRA_IPV4_IMPORT_LOOKUP);
940
paul718e3742002-12-13 20:15:29 +0000941 stream_putc (s, p->prefixlen);
942 stream_put_in_addr (s, &p->u.prefix4);
pauld3092e72006-01-17 17:33:46 +0000943
944 stream_putw_at (s, 0, stream_get_endp (s));
945
paul718e3742002-12-13 20:15:29 +0000946 /* Write the packet. */
pauld3092e72006-01-17 17:33:46 +0000947 ret = writen (zlookup->sock, s->data, stream_get_endp (s));
paul718e3742002-12-13 20:15:29 +0000948
949 if (ret < 0)
950 {
951 zlog_err ("can't write to zlookup->sock");
952 close (zlookup->sock);
953 zlookup->sock = -1;
954 return 1;
955 }
956 if (ret == 0)
957 {
958 zlog_err ("zlookup->sock connection closed");
959 close (zlookup->sock);
960 zlookup->sock = -1;
961 return 1;
962 }
963
964 /* Get result. */
965 stream_reset (s);
966
967 /* Fetch length. */
968 nbytes = stream_read (s, zlookup->sock, 2);
969 length = stream_getw (s);
970
971 /* Fetch whole data. */
972 nbytes = stream_read (s, zlookup->sock, length - 2);
pauld3092e72006-01-17 17:33:46 +0000973 marker = stream_getc (s);
974 version = stream_getc (s);
975
976 if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER)
977 {
978 zlog_err("%s: socket %d version mismatch, marker %d, version %d",
979 __func__, zlookup->sock, marker, version);
980 return 0;
981 }
982
983 command = stream_getw (s);
984
paul718e3742002-12-13 20:15:29 +0000985 addr.s_addr = stream_get_ipv4 (s);
986 metric = stream_getl (s);
987 nexthop_num = stream_getc (s);
988
989 /* Set IGP metric value. */
990 if (igpmetric)
991 *igpmetric = metric;
992
993 /* If there is nexthop then this is active route. */
994 if (nexthop_num)
995 {
996 nexthop.s_addr = 0;
997 nexthop_type = stream_getc (s);
998 if (nexthop_type == ZEBRA_NEXTHOP_IPV4)
999 {
1000 nexthop.s_addr = stream_get_ipv4 (s);
1001 if (igpnexthop)
1002 *igpnexthop = nexthop;
1003 }
1004 else
1005 *igpnexthop = nexthop;
1006
1007 return 1;
1008 }
1009 else
1010 return 0;
1011}
1012
1013/* Scan all configured BGP route then check the route exists in IGP or
1014 not. */
paul94f2b392005-06-28 12:44:16 +00001015static int
paul718e3742002-12-13 20:15:29 +00001016bgp_import (struct thread *t)
1017{
1018 struct bgp *bgp;
1019 struct bgp_node *rn;
1020 struct bgp_static *bgp_static;
paul1eb8ef22005-04-07 07:30:20 +00001021 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001022 int valid;
1023 u_int32_t metric;
1024 struct in_addr nexthop;
1025 afi_t afi;
1026 safi_t safi;
1027
1028 bgp_import_thread =
1029 thread_add_timer (master, bgp_import, NULL, bgp_import_interval);
1030
hassof4184462005-02-01 20:13:16 +00001031 if (BGP_DEBUG (events, EVENTS))
1032 zlog_debug ("Import timer expired.");
paul718e3742002-12-13 20:15:29 +00001033
paul1eb8ef22005-04-07 07:30:20 +00001034 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul6cbbc3c2003-04-28 17:11:02 +00001035 {
1036 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1037 for (safi = SAFI_UNICAST; safi < SAFI_MPLS_VPN; safi++)
1038 for (rn = bgp_table_top (bgp->route[afi][safi]); rn;
1039 rn = bgp_route_next (rn))
1040 if ((bgp_static = rn->info) != NULL)
paul718e3742002-12-13 20:15:29 +00001041 {
paul6cbbc3c2003-04-28 17:11:02 +00001042 if (bgp_static->backdoor)
1043 continue;
paul718e3742002-12-13 20:15:29 +00001044
paul6cbbc3c2003-04-28 17:11:02 +00001045 valid = bgp_static->valid;
1046 metric = bgp_static->igpmetric;
1047 nexthop = bgp_static->igpnexthop;
1048
1049 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK)
1050 && afi == AFI_IP && safi == SAFI_UNICAST)
1051 bgp_static->valid = bgp_import_check (&rn->p, &bgp_static->igpmetric,
1052 &bgp_static->igpnexthop);
paul718e3742002-12-13 20:15:29 +00001053 else
paul6cbbc3c2003-04-28 17:11:02 +00001054 {
1055 bgp_static->valid = 1;
1056 bgp_static->igpmetric = 0;
1057 bgp_static->igpnexthop.s_addr = 0;
1058 }
1059
1060 if (bgp_static->valid != valid)
1061 {
1062 if (bgp_static->valid)
1063 bgp_static_update (bgp, &rn->p, bgp_static, afi, safi);
1064 else
1065 bgp_static_withdraw (bgp, &rn->p, afi, safi);
1066 }
1067 else if (bgp_static->valid)
1068 {
1069 if (bgp_static->igpmetric != metric
1070 || bgp_static->igpnexthop.s_addr != nexthop.s_addr
1071 || bgp_static->rmap.name)
1072 bgp_static_update (bgp, &rn->p, bgp_static, afi, safi);
1073 }
paul718e3742002-12-13 20:15:29 +00001074 }
paul6cbbc3c2003-04-28 17:11:02 +00001075 }
paul718e3742002-12-13 20:15:29 +00001076 return 0;
1077}
1078
1079/* Connect to zebra for nexthop lookup. */
paul94f2b392005-06-28 12:44:16 +00001080static int
paul718e3742002-12-13 20:15:29 +00001081zlookup_connect (struct thread *t)
1082{
1083 struct zclient *zlookup;
1084
1085 zlookup = THREAD_ARG (t);
1086 zlookup->t_connect = NULL;
1087
1088 if (zlookup->sock != -1)
1089 return 0;
1090
Vyacheslav Trushkinb5114682011-11-25 18:51:48 +04001091 if (zclient_socket_connect (zlookup) < 0)
paul718e3742002-12-13 20:15:29 +00001092 return -1;
1093
paul718e3742002-12-13 20:15:29 +00001094 return 0;
1095}
1096
1097/* Check specified multiaccess next-hop. */
1098int
1099bgp_multiaccess_check_v4 (struct in_addr nexthop, char *peer)
1100{
1101 struct bgp_node *rn1;
1102 struct bgp_node *rn2;
1103 struct prefix p1;
1104 struct prefix p2;
1105 struct in_addr addr;
1106 int ret;
1107
1108 ret = inet_aton (peer, &addr);
1109 if (! ret)
1110 return 0;
1111
1112 memset (&p1, 0, sizeof (struct prefix));
1113 p1.family = AF_INET;
1114 p1.prefixlen = IPV4_MAX_BITLEN;
1115 p1.u.prefix4 = nexthop;
1116 memset (&p2, 0, sizeof (struct prefix));
1117 p2.family = AF_INET;
1118 p2.prefixlen = IPV4_MAX_BITLEN;
1119 p2.u.prefix4 = addr;
1120
1121 /* If bgp scan is not enabled, return invalid. */
1122 if (zlookup->sock < 0)
1123 return 0;
1124
paul59320202004-11-09 01:54:03 +00001125 rn1 = bgp_node_match (bgp_connected_table[AFI_IP], &p1);
paul718e3742002-12-13 20:15:29 +00001126 if (! rn1)
1127 return 0;
Chris Caputo6c88b442010-07-27 16:28:55 +00001128 bgp_unlock_node (rn1);
paul718e3742002-12-13 20:15:29 +00001129
paul59320202004-11-09 01:54:03 +00001130 rn2 = bgp_node_match (bgp_connected_table[AFI_IP], &p2);
paul718e3742002-12-13 20:15:29 +00001131 if (! rn2)
1132 return 0;
Chris Caputo6c88b442010-07-27 16:28:55 +00001133 bgp_unlock_node (rn2);
paul718e3742002-12-13 20:15:29 +00001134
Chris Caputo6c88b442010-07-27 16:28:55 +00001135 /* This is safe, even with above unlocks, since we are just
1136 comparing pointers to the objects, not the objects themselves. */
paul718e3742002-12-13 20:15:29 +00001137 if (rn1 == rn2)
1138 return 1;
1139
1140 return 0;
1141}
1142
1143DEFUN (bgp_scan_time,
1144 bgp_scan_time_cmd,
1145 "bgp scan-time <5-60>",
1146 "BGP specific commands\n"
1147 "Configure background scanner interval\n"
1148 "Scanner interval (seconds)\n")
1149{
1150 bgp_scan_interval = atoi (argv[0]);
1151
1152 if (bgp_scan_thread)
1153 {
1154 thread_cancel (bgp_scan_thread);
1155 bgp_scan_thread =
paul59320202004-11-09 01:54:03 +00001156 thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval);
paul718e3742002-12-13 20:15:29 +00001157 }
1158
1159 return CMD_SUCCESS;
1160}
1161
1162DEFUN (no_bgp_scan_time,
1163 no_bgp_scan_time_cmd,
1164 "no bgp scan-time",
1165 NO_STR
1166 "BGP specific commands\n"
1167 "Configure background scanner interval\n")
1168{
1169 bgp_scan_interval = BGP_SCAN_INTERVAL_DEFAULT;
1170
1171 if (bgp_scan_thread)
1172 {
1173 thread_cancel (bgp_scan_thread);
1174 bgp_scan_thread =
paul59320202004-11-09 01:54:03 +00001175 thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval);
paul718e3742002-12-13 20:15:29 +00001176 }
1177
1178 return CMD_SUCCESS;
1179}
1180
1181ALIAS (no_bgp_scan_time,
1182 no_bgp_scan_time_val_cmd,
1183 "no bgp scan-time <5-60>",
1184 NO_STR
1185 "BGP specific commands\n"
1186 "Configure background scanner interval\n"
1187 "Scanner interval (seconds)\n")
1188
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001189static int
1190show_ip_bgp_scan_tables (struct vty *vty, const char detail)
paul718e3742002-12-13 20:15:29 +00001191{
1192 struct bgp_node *rn;
1193 struct bgp_nexthop_cache *bnc;
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001194 char buf[INET6_ADDRSTRLEN];
1195 u_char i;
paul718e3742002-12-13 20:15:29 +00001196
1197 if (bgp_scan_thread)
1198 vty_out (vty, "BGP scan is running%s", VTY_NEWLINE);
1199 else
1200 vty_out (vty, "BGP scan is not running%s", VTY_NEWLINE);
1201 vty_out (vty, "BGP scan interval is %d%s", bgp_scan_interval, VTY_NEWLINE);
1202
1203 vty_out (vty, "Current BGP nexthop cache:%s", VTY_NEWLINE);
paul59320202004-11-09 01:54:03 +00001204 for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP]); rn; rn = bgp_route_next (rn))
paul718e3742002-12-13 20:15:29 +00001205 if ((bnc = rn->info) != NULL)
1206 {
1207 if (bnc->valid)
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001208 {
paul718e3742002-12-13 20:15:29 +00001209 vty_out (vty, " %s valid [IGP metric %d]%s",
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001210 inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), bnc->metric, VTY_NEWLINE);
1211 if (detail)
1212 for (i = 0; i < bnc->nexthop_num; i++)
Denis Ovsienko0e8032d2011-08-09 14:42:58 +04001213 switch (bnc->nexthop[i].type)
1214 {
1215 case NEXTHOP_TYPE_IPV4:
1216 vty_out (vty, " gate %s%s", inet_ntop (AF_INET, &bnc->nexthop[i].gate.ipv4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
1217 break;
1218 case NEXTHOP_TYPE_IFINDEX:
1219 vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE);
1220 break;
1221 default:
1222 vty_out (vty, " invalid nexthop type %u%s", bnc->nexthop[i].type, VTY_NEWLINE);
1223 }
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001224 }
paul718e3742002-12-13 20:15:29 +00001225 else
1226 vty_out (vty, " %s invalid%s",
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001227 inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001228 }
1229
1230#ifdef HAVE_IPV6
1231 {
paul59320202004-11-09 01:54:03 +00001232 for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP6]);
1233 rn;
1234 rn = bgp_route_next (rn))
paul718e3742002-12-13 20:15:29 +00001235 if ((bnc = rn->info) != NULL)
1236 {
1237 if (bnc->valid)
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001238 {
paul718e3742002-12-13 20:15:29 +00001239 vty_out (vty, " %s valid [IGP metric %d]%s",
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001240 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00001241 bnc->metric, VTY_NEWLINE);
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001242 if (detail)
1243 for (i = 0; i < bnc->nexthop_num; i++)
Denis Ovsienko0e8032d2011-08-09 14:42:58 +04001244 switch (bnc->nexthop[i].type)
1245 {
1246 case NEXTHOP_TYPE_IPV6:
1247 vty_out (vty, " gate %s%s", inet_ntop (AF_INET6, &bnc->nexthop[i].gate.ipv6, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
1248 break;
1249 case NEXTHOP_TYPE_IFINDEX:
1250 vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE);
1251 break;
1252 default:
1253 vty_out (vty, " invalid nexthop type %u%s", bnc->nexthop[i].type, VTY_NEWLINE);
1254 }
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001255 }
paul718e3742002-12-13 20:15:29 +00001256 else
1257 vty_out (vty, " %s invalid%s",
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001258 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00001259 VTY_NEWLINE);
1260 }
1261 }
1262#endif /* HAVE_IPV6 */
1263
1264 vty_out (vty, "BGP connected route:%s", VTY_NEWLINE);
paul59320202004-11-09 01:54:03 +00001265 for (rn = bgp_table_top (bgp_connected_table[AFI_IP]);
1266 rn;
1267 rn = bgp_route_next (rn))
paul718e3742002-12-13 20:15:29 +00001268 if (rn->info != NULL)
1269 vty_out (vty, " %s/%d%s", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
1270 VTY_NEWLINE);
1271
1272#ifdef HAVE_IPV6
1273 {
paul59320202004-11-09 01:54:03 +00001274 for (rn = bgp_table_top (bgp_connected_table[AFI_IP6]);
1275 rn;
1276 rn = bgp_route_next (rn))
paul718e3742002-12-13 20:15:29 +00001277 if (rn->info != NULL)
1278 vty_out (vty, " %s/%d%s",
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001279 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00001280 rn->p.prefixlen,
1281 VTY_NEWLINE);
1282 }
1283#endif /* HAVE_IPV6 */
1284
1285 return CMD_SUCCESS;
1286}
1287
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001288DEFUN (show_ip_bgp_scan,
1289 show_ip_bgp_scan_cmd,
1290 "show ip bgp scan",
1291 SHOW_STR
1292 IP_STR
1293 BGP_STR
1294 "BGP scan status\n")
1295{
1296 return show_ip_bgp_scan_tables (vty, 0);
1297}
1298
1299DEFUN (show_ip_bgp_scan_detail,
1300 show_ip_bgp_scan_detail_cmd,
1301 "show ip bgp scan detail",
1302 SHOW_STR
1303 IP_STR
1304 BGP_STR
1305 "BGP scan status\n"
1306 "More detailed output\n")
1307{
1308 return show_ip_bgp_scan_tables (vty, 1);
1309}
1310
paul718e3742002-12-13 20:15:29 +00001311int
1312bgp_config_write_scan_time (struct vty *vty)
1313{
1314 if (bgp_scan_interval != BGP_SCAN_INTERVAL_DEFAULT)
1315 vty_out (vty, " bgp scan-time %d%s", bgp_scan_interval, VTY_NEWLINE);
1316 return CMD_SUCCESS;
1317}
1318
1319void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001320bgp_scan_init (void)
paul718e3742002-12-13 20:15:29 +00001321{
1322 zlookup = zclient_new ();
1323 zlookup->sock = -1;
paul718e3742002-12-13 20:15:29 +00001324 zlookup->t_connect = thread_add_event (master, zlookup_connect, zlookup, 0);
1325
1326 bgp_scan_interval = BGP_SCAN_INTERVAL_DEFAULT;
1327 bgp_import_interval = BGP_IMPORT_INTERVAL_DEFAULT;
1328
Paul Jakma64e580a2006-02-21 01:09:01 +00001329 cache1_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
1330 cache2_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
paul59320202004-11-09 01:54:03 +00001331 bgp_nexthop_cache_table[AFI_IP] = cache1_table[AFI_IP];
paul718e3742002-12-13 20:15:29 +00001332
Paul Jakma64e580a2006-02-21 01:09:01 +00001333 bgp_connected_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +00001334
1335#ifdef HAVE_IPV6
Paul Jakma64e580a2006-02-21 01:09:01 +00001336 cache1_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
1337 cache2_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
paul59320202004-11-09 01:54:03 +00001338 bgp_nexthop_cache_table[AFI_IP6] = cache1_table[AFI_IP6];
Paul Jakma64e580a2006-02-21 01:09:01 +00001339 bgp_connected_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +00001340#endif /* HAVE_IPV6 */
1341
1342 /* Make BGP scan thread. */
paul59320202004-11-09 01:54:03 +00001343 bgp_scan_thread = thread_add_timer (master, bgp_scan_timer,
1344 NULL, bgp_scan_interval);
paul6cbbc3c2003-04-28 17:11:02 +00001345 /* Make BGP import there. */
1346 bgp_import_thread = thread_add_timer (master, bgp_import, NULL, 0);
paul718e3742002-12-13 20:15:29 +00001347
1348 install_element (BGP_NODE, &bgp_scan_time_cmd);
1349 install_element (BGP_NODE, &no_bgp_scan_time_cmd);
1350 install_element (BGP_NODE, &no_bgp_scan_time_val_cmd);
1351 install_element (VIEW_NODE, &show_ip_bgp_scan_cmd);
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001352 install_element (VIEW_NODE, &show_ip_bgp_scan_detail_cmd);
Paul Jakma62687ff2008-08-23 14:27:06 +01001353 install_element (RESTRICTED_NODE, &show_ip_bgp_scan_cmd);
paul718e3742002-12-13 20:15:29 +00001354 install_element (ENABLE_NODE, &show_ip_bgp_scan_cmd);
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001355 install_element (ENABLE_NODE, &show_ip_bgp_scan_detail_cmd);
paul718e3742002-12-13 20:15:29 +00001356}
Chris Caputo228da422009-07-18 05:44:03 +00001357
1358void
1359bgp_scan_finish (void)
1360{
Chris Caputo6c88b442010-07-27 16:28:55 +00001361 /* Only the current one needs to be reset. */
1362 bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP]);
1363
Chris Caputo228da422009-07-18 05:44:03 +00001364 bgp_table_unlock (cache1_table[AFI_IP]);
1365 cache1_table[AFI_IP] = NULL;
1366
1367 bgp_table_unlock (cache2_table[AFI_IP]);
1368 cache2_table[AFI_IP] = NULL;
1369
1370 bgp_table_unlock (bgp_connected_table[AFI_IP]);
1371 bgp_connected_table[AFI_IP] = NULL;
1372
1373#ifdef HAVE_IPV6
Chris Caputo6c88b442010-07-27 16:28:55 +00001374 /* Only the current one needs to be reset. */
1375 bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP6]);
1376
Chris Caputo228da422009-07-18 05:44:03 +00001377 bgp_table_unlock (cache1_table[AFI_IP6]);
1378 cache1_table[AFI_IP6] = NULL;
1379
1380 bgp_table_unlock (cache2_table[AFI_IP6]);
1381 cache2_table[AFI_IP6] = NULL;
1382
1383 bgp_table_unlock (bgp_connected_table[AFI_IP6]);
1384 bgp_connected_table[AFI_IP6] = NULL;
1385#endif /* HAVE_IPV6 */
1386}