blob: 24068141c1d54a30783d617f0de212ed8b41f38e [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"
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +000031#include "hash.h"
32#include "jhash.h"
Donald Sharp04907292016-01-07 10:03:01 -050033#include "filter.h"
paul718e3742002-12-13 20:15:29 +000034
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"
40#include "bgpd/bgp_debug.h"
41#include "bgpd/bgp_damp.h"
42#include "zebra/rib.h"
43#include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
44
45struct bgp_nexthop_cache *zlookup_query (struct in_addr);
paul718e3742002-12-13 20:15:29 +000046struct bgp_nexthop_cache *zlookup_query_ipv6 (struct in6_addr *);
David Lamparter6b0655a2014-06-04 06:53:35 +020047
paul718e3742002-12-13 20:15:29 +000048/* Only one BGP scan thread are activated at the same time. */
paul00d252c2005-05-23 14:19:54 +000049static struct thread *bgp_scan_thread = NULL;
paul718e3742002-12-13 20:15:29 +000050
51/* BGP import thread */
paul00d252c2005-05-23 14:19:54 +000052static struct thread *bgp_import_thread = NULL;
paul718e3742002-12-13 20:15:29 +000053
54/* BGP scan interval. */
paul00d252c2005-05-23 14:19:54 +000055static int bgp_scan_interval;
paul718e3742002-12-13 20:15:29 +000056
57/* BGP import interval. */
paul00d252c2005-05-23 14:19:54 +000058static int bgp_import_interval;
paul718e3742002-12-13 20:15:29 +000059
60/* Route table for next-hop lookup cache. */
paul00d252c2005-05-23 14:19:54 +000061static struct bgp_table *bgp_nexthop_cache_table[AFI_MAX];
62static struct bgp_table *cache1_table[AFI_MAX];
63static struct bgp_table *cache2_table[AFI_MAX];
paul718e3742002-12-13 20:15:29 +000064
65/* Route table for connected route. */
paul00d252c2005-05-23 14:19:54 +000066static struct bgp_table *bgp_connected_table[AFI_MAX];
paul718e3742002-12-13 20:15:29 +000067
68/* BGP nexthop lookup query client. */
Chris Caputo228da422009-07-18 05:44:03 +000069struct zclient *zlookup = NULL;
David Lamparter6b0655a2014-06-04 06:53:35 +020070
paul718e3742002-12-13 20:15:29 +000071/* Add nexthop to the end of the list. */
paul94f2b392005-06-28 12:44:16 +000072static void
paul718e3742002-12-13 20:15:29 +000073bnc_nexthop_add (struct bgp_nexthop_cache *bnc, struct nexthop *nexthop)
74{
75 struct nexthop *last;
76
77 for (last = bnc->nexthop; last && last->next; last = last->next)
78 ;
79 if (last)
80 last->next = nexthop;
81 else
82 bnc->nexthop = nexthop;
83 nexthop->prev = last;
84}
85
paul94f2b392005-06-28 12:44:16 +000086static void
paul718e3742002-12-13 20:15:29 +000087bnc_nexthop_free (struct bgp_nexthop_cache *bnc)
88{
89 struct nexthop *nexthop;
90 struct nexthop *next = NULL;
91
92 for (nexthop = bnc->nexthop; nexthop; nexthop = next)
93 {
94 next = nexthop->next;
95 XFREE (MTYPE_NEXTHOP, nexthop);
96 }
97}
98
paul94f2b392005-06-28 12:44:16 +000099static struct bgp_nexthop_cache *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800100bnc_new (void)
paul718e3742002-12-13 20:15:29 +0000101{
Stephen Hemminger393deb92008-08-18 14:13:29 -0700102 return XCALLOC (MTYPE_BGP_NEXTHOP_CACHE, sizeof (struct bgp_nexthop_cache));
paul718e3742002-12-13 20:15:29 +0000103}
104
paul94f2b392005-06-28 12:44:16 +0000105static void
paul718e3742002-12-13 20:15:29 +0000106bnc_free (struct bgp_nexthop_cache *bnc)
107{
108 bnc_nexthop_free (bnc);
109 XFREE (MTYPE_BGP_NEXTHOP_CACHE, bnc);
110}
David Lamparter6b0655a2014-06-04 06:53:35 +0200111
paul94f2b392005-06-28 12:44:16 +0000112static int
paul718e3742002-12-13 20:15:29 +0000113bgp_nexthop_same (struct nexthop *next1, struct nexthop *next2)
114{
115 if (next1->type != next2->type)
116 return 0;
117
118 switch (next1->type)
119 {
120 case ZEBRA_NEXTHOP_IPV4:
121 if (! IPV4_ADDR_SAME (&next1->gate.ipv4, &next2->gate.ipv4))
122 return 0;
123 break;
Christian Frankebb97e462013-05-25 14:01:35 +0000124 case ZEBRA_NEXTHOP_IPV4_IFINDEX:
125 if (! IPV4_ADDR_SAME (&next1->gate.ipv4, &next2->gate.ipv4)
126 || next1->ifindex != next2->ifindex)
127 return 0;
128 break;
paul718e3742002-12-13 20:15:29 +0000129 case ZEBRA_NEXTHOP_IFINDEX:
130 case ZEBRA_NEXTHOP_IFNAME:
131 if (next1->ifindex != next2->ifindex)
132 return 0;
133 break;
paul718e3742002-12-13 20:15:29 +0000134 case ZEBRA_NEXTHOP_IPV6:
135 if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6))
136 return 0;
137 break;
138 case ZEBRA_NEXTHOP_IPV6_IFINDEX:
139 case ZEBRA_NEXTHOP_IPV6_IFNAME:
140 if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6))
141 return 0;
142 if (next1->ifindex != next2->ifindex)
143 return 0;
144 break;
hassofa2b17e2004-03-04 17:45:00 +0000145 default:
146 /* do nothing */
147 break;
paul718e3742002-12-13 20:15:29 +0000148 }
149 return 1;
150}
151
paul94f2b392005-06-28 12:44:16 +0000152static int
Denis Ovsienko8e80bdf2011-08-05 18:52:52 +0400153bgp_nexthop_cache_different (struct bgp_nexthop_cache *bnc1,
paul718e3742002-12-13 20:15:29 +0000154 struct bgp_nexthop_cache *bnc2)
155{
156 int i;
157 struct nexthop *next1, *next2;
158
159 if (bnc1->nexthop_num != bnc2->nexthop_num)
160 return 1;
161
162 next1 = bnc1->nexthop;
163 next2 = bnc2->nexthop;
164
165 for (i = 0; i < bnc1->nexthop_num; i++)
166 {
167 if (! bgp_nexthop_same (next1, next2))
168 return 1;
169
170 next1 = next1->next;
171 next2 = next2->next;
172 }
173 return 0;
174}
175
176/* If nexthop exists on connected network return 1. */
177int
Denis Ovsienko8e80bdf2011-08-05 18:52:52 +0400178bgp_nexthop_onlink (afi_t afi, struct attr *attr)
paul718e3742002-12-13 20:15:29 +0000179{
180 struct bgp_node *rn;
Paul Jakmafc98d162012-01-09 11:36:23 +0000181
182 /* If zebra is not enabled return */
183 if (zlookup->sock < 0)
184 return 1;
185
paul718e3742002-12-13 20:15:29 +0000186 /* Lookup the address is onlink or not. */
187 if (afi == AFI_IP)
188 {
paul59320202004-11-09 01:54:03 +0000189 rn = bgp_node_match_ipv4 (bgp_connected_table[AFI_IP], &attr->nexthop);
paul718e3742002-12-13 20:15:29 +0000190 if (rn)
191 {
192 bgp_unlock_node (rn);
193 return 1;
194 }
195 }
paul718e3742002-12-13 20:15:29 +0000196 else if (afi == AFI_IP6)
197 {
Paul Jakmafb982c22007-05-04 20:15:47 +0000198 if (attr->extra->mp_nexthop_len == 32)
paul718e3742002-12-13 20:15:29 +0000199 return 1;
Paul Jakmafb982c22007-05-04 20:15:47 +0000200 else if (attr->extra->mp_nexthop_len == 16)
paul718e3742002-12-13 20:15:29 +0000201 {
Paul Jakmafb982c22007-05-04 20:15:47 +0000202 if (IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
paul718e3742002-12-13 20:15:29 +0000203 return 1;
204
paul59320202004-11-09 01:54:03 +0000205 rn = bgp_node_match_ipv6 (bgp_connected_table[AFI_IP6],
Paul Jakmafb982c22007-05-04 20:15:47 +0000206 &attr->extra->mp_nexthop_global);
paul718e3742002-12-13 20:15:29 +0000207 if (rn)
208 {
209 bgp_unlock_node (rn);
210 return 1;
211 }
212 }
213 }
paul718e3742002-12-13 20:15:29 +0000214 return 0;
215}
216
paul718e3742002-12-13 20:15:29 +0000217/* Check specified next-hop is reachable or not. */
paul94f2b392005-06-28 12:44:16 +0000218static int
paul718e3742002-12-13 20:15:29 +0000219bgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp_info *ri, int *changed,
220 int *metricchanged)
221{
222 struct bgp_node *rn;
223 struct prefix p;
224 struct bgp_nexthop_cache *bnc;
225 struct attr *attr;
Paul Jakmafc98d162012-01-09 11:36:23 +0000226
227 /* If lookup is not enabled, return valid. */
228 if (zlookup->sock < 0)
229 {
230 if (ri->extra)
231 ri->extra->igpmetric = 0;
232 return 1;
233 }
234
paul718e3742002-12-13 20:15:29 +0000235 /* Only check IPv6 global address only nexthop. */
236 attr = ri->attr;
237
Paul Jakmafb982c22007-05-04 20:15:47 +0000238 if (attr->extra->mp_nexthop_len != 16
239 || IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
paul718e3742002-12-13 20:15:29 +0000240 return 1;
241
242 memset (&p, 0, sizeof (struct prefix));
243 p.family = AF_INET6;
244 p.prefixlen = IPV6_MAX_BITLEN;
Paul Jakmafb982c22007-05-04 20:15:47 +0000245 p.u.prefix6 = attr->extra->mp_nexthop_global;
paul718e3742002-12-13 20:15:29 +0000246
247 /* IBGP or ebgp-multihop */
paul59320202004-11-09 01:54:03 +0000248 rn = bgp_node_get (bgp_nexthop_cache_table[AFI_IP6], &p);
paul718e3742002-12-13 20:15:29 +0000249
250 if (rn->info)
251 {
252 bnc = rn->info;
253 bgp_unlock_node (rn);
254 }
255 else
256 {
Denis Ovsienkob64bfc12011-08-08 19:36:44 +0400257 if (NULL == (bnc = zlookup_query_ipv6 (&attr->extra->mp_nexthop_global)))
258 bnc = bnc_new ();
259 else
paul718e3742002-12-13 20:15:29 +0000260 {
paul718e3742002-12-13 20:15:29 +0000261 if (changed)
262 {
Denis Ovsienko8e80bdf2011-08-05 18:52:52 +0400263 struct bgp_table *old;
264 struct bgp_node *oldrn;
265
paul59320202004-11-09 01:54:03 +0000266 if (bgp_nexthop_cache_table[AFI_IP6] == cache1_table[AFI_IP6])
267 old = cache2_table[AFI_IP6];
paul718e3742002-12-13 20:15:29 +0000268 else
paul59320202004-11-09 01:54:03 +0000269 old = cache1_table[AFI_IP6];
paul718e3742002-12-13 20:15:29 +0000270
271 oldrn = bgp_node_lookup (old, &p);
272 if (oldrn)
273 {
Denis Ovsienko8e80bdf2011-08-05 18:52:52 +0400274 struct bgp_nexthop_cache *oldbnc = oldrn->info;
paul718e3742002-12-13 20:15:29 +0000275
Denis Ovsienko8e80bdf2011-08-05 18:52:52 +0400276 bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc);
paul718e3742002-12-13 20:15:29 +0000277
278 if (bnc->metric != oldbnc->metric)
279 bnc->metricchanged = 1;
Chris Caputo6c88b442010-07-27 16:28:55 +0000280
281 bgp_unlock_node (oldrn);
paul718e3742002-12-13 20:15:29 +0000282 }
283 }
284 }
paul718e3742002-12-13 20:15:29 +0000285 rn->info = bnc;
286 }
287
288 if (changed)
289 *changed = bnc->changed;
290
291 if (metricchanged)
292 *metricchanged = bnc->metricchanged;
293
Paul Jakmafb982c22007-05-04 20:15:47 +0000294 if (bnc->valid && bnc->metric)
295 (bgp_info_extra_get (ri))->igpmetric = bnc->metric;
296 else if (ri->extra)
297 ri->extra->igpmetric = 0;
paul718e3742002-12-13 20:15:29 +0000298
299 return bnc->valid;
300}
paul718e3742002-12-13 20:15:29 +0000301
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 if (afi == AFI_IP6)
321 return bgp_nexthop_lookup_ipv6 (peer, ri, changed, metricchanged);
paul718e3742002-12-13 20:15:29 +0000322
323 addr = ri->attr->nexthop;
324
325 memset (&p, 0, sizeof (struct prefix));
326 p.family = AF_INET;
327 p.prefixlen = IPV4_MAX_BITLEN;
328 p.u.prefix4 = addr;
329
330 /* IBGP or ebgp-multihop */
paul59320202004-11-09 01:54:03 +0000331 rn = bgp_node_get (bgp_nexthop_cache_table[AFI_IP], &p);
paul718e3742002-12-13 20:15:29 +0000332
333 if (rn->info)
334 {
335 bnc = rn->info;
336 bgp_unlock_node (rn);
337 }
338 else
339 {
Denis Ovsienkob64bfc12011-08-08 19:36:44 +0400340 if (NULL == (bnc = zlookup_query (addr)))
341 bnc = bnc_new ();
342 else
paul718e3742002-12-13 20:15:29 +0000343 {
paul718e3742002-12-13 20:15:29 +0000344 if (changed)
345 {
Denis Ovsienko8e80bdf2011-08-05 18:52:52 +0400346 struct bgp_table *old;
347 struct bgp_node *oldrn;
348
paul59320202004-11-09 01:54:03 +0000349 if (bgp_nexthop_cache_table[AFI_IP] == cache1_table[AFI_IP])
350 old = cache2_table[AFI_IP];
paul718e3742002-12-13 20:15:29 +0000351 else
paul59320202004-11-09 01:54:03 +0000352 old = cache1_table[AFI_IP];
paul718e3742002-12-13 20:15:29 +0000353
354 oldrn = bgp_node_lookup (old, &p);
355 if (oldrn)
356 {
Denis Ovsienko8e80bdf2011-08-05 18:52:52 +0400357 struct bgp_nexthop_cache *oldbnc = oldrn->info;
paul718e3742002-12-13 20:15:29 +0000358
Denis Ovsienko8e80bdf2011-08-05 18:52:52 +0400359 bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc);
paul718e3742002-12-13 20:15:29 +0000360
361 if (bnc->metric != oldbnc->metric)
362 bnc->metricchanged = 1;
Chris Caputo6c88b442010-07-27 16:28:55 +0000363
364 bgp_unlock_node (oldrn);
paul718e3742002-12-13 20:15:29 +0000365 }
366 }
367 }
paul718e3742002-12-13 20:15:29 +0000368 rn->info = bnc;
369 }
370
371 if (changed)
372 *changed = bnc->changed;
373
374 if (metricchanged)
375 *metricchanged = bnc->metricchanged;
376
Paul Jakmafb982c22007-05-04 20:15:47 +0000377 if (bnc->valid && bnc->metric)
378 (bgp_info_extra_get(ri))->igpmetric = bnc->metric;
379 else if (ri->extra)
380 ri->extra->igpmetric = 0;
paul718e3742002-12-13 20:15:29 +0000381
382 return bnc->valid;
383}
384
385/* Reset and free all BGP nexthop cache. */
paul94f2b392005-06-28 12:44:16 +0000386static void
paul718e3742002-12-13 20:15:29 +0000387bgp_nexthop_cache_reset (struct bgp_table *table)
388{
389 struct bgp_node *rn;
390 struct bgp_nexthop_cache *bnc;
391
392 for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
393 if ((bnc = rn->info) != NULL)
394 {
395 bnc_free (bnc);
396 rn->info = NULL;
397 bgp_unlock_node (rn);
398 }
399}
400
paul94f2b392005-06-28 12:44:16 +0000401static void
paul59320202004-11-09 01:54:03 +0000402bgp_scan (afi_t afi, safi_t safi)
paul718e3742002-12-13 20:15:29 +0000403{
404 struct bgp_node *rn;
405 struct bgp *bgp;
406 struct bgp_info *bi;
407 struct bgp_info *next;
408 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000409 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000410 int valid;
411 int current;
412 int changed;
413 int metricchanged;
414
415 /* Change cache. */
paul59320202004-11-09 01:54:03 +0000416 if (bgp_nexthop_cache_table[afi] == cache1_table[afi])
417 bgp_nexthop_cache_table[afi] = cache2_table[afi];
paul718e3742002-12-13 20:15:29 +0000418 else
paul59320202004-11-09 01:54:03 +0000419 bgp_nexthop_cache_table[afi] = cache1_table[afi];
paul718e3742002-12-13 20:15:29 +0000420
421 /* Get default bgp. */
422 bgp = bgp_get_default ();
423 if (bgp == NULL)
424 return;
425
426 /* Maximum prefix check */
paul1eb8ef22005-04-07 07:30:20 +0000427 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000428 {
429 if (peer->status != Established)
430 continue;
431
paul59320202004-11-09 01:54:03 +0000432 if (peer->afc[afi][SAFI_UNICAST])
433 bgp_maximum_prefix_overflow (peer, afi, SAFI_UNICAST, 1);
434 if (peer->afc[afi][SAFI_MULTICAST])
435 bgp_maximum_prefix_overflow (peer, afi, SAFI_MULTICAST, 1);
436 if (peer->afc[afi][SAFI_MPLS_VPN])
437 bgp_maximum_prefix_overflow (peer, afi, SAFI_MPLS_VPN, 1);
paul718e3742002-12-13 20:15:29 +0000438 }
439
paul59320202004-11-09 01:54:03 +0000440 for (rn = bgp_table_top (bgp->rib[afi][SAFI_UNICAST]); rn;
paul718e3742002-12-13 20:15:29 +0000441 rn = bgp_route_next (rn))
442 {
443 for (bi = rn->info; bi; bi = next)
444 {
445 next = bi->next;
446
447 if (bi->type == ZEBRA_ROUTE_BGP && bi->sub_type == BGP_ROUTE_NORMAL)
448 {
449 changed = 0;
450 metricchanged = 0;
451
Christian Frankea0f6ce52013-04-11 08:24:30 +0000452 if (bi->peer->sort == BGP_PEER_EBGP && bi->peer->ttl == 1
453 && !CHECK_FLAG(bi->peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
Denis Ovsienko8e80bdf2011-08-05 18:52:52 +0400454 valid = bgp_nexthop_onlink (afi, bi->attr);
paul718e3742002-12-13 20:15:29 +0000455 else
paul59320202004-11-09 01:54:03 +0000456 valid = bgp_nexthop_lookup (afi, bi->peer, bi,
paul718e3742002-12-13 20:15:29 +0000457 &changed, &metricchanged);
458
459 current = CHECK_FLAG (bi->flags, BGP_INFO_VALID) ? 1 : 0;
460
461 if (changed)
462 SET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED);
463 else
464 UNSET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED);
465
466 if (valid != current)
467 {
468 if (CHECK_FLAG (bi->flags, BGP_INFO_VALID))
469 {
470 bgp_aggregate_decrement (bgp, &rn->p, bi,
paul59320202004-11-09 01:54:03 +0000471 afi, SAFI_UNICAST);
Paul Jakma1a392d42006-09-07 00:24:49 +0000472 bgp_info_unset_flag (rn, bi, BGP_INFO_VALID);
paul718e3742002-12-13 20:15:29 +0000473 }
474 else
475 {
Paul Jakma1a392d42006-09-07 00:24:49 +0000476 bgp_info_set_flag (rn, bi, BGP_INFO_VALID);
paul718e3742002-12-13 20:15:29 +0000477 bgp_aggregate_increment (bgp, &rn->p, bi,
paul59320202004-11-09 01:54:03 +0000478 afi, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000479 }
480 }
481
paul59320202004-11-09 01:54:03 +0000482 if (CHECK_FLAG (bgp->af_flags[afi][SAFI_UNICAST],
paul718e3742002-12-13 20:15:29 +0000483 BGP_CONFIG_DAMPENING)
Paul Jakmafb982c22007-05-04 20:15:47 +0000484 && bi->extra && bi->extra->damp_info )
paul59320202004-11-09 01:54:03 +0000485 if (bgp_damp_scan (bi, afi, SAFI_UNICAST))
paul718e3742002-12-13 20:15:29 +0000486 bgp_aggregate_increment (bgp, &rn->p, bi,
paul59320202004-11-09 01:54:03 +0000487 afi, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000488 }
489 }
Paul Jakma91b9e852015-12-01 14:32:11 +0000490 if (rn->info)
491 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 }
Christian Frankedcab1bb2012-12-07 16:45:52 +0000507
508 /* Reevaluate default-originate route-maps and announce/withdraw
509 * default route if neccesary. */
510 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
511 {
512 if (peer->status == Established
513 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
514 && peer->default_rmap[afi][safi].name)
515 bgp_default_originate (peer, afi, safi, 0);
516 }
paul718e3742002-12-13 20:15:29 +0000517}
518
paul718e3742002-12-13 20:15:29 +0000519/* BGP scan thread. This thread check nexthop reachability. */
paul94f2b392005-06-28 12:44:16 +0000520static int
paul59320202004-11-09 01:54:03 +0000521bgp_scan_timer (struct thread *t)
paul718e3742002-12-13 20:15:29 +0000522{
523 bgp_scan_thread =
Donald Sharp774914f2015-10-14 08:50:39 -0400524 thread_add_timer (bm->master, bgp_scan_timer, NULL, bgp_scan_interval);
paul718e3742002-12-13 20:15:29 +0000525
hassof4184462005-02-01 20:13:16 +0000526 if (BGP_DEBUG (events, EVENTS))
ajs478ba052004-12-08 20:41:23 +0000527 zlog_debug ("Performing BGP general scanning");
paul718e3742002-12-13 20:15:29 +0000528
paul59320202004-11-09 01:54:03 +0000529 bgp_scan (AFI_IP, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000530
paul59320202004-11-09 01:54:03 +0000531 bgp_scan (AFI_IP6, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000532
533 return 0;
534}
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +0000535
536/* BGP own address structure */
537struct bgp_addr
538{
539 struct in_addr addr;
540 int refcnt;
541};
542
543static struct hash *bgp_address_hash;
544
545static void *
546bgp_address_hash_alloc (void *p)
547{
548 struct in_addr *val = p;
549 struct bgp_addr *addr;
550
551 addr = XMALLOC (MTYPE_BGP_ADDR, sizeof (struct bgp_addr));
552 addr->refcnt = 0;
553 addr->addr.s_addr = val->s_addr;
554
555 return addr;
556}
557
558static unsigned int
559bgp_address_hash_key_make (void *p)
560{
561 const struct bgp_addr *addr = p;
562
563 return jhash_1word(addr->addr.s_addr, 0);
564}
565
566static int
567bgp_address_hash_cmp (const void *p1, const void *p2)
568{
569 const struct bgp_addr *addr1 = p1;
570 const struct bgp_addr *addr2 = p2;
571
572 return addr1->addr.s_addr == addr2->addr.s_addr;
573}
574
575void
576bgp_address_init (void)
577{
578 bgp_address_hash = hash_create (bgp_address_hash_key_make,
579 bgp_address_hash_cmp);
580}
581
Lou Berger82dd7072016-01-12 13:41:57 -0500582void
583bgp_address_destroy (void)
584{
Lou Bergerd5d5e3e2016-01-12 13:41:58 -0500585 if (bgp_address_hash == NULL)
586 return;
587
Lou Berger82dd7072016-01-12 13:41:57 -0500588 hash_clean(bgp_address_hash, NULL);
589 hash_free(bgp_address_hash);
590 bgp_address_hash = NULL;
591}
592
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +0000593static void
594bgp_address_add (struct prefix *p)
595{
596 struct bgp_addr tmp;
597 struct bgp_addr *addr;
598
599 tmp.addr = p->u.prefix4;
600
601 addr = hash_get (bgp_address_hash, &tmp, bgp_address_hash_alloc);
602 addr->refcnt++;
603}
604
605static void
606bgp_address_del (struct prefix *p)
607{
608 struct bgp_addr tmp;
609 struct bgp_addr *addr;
610
611 tmp.addr = p->u.prefix4;
612
613 addr = hash_lookup (bgp_address_hash, &tmp);
Rakesh Garimella9e47abd2013-03-11 12:38:31 +0000614 /* may have been deleted earlier by bgp_interface_down() */
615 if (addr == NULL)
616 return;
617
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +0000618 addr->refcnt--;
619
620 if (addr->refcnt == 0)
621 {
622 hash_release (bgp_address_hash, addr);
623 XFREE (MTYPE_BGP_ADDR, addr);
624 }
625}
626
David Lamparter6b0655a2014-06-04 06:53:35 +0200627
paul59320202004-11-09 01:54:03 +0000628struct bgp_connected_ref
paul718e3742002-12-13 20:15:29 +0000629{
630 unsigned int refcnt;
631};
632
633void
634bgp_connected_add (struct connected *ifc)
635{
636 struct prefix p;
637 struct prefix *addr;
paul718e3742002-12-13 20:15:29 +0000638 struct interface *ifp;
639 struct bgp_node *rn;
paul59320202004-11-09 01:54:03 +0000640 struct bgp_connected_ref *bc;
paul718e3742002-12-13 20:15:29 +0000641
642 ifp = ifc->ifp;
643
644 if (! ifp)
645 return;
646
647 if (if_is_loopback (ifp))
648 return;
649
650 addr = ifc->address;
paul718e3742002-12-13 20:15:29 +0000651
Donald Sharp26a18eb2015-09-29 09:25:10 -0400652 p = *(CONNECTED_PREFIX(ifc));
paul718e3742002-12-13 20:15:29 +0000653 if (addr->family == AF_INET)
654 {
paul718e3742002-12-13 20:15:29 +0000655 apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
656
657 if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
658 return;
659
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +0000660 bgp_address_add (addr);
661
paul59320202004-11-09 01:54:03 +0000662 rn = bgp_node_get (bgp_connected_table[AFI_IP], (struct prefix *) &p);
paul718e3742002-12-13 20:15:29 +0000663 if (rn->info)
664 {
665 bc = rn->info;
666 bc->refcnt++;
667 }
668 else
669 {
Chris Caputo6c88b442010-07-27 16:28:55 +0000670 bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
paul718e3742002-12-13 20:15:29 +0000671 bc->refcnt = 1;
672 rn->info = bc;
673 }
674 }
Andrew J. Schorre4529632006-12-12 19:18:21 +0000675 else if (addr->family == AF_INET6)
paul718e3742002-12-13 20:15:29 +0000676 {
paul718e3742002-12-13 20:15:29 +0000677 apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
678
679 if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
680 return;
681
682 if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
683 return;
684
paul59320202004-11-09 01:54:03 +0000685 rn = bgp_node_get (bgp_connected_table[AFI_IP6], (struct prefix *) &p);
paul718e3742002-12-13 20:15:29 +0000686 if (rn->info)
687 {
688 bc = rn->info;
689 bc->refcnt++;
690 }
691 else
692 {
Chris Caputo6c88b442010-07-27 16:28:55 +0000693 bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
paul718e3742002-12-13 20:15:29 +0000694 bc->refcnt = 1;
695 rn->info = bc;
696 }
697 }
paul718e3742002-12-13 20:15:29 +0000698}
699
700void
701bgp_connected_delete (struct connected *ifc)
702{
703 struct prefix p;
704 struct prefix *addr;
paul718e3742002-12-13 20:15:29 +0000705 struct interface *ifp;
706 struct bgp_node *rn;
paul59320202004-11-09 01:54:03 +0000707 struct bgp_connected_ref *bc;
paul718e3742002-12-13 20:15:29 +0000708
709 ifp = ifc->ifp;
710
711 if (if_is_loopback (ifp))
712 return;
713
714 addr = ifc->address;
paul718e3742002-12-13 20:15:29 +0000715
Donald Sharp26a18eb2015-09-29 09:25:10 -0400716 p = *(CONNECTED_PREFIX(ifc));
paul718e3742002-12-13 20:15:29 +0000717 if (addr->family == AF_INET)
718 {
paul718e3742002-12-13 20:15:29 +0000719 apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
720
721 if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
722 return;
723
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +0000724 bgp_address_del (addr);
725
paul59320202004-11-09 01:54:03 +0000726 rn = bgp_node_lookup (bgp_connected_table[AFI_IP], &p);
paul718e3742002-12-13 20:15:29 +0000727 if (! rn)
728 return;
729
730 bc = rn->info;
731 bc->refcnt--;
732 if (bc->refcnt == 0)
733 {
Chris Caputo6c88b442010-07-27 16:28:55 +0000734 XFREE (MTYPE_BGP_CONN, bc);
paul718e3742002-12-13 20:15:29 +0000735 rn->info = NULL;
736 }
737 bgp_unlock_node (rn);
738 bgp_unlock_node (rn);
739 }
paul718e3742002-12-13 20:15:29 +0000740 else if (addr->family == AF_INET6)
741 {
paul718e3742002-12-13 20:15:29 +0000742 apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
743
744 if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
745 return;
746
747 if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
748 return;
749
paul59320202004-11-09 01:54:03 +0000750 rn = bgp_node_lookup (bgp_connected_table[AFI_IP6], (struct prefix *) &p);
paul718e3742002-12-13 20:15:29 +0000751 if (! rn)
752 return;
753
754 bc = rn->info;
755 bc->refcnt--;
756 if (bc->refcnt == 0)
757 {
Chris Caputo6c88b442010-07-27 16:28:55 +0000758 XFREE (MTYPE_BGP_CONN, bc);
paul718e3742002-12-13 20:15:29 +0000759 rn->info = NULL;
760 }
761 bgp_unlock_node (rn);
762 bgp_unlock_node (rn);
763 }
paul718e3742002-12-13 20:15:29 +0000764}
765
766int
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +0000767bgp_nexthop_self (struct attr *attr)
paul718e3742002-12-13 20:15:29 +0000768{
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +0000769 struct bgp_addr tmp, *addr;
paul718e3742002-12-13 20:15:29 +0000770
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +0000771 tmp.addr = attr->nexthop;
paul718e3742002-12-13 20:15:29 +0000772
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +0000773 addr = hash_lookup (bgp_address_hash, &tmp);
774 if (addr)
775 return 1;
776
paul718e3742002-12-13 20:15:29 +0000777 return 0;
778}
David Lamparter6b0655a2014-06-04 06:53:35 +0200779
paul94f2b392005-06-28 12:44:16 +0000780static struct bgp_nexthop_cache *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800781zlookup_read (void)
paul718e3742002-12-13 20:15:29 +0000782{
783 struct stream *s;
pauld3092e72006-01-17 17:33:46 +0000784 uint16_t length;
785 u_char marker;
786 u_char version;
Nicolas Dichtel794c4732015-09-16 09:42:36 +0200787 uint16_t vrf_id;
788 uint16_t command;
789 int err;
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100790 struct in_addr raddr __attribute__((unused));
pauld3092e72006-01-17 17:33:46 +0000791 uint32_t metric;
paul718e3742002-12-13 20:15:29 +0000792 int i;
793 u_char nexthop_num;
794 struct nexthop *nexthop;
795 struct bgp_nexthop_cache *bnc;
796
797 s = zlookup->ibuf;
798 stream_reset (s);
799
Nicolas Dichtel794c4732015-09-16 09:42:36 +0200800 err = zclient_read_header (s, zlookup->sock, &length, &marker, &version,
801 &vrf_id, &command);
802 if (err < 0)
803 {
804 zlog_err("%s: zserv_read_header() failed", __func__);
805 return NULL;
806 }
Donald Sharpa9d4cb32015-09-17 10:54:25 -0400807
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100808 /* XXX: not doing anything with raddr */
paul718e3742002-12-13 20:15:29 +0000809 raddr.s_addr = stream_get_ipv4 (s);
810 metric = stream_getl (s);
811 nexthop_num = stream_getc (s);
812
813 if (nexthop_num)
814 {
815 bnc = bnc_new ();
816 bnc->valid = 1;
817 bnc->metric = metric;
818 bnc->nexthop_num = nexthop_num;
819
820 for (i = 0; i < nexthop_num; i++)
821 {
Stephen Hemminger393deb92008-08-18 14:13:29 -0700822 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000823 nexthop->type = stream_getc (s);
824 switch (nexthop->type)
825 {
826 case ZEBRA_NEXTHOP_IPV4:
827 nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
828 break;
Christian Frankebb97e462013-05-25 14:01:35 +0000829 case ZEBRA_NEXTHOP_IPV4_IFINDEX:
830 nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
831 nexthop->ifindex = stream_getl (s);
832 break;
paul718e3742002-12-13 20:15:29 +0000833 case ZEBRA_NEXTHOP_IFINDEX:
834 case ZEBRA_NEXTHOP_IFNAME:
835 nexthop->ifindex = stream_getl (s);
836 break;
hassofa2b17e2004-03-04 17:45:00 +0000837 default:
838 /* do nothing */
839 break;
paul718e3742002-12-13 20:15:29 +0000840 }
841 bnc_nexthop_add (bnc, nexthop);
842 }
843 }
844 else
845 return NULL;
846
847 return bnc;
848}
849
850struct bgp_nexthop_cache *
851zlookup_query (struct in_addr addr)
852{
853 int ret;
854 struct stream *s;
855
856 /* Check socket. */
857 if (zlookup->sock < 0)
858 return NULL;
859
860 s = zlookup->obuf;
861 stream_reset (s);
Feng Luc99f3482014-10-16 09:52:36 +0800862 zclient_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +0000863 stream_put_in_addr (s, &addr);
pauld3092e72006-01-17 17:33:46 +0000864
865 stream_putw_at (s, 0, stream_get_endp (s));
866
867 ret = writen (zlookup->sock, s->data, stream_get_endp (s));
paul718e3742002-12-13 20:15:29 +0000868 if (ret < 0)
869 {
870 zlog_err ("can't write to zlookup->sock");
871 close (zlookup->sock);
872 zlookup->sock = -1;
873 return NULL;
874 }
875 if (ret == 0)
876 {
877 zlog_err ("zlookup->sock connection closed");
878 close (zlookup->sock);
879 zlookup->sock = -1;
880 return NULL;
881 }
882
883 return zlookup_read ();
884}
885
paul94f2b392005-06-28 12:44:16 +0000886static struct bgp_nexthop_cache *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800887zlookup_read_ipv6 (void)
paul718e3742002-12-13 20:15:29 +0000888{
889 struct stream *s;
Nicolas Dichtel794c4732015-09-16 09:42:36 +0200890 uint16_t length, vrf_id, cmd;
pauld3092e72006-01-17 17:33:46 +0000891 u_char version, marker;
paul718e3742002-12-13 20:15:29 +0000892 struct in6_addr raddr;
pauld3092e72006-01-17 17:33:46 +0000893 uint32_t metric;
Nicolas Dichtel794c4732015-09-16 09:42:36 +0200894 int i, err;
paul718e3742002-12-13 20:15:29 +0000895 u_char nexthop_num;
896 struct nexthop *nexthop;
897 struct bgp_nexthop_cache *bnc;
898
899 s = zlookup->ibuf;
900 stream_reset (s);
901
Nicolas Dichtel794c4732015-09-16 09:42:36 +0200902 err = zclient_read_header (s, zlookup->sock, &length, &marker, &version,
903 &vrf_id, &cmd);
904 if (err < 0)
905 {
906 zlog_err("%s: zserv_read_header() failed", __func__);
907 return NULL;
908 }
Donald Sharpa9d4cb32015-09-17 10:54:25 -0400909
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100910 /* XXX: not actually doing anything with raddr */
paul718e3742002-12-13 20:15:29 +0000911 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 {
Stephen Hemminger393deb92008-08-18 14:13:29 -0700925 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000926 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;
hassofa2b17e2004-03-04 17:45:00 +0000941 default:
942 /* do nothing */
943 break;
paul718e3742002-12-13 20:15:29 +0000944 }
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);
Feng Luc99f3482014-10-16 09:52:36 +0800966 zclient_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +0000967 stream_put (s, addr, 16);
pauld3092e72006-01-17 17:33:46 +0000968 stream_putw_at (s, 0, stream_get_endp (s));
969
970 ret = writen (zlookup->sock, s->data, stream_get_endp (s));
paul718e3742002-12-13 20:15:29 +0000971 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}
paul718e3742002-12-13 20:15:29 +0000988
paul94f2b392005-06-28 12:44:16 +0000989static int
990bgp_import_check (struct prefix *p, u_int32_t *igpmetric,
991 struct in_addr *igpnexthop)
paul718e3742002-12-13 20:15:29 +0000992{
993 struct stream *s;
994 int ret;
Nicolas Dichtel794c4732015-09-16 09:42:36 +0200995 u_int16_t length, vrf_id, command;
pauld3092e72006-01-17 17:33:46 +0000996 u_char version, marker;
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100997 struct in_addr addr __attribute__((unused));
paul718e3742002-12-13 20:15:29 +0000998 struct in_addr nexthop;
999 u_int32_t metric = 0;
1000 u_char nexthop_num;
1001 u_char nexthop_type;
1002
1003 /* If lookup connection is not available return valid. */
1004 if (zlookup->sock < 0)
1005 {
1006 if (igpmetric)
1007 *igpmetric = 0;
1008 return 1;
1009 }
1010
1011 /* Send query to the lookup connection */
1012 s = zlookup->obuf;
1013 stream_reset (s);
Feng Luc99f3482014-10-16 09:52:36 +08001014 zclient_create_header (s, ZEBRA_IPV4_IMPORT_LOOKUP, VRF_DEFAULT);
pauld3092e72006-01-17 17:33:46 +00001015
paul718e3742002-12-13 20:15:29 +00001016 stream_putc (s, p->prefixlen);
1017 stream_put_in_addr (s, &p->u.prefix4);
pauld3092e72006-01-17 17:33:46 +00001018
1019 stream_putw_at (s, 0, stream_get_endp (s));
1020
paul718e3742002-12-13 20:15:29 +00001021 /* Write the packet. */
pauld3092e72006-01-17 17:33:46 +00001022 ret = writen (zlookup->sock, s->data, stream_get_endp (s));
paul718e3742002-12-13 20:15:29 +00001023
1024 if (ret < 0)
1025 {
1026 zlog_err ("can't write to zlookup->sock");
1027 close (zlookup->sock);
1028 zlookup->sock = -1;
1029 return 1;
1030 }
1031 if (ret == 0)
1032 {
1033 zlog_err ("zlookup->sock connection closed");
1034 close (zlookup->sock);
1035 zlookup->sock = -1;
1036 return 1;
1037 }
1038
1039 /* Get result. */
1040 stream_reset (s);
1041
Nicolas Dichtel794c4732015-09-16 09:42:36 +02001042 ret = zclient_read_header (s, zlookup->sock, &length, &marker, &version,
1043 &vrf_id, &command);
1044 if (ret < 0)
1045 {
1046 zlog_err("%s: zserv_read_header() failed", __func__);
1047 return 0;
1048 }
Donald Sharpa9d4cb32015-09-17 10:54:25 -04001049
Paul Jakma7aa9dce2014-09-19 14:42:23 +01001050 /* XXX: not using addr */
paul718e3742002-12-13 20:15:29 +00001051 addr.s_addr = stream_get_ipv4 (s);
1052 metric = stream_getl (s);
1053 nexthop_num = stream_getc (s);
1054
1055 /* Set IGP metric value. */
1056 if (igpmetric)
1057 *igpmetric = metric;
1058
1059 /* If there is nexthop then this is active route. */
1060 if (nexthop_num)
1061 {
1062 nexthop.s_addr = 0;
1063 nexthop_type = stream_getc (s);
Christian Frankea12afd52013-05-25 14:01:36 +00001064 switch (nexthop_type)
paul718e3742002-12-13 20:15:29 +00001065 {
Christian Frankea12afd52013-05-25 14:01:36 +00001066 case ZEBRA_NEXTHOP_IPV4:
paul718e3742002-12-13 20:15:29 +00001067 nexthop.s_addr = stream_get_ipv4 (s);
Christian Frankea12afd52013-05-25 14:01:36 +00001068 break;
1069 case ZEBRA_NEXTHOP_IPV4_IFINDEX:
1070 nexthop.s_addr = stream_get_ipv4 (s);
1071 /* ifindex */ (void)stream_getl (s);
1072 break;
1073 default:
1074 /* do nothing */
1075 break;
paul718e3742002-12-13 20:15:29 +00001076 }
Christian Frankea12afd52013-05-25 14:01:36 +00001077 *igpnexthop = nexthop;
paul718e3742002-12-13 20:15:29 +00001078
1079 return 1;
1080 }
1081 else
1082 return 0;
1083}
1084
1085/* Scan all configured BGP route then check the route exists in IGP or
1086 not. */
paul94f2b392005-06-28 12:44:16 +00001087static int
paul718e3742002-12-13 20:15:29 +00001088bgp_import (struct thread *t)
1089{
1090 struct bgp *bgp;
1091 struct bgp_node *rn;
1092 struct bgp_static *bgp_static;
paul1eb8ef22005-04-07 07:30:20 +00001093 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001094 int valid;
1095 u_int32_t metric;
1096 struct in_addr nexthop;
1097 afi_t afi;
1098 safi_t safi;
1099
1100 bgp_import_thread =
Donald Sharp774914f2015-10-14 08:50:39 -04001101 thread_add_timer (bm->master, bgp_import, NULL, bgp_import_interval);
paul718e3742002-12-13 20:15:29 +00001102
hassof4184462005-02-01 20:13:16 +00001103 if (BGP_DEBUG (events, EVENTS))
1104 zlog_debug ("Import timer expired.");
paul718e3742002-12-13 20:15:29 +00001105
paul1eb8ef22005-04-07 07:30:20 +00001106 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul6cbbc3c2003-04-28 17:11:02 +00001107 {
1108 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1109 for (safi = SAFI_UNICAST; safi < SAFI_MPLS_VPN; safi++)
1110 for (rn = bgp_table_top (bgp->route[afi][safi]); rn;
1111 rn = bgp_route_next (rn))
1112 if ((bgp_static = rn->info) != NULL)
paul718e3742002-12-13 20:15:29 +00001113 {
paul6cbbc3c2003-04-28 17:11:02 +00001114 if (bgp_static->backdoor)
1115 continue;
paul718e3742002-12-13 20:15:29 +00001116
paul6cbbc3c2003-04-28 17:11:02 +00001117 valid = bgp_static->valid;
1118 metric = bgp_static->igpmetric;
1119 nexthop = bgp_static->igpnexthop;
1120
1121 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK)
1122 && afi == AFI_IP && safi == SAFI_UNICAST)
1123 bgp_static->valid = bgp_import_check (&rn->p, &bgp_static->igpmetric,
1124 &bgp_static->igpnexthop);
paul718e3742002-12-13 20:15:29 +00001125 else
paul6cbbc3c2003-04-28 17:11:02 +00001126 {
1127 bgp_static->valid = 1;
1128 bgp_static->igpmetric = 0;
1129 bgp_static->igpnexthop.s_addr = 0;
1130 }
1131
1132 if (bgp_static->valid != valid)
1133 {
1134 if (bgp_static->valid)
1135 bgp_static_update (bgp, &rn->p, bgp_static, afi, safi);
1136 else
1137 bgp_static_withdraw (bgp, &rn->p, afi, safi);
1138 }
1139 else if (bgp_static->valid)
1140 {
1141 if (bgp_static->igpmetric != metric
1142 || bgp_static->igpnexthop.s_addr != nexthop.s_addr
1143 || bgp_static->rmap.name)
1144 bgp_static_update (bgp, &rn->p, bgp_static, afi, safi);
1145 }
paul718e3742002-12-13 20:15:29 +00001146 }
paul6cbbc3c2003-04-28 17:11:02 +00001147 }
paul718e3742002-12-13 20:15:29 +00001148 return 0;
1149}
1150
1151/* Connect to zebra for nexthop lookup. */
paul94f2b392005-06-28 12:44:16 +00001152static int
paul718e3742002-12-13 20:15:29 +00001153zlookup_connect (struct thread *t)
1154{
1155 struct zclient *zlookup;
1156
1157 zlookup = THREAD_ARG (t);
1158 zlookup->t_connect = NULL;
1159
1160 if (zlookup->sock != -1)
1161 return 0;
1162
Vyacheslav Trushkinb5114682011-11-25 18:51:48 +04001163 if (zclient_socket_connect (zlookup) < 0)
paul718e3742002-12-13 20:15:29 +00001164 return -1;
1165
paul718e3742002-12-13 20:15:29 +00001166 return 0;
1167}
1168
1169/* Check specified multiaccess next-hop. */
1170int
1171bgp_multiaccess_check_v4 (struct in_addr nexthop, char *peer)
1172{
1173 struct bgp_node *rn1;
1174 struct bgp_node *rn2;
1175 struct prefix p1;
1176 struct prefix p2;
1177 struct in_addr addr;
1178 int ret;
1179
1180 ret = inet_aton (peer, &addr);
1181 if (! ret)
1182 return 0;
1183
1184 memset (&p1, 0, sizeof (struct prefix));
1185 p1.family = AF_INET;
1186 p1.prefixlen = IPV4_MAX_BITLEN;
1187 p1.u.prefix4 = nexthop;
1188 memset (&p2, 0, sizeof (struct prefix));
1189 p2.family = AF_INET;
1190 p2.prefixlen = IPV4_MAX_BITLEN;
1191 p2.u.prefix4 = addr;
1192
1193 /* If bgp scan is not enabled, return invalid. */
1194 if (zlookup->sock < 0)
1195 return 0;
1196
paul59320202004-11-09 01:54:03 +00001197 rn1 = bgp_node_match (bgp_connected_table[AFI_IP], &p1);
paul718e3742002-12-13 20:15:29 +00001198 if (! rn1)
1199 return 0;
Chris Caputo6c88b442010-07-27 16:28:55 +00001200 bgp_unlock_node (rn1);
paul718e3742002-12-13 20:15:29 +00001201
paul59320202004-11-09 01:54:03 +00001202 rn2 = bgp_node_match (bgp_connected_table[AFI_IP], &p2);
paul718e3742002-12-13 20:15:29 +00001203 if (! rn2)
1204 return 0;
Chris Caputo6c88b442010-07-27 16:28:55 +00001205 bgp_unlock_node (rn2);
paul718e3742002-12-13 20:15:29 +00001206
Chris Caputo6c88b442010-07-27 16:28:55 +00001207 /* This is safe, even with above unlocks, since we are just
1208 comparing pointers to the objects, not the objects themselves. */
paul718e3742002-12-13 20:15:29 +00001209 if (rn1 == rn2)
1210 return 1;
1211
1212 return 0;
1213}
David Lamparter6b0655a2014-06-04 06:53:35 +02001214
paul718e3742002-12-13 20:15:29 +00001215DEFUN (bgp_scan_time,
1216 bgp_scan_time_cmd,
1217 "bgp scan-time <5-60>",
1218 "BGP specific commands\n"
1219 "Configure background scanner interval\n"
1220 "Scanner interval (seconds)\n")
1221{
1222 bgp_scan_interval = atoi (argv[0]);
1223
1224 if (bgp_scan_thread)
1225 {
1226 thread_cancel (bgp_scan_thread);
1227 bgp_scan_thread =
Donald Sharp774914f2015-10-14 08:50:39 -04001228 thread_add_timer (bm->master, bgp_scan_timer, NULL, bgp_scan_interval);
paul718e3742002-12-13 20:15:29 +00001229 }
1230
1231 return CMD_SUCCESS;
1232}
1233
1234DEFUN (no_bgp_scan_time,
1235 no_bgp_scan_time_cmd,
1236 "no bgp scan-time",
1237 NO_STR
1238 "BGP specific commands\n"
1239 "Configure background scanner interval\n")
1240{
1241 bgp_scan_interval = BGP_SCAN_INTERVAL_DEFAULT;
1242
1243 if (bgp_scan_thread)
1244 {
1245 thread_cancel (bgp_scan_thread);
1246 bgp_scan_thread =
Donald Sharp774914f2015-10-14 08:50:39 -04001247 thread_add_timer (bm->master, bgp_scan_timer, NULL, bgp_scan_interval);
paul718e3742002-12-13 20:15:29 +00001248 }
1249
1250 return CMD_SUCCESS;
1251}
1252
1253ALIAS (no_bgp_scan_time,
1254 no_bgp_scan_time_val_cmd,
1255 "no bgp scan-time <5-60>",
1256 NO_STR
1257 "BGP specific commands\n"
1258 "Configure background scanner interval\n"
1259 "Scanner interval (seconds)\n")
1260
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001261static int
1262show_ip_bgp_scan_tables (struct vty *vty, const char detail)
paul718e3742002-12-13 20:15:29 +00001263{
1264 struct bgp_node *rn;
1265 struct bgp_nexthop_cache *bnc;
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001266 char buf[INET6_ADDRSTRLEN];
1267 u_char i;
paul718e3742002-12-13 20:15:29 +00001268
1269 if (bgp_scan_thread)
1270 vty_out (vty, "BGP scan is running%s", VTY_NEWLINE);
1271 else
1272 vty_out (vty, "BGP scan is not running%s", VTY_NEWLINE);
1273 vty_out (vty, "BGP scan interval is %d%s", bgp_scan_interval, VTY_NEWLINE);
1274
1275 vty_out (vty, "Current BGP nexthop cache:%s", VTY_NEWLINE);
paul59320202004-11-09 01:54:03 +00001276 for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP]); rn; rn = bgp_route_next (rn))
paul718e3742002-12-13 20:15:29 +00001277 if ((bnc = rn->info) != NULL)
1278 {
1279 if (bnc->valid)
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001280 {
paul718e3742002-12-13 20:15:29 +00001281 vty_out (vty, " %s valid [IGP metric %d]%s",
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001282 inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), bnc->metric, VTY_NEWLINE);
1283 if (detail)
1284 for (i = 0; i < bnc->nexthop_num; i++)
Denis Ovsienko0e8032d2011-08-09 14:42:58 +04001285 switch (bnc->nexthop[i].type)
1286 {
1287 case NEXTHOP_TYPE_IPV4:
1288 vty_out (vty, " gate %s%s", inet_ntop (AF_INET, &bnc->nexthop[i].gate.ipv4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
1289 break;
Christian Frankebb97e462013-05-25 14:01:35 +00001290 case NEXTHOP_TYPE_IPV4_IFINDEX:
1291 vty_out (vty, " gate %s", inet_ntop (AF_INET, &bnc->nexthop[i].gate.ipv4, buf, INET6_ADDRSTRLEN));
1292 vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE);
1293 break;
Denis Ovsienko0e8032d2011-08-09 14:42:58 +04001294 case NEXTHOP_TYPE_IFINDEX:
1295 vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE);
1296 break;
1297 default:
1298 vty_out (vty, " invalid nexthop type %u%s", bnc->nexthop[i].type, VTY_NEWLINE);
1299 }
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001300 }
paul718e3742002-12-13 20:15:29 +00001301 else
1302 vty_out (vty, " %s invalid%s",
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001303 inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001304 }
1305
paul718e3742002-12-13 20:15:29 +00001306 {
paul59320202004-11-09 01:54:03 +00001307 for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP6]);
1308 rn;
1309 rn = bgp_route_next (rn))
paul718e3742002-12-13 20:15:29 +00001310 if ((bnc = rn->info) != NULL)
1311 {
1312 if (bnc->valid)
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001313 {
paul718e3742002-12-13 20:15:29 +00001314 vty_out (vty, " %s valid [IGP metric %d]%s",
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001315 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00001316 bnc->metric, VTY_NEWLINE);
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001317 if (detail)
1318 for (i = 0; i < bnc->nexthop_num; i++)
Denis Ovsienko0e8032d2011-08-09 14:42:58 +04001319 switch (bnc->nexthop[i].type)
1320 {
1321 case NEXTHOP_TYPE_IPV6:
1322 vty_out (vty, " gate %s%s", inet_ntop (AF_INET6, &bnc->nexthop[i].gate.ipv6, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
1323 break;
1324 case NEXTHOP_TYPE_IFINDEX:
1325 vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE);
1326 break;
1327 default:
1328 vty_out (vty, " invalid nexthop type %u%s", bnc->nexthop[i].type, VTY_NEWLINE);
1329 }
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001330 }
paul718e3742002-12-13 20:15:29 +00001331 else
1332 vty_out (vty, " %s invalid%s",
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001333 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00001334 VTY_NEWLINE);
1335 }
1336 }
paul718e3742002-12-13 20:15:29 +00001337
1338 vty_out (vty, "BGP connected route:%s", VTY_NEWLINE);
paul59320202004-11-09 01:54:03 +00001339 for (rn = bgp_table_top (bgp_connected_table[AFI_IP]);
1340 rn;
1341 rn = bgp_route_next (rn))
paul718e3742002-12-13 20:15:29 +00001342 if (rn->info != NULL)
1343 vty_out (vty, " %s/%d%s", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
1344 VTY_NEWLINE);
1345
paul718e3742002-12-13 20:15:29 +00001346 {
paul59320202004-11-09 01:54:03 +00001347 for (rn = bgp_table_top (bgp_connected_table[AFI_IP6]);
1348 rn;
1349 rn = bgp_route_next (rn))
paul718e3742002-12-13 20:15:29 +00001350 if (rn->info != NULL)
1351 vty_out (vty, " %s/%d%s",
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001352 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00001353 rn->p.prefixlen,
1354 VTY_NEWLINE);
1355 }
paul718e3742002-12-13 20:15:29 +00001356
1357 return CMD_SUCCESS;
1358}
1359
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001360DEFUN (show_ip_bgp_scan,
1361 show_ip_bgp_scan_cmd,
1362 "show ip bgp scan",
1363 SHOW_STR
1364 IP_STR
1365 BGP_STR
1366 "BGP scan status\n")
1367{
1368 return show_ip_bgp_scan_tables (vty, 0);
1369}
1370
1371DEFUN (show_ip_bgp_scan_detail,
1372 show_ip_bgp_scan_detail_cmd,
1373 "show ip bgp scan detail",
1374 SHOW_STR
1375 IP_STR
1376 BGP_STR
1377 "BGP scan status\n"
1378 "More detailed output\n")
1379{
1380 return show_ip_bgp_scan_tables (vty, 1);
1381}
1382
paul718e3742002-12-13 20:15:29 +00001383int
1384bgp_config_write_scan_time (struct vty *vty)
1385{
1386 if (bgp_scan_interval != BGP_SCAN_INTERVAL_DEFAULT)
1387 vty_out (vty, " bgp scan-time %d%s", bgp_scan_interval, VTY_NEWLINE);
1388 return CMD_SUCCESS;
1389}
1390
1391void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001392bgp_scan_init (void)
paul718e3742002-12-13 20:15:29 +00001393{
Donald Sharp774914f2015-10-14 08:50:39 -04001394 zlookup = zclient_new (bm->master);
paul718e3742002-12-13 20:15:29 +00001395 zlookup->sock = -1;
Donald Sharp774914f2015-10-14 08:50:39 -04001396 zlookup->t_connect = thread_add_event (bm->master, zlookup_connect, zlookup, 0);
paul718e3742002-12-13 20:15:29 +00001397
1398 bgp_scan_interval = BGP_SCAN_INTERVAL_DEFAULT;
1399 bgp_import_interval = BGP_IMPORT_INTERVAL_DEFAULT;
1400
Paul Jakma64e580a2006-02-21 01:09:01 +00001401 cache1_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
1402 cache2_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
paul59320202004-11-09 01:54:03 +00001403 bgp_nexthop_cache_table[AFI_IP] = cache1_table[AFI_IP];
paul718e3742002-12-13 20:15:29 +00001404
Paul Jakma64e580a2006-02-21 01:09:01 +00001405 bgp_connected_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +00001406
Paul Jakma64e580a2006-02-21 01:09:01 +00001407 cache1_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
1408 cache2_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
paul59320202004-11-09 01:54:03 +00001409 bgp_nexthop_cache_table[AFI_IP6] = cache1_table[AFI_IP6];
Paul Jakma64e580a2006-02-21 01:09:01 +00001410 bgp_connected_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +00001411
1412 /* Make BGP scan thread. */
Donald Sharp774914f2015-10-14 08:50:39 -04001413 bgp_scan_thread = thread_add_timer (bm->master, bgp_scan_timer,
paul59320202004-11-09 01:54:03 +00001414 NULL, bgp_scan_interval);
paul6cbbc3c2003-04-28 17:11:02 +00001415 /* Make BGP import there. */
Donald Sharp774914f2015-10-14 08:50:39 -04001416 bgp_import_thread = thread_add_timer (bm->master, bgp_import, NULL, 0);
paul718e3742002-12-13 20:15:29 +00001417
1418 install_element (BGP_NODE, &bgp_scan_time_cmd);
1419 install_element (BGP_NODE, &no_bgp_scan_time_cmd);
1420 install_element (BGP_NODE, &no_bgp_scan_time_val_cmd);
1421 install_element (VIEW_NODE, &show_ip_bgp_scan_cmd);
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001422 install_element (VIEW_NODE, &show_ip_bgp_scan_detail_cmd);
Paul Jakma62687ff2008-08-23 14:27:06 +01001423 install_element (RESTRICTED_NODE, &show_ip_bgp_scan_cmd);
paul718e3742002-12-13 20:15:29 +00001424 install_element (ENABLE_NODE, &show_ip_bgp_scan_cmd);
Denis Ovsienko318f0d82011-08-05 21:47:08 +04001425 install_element (ENABLE_NODE, &show_ip_bgp_scan_detail_cmd);
paul718e3742002-12-13 20:15:29 +00001426}
Chris Caputo228da422009-07-18 05:44:03 +00001427
1428void
1429bgp_scan_finish (void)
1430{
Lou Berger056f3762013-04-10 12:30:04 -07001431 if (cache1_table[AFI_IP])
1432 bgp_table_unlock (cache1_table[AFI_IP]);
Chris Caputo228da422009-07-18 05:44:03 +00001433 cache1_table[AFI_IP] = NULL;
1434
Lou Berger056f3762013-04-10 12:30:04 -07001435 if (cache2_table[AFI_IP])
1436 bgp_table_unlock (cache2_table[AFI_IP]);
Chris Caputo228da422009-07-18 05:44:03 +00001437 cache2_table[AFI_IP] = NULL;
Lou Berger056f3762013-04-10 12:30:04 -07001438
1439 if (bgp_connected_table[AFI_IP])
1440 bgp_table_unlock (bgp_connected_table[AFI_IP]);
Chris Caputo228da422009-07-18 05:44:03 +00001441 bgp_connected_table[AFI_IP] = NULL;
1442
Lou Berger056f3762013-04-10 12:30:04 -07001443 if (cache1_table[AFI_IP6])
1444 bgp_table_unlock (cache1_table[AFI_IP6]);
Chris Caputo228da422009-07-18 05:44:03 +00001445 cache1_table[AFI_IP6] = NULL;
1446
Lou Berger056f3762013-04-10 12:30:04 -07001447 if (cache2_table[AFI_IP6])
1448 bgp_table_unlock (cache2_table[AFI_IP6]);
Chris Caputo228da422009-07-18 05:44:03 +00001449 cache2_table[AFI_IP6] = NULL;
1450
Lou Berger056f3762013-04-10 12:30:04 -07001451 if (bgp_connected_table[AFI_IP6])
1452 bgp_table_unlock (bgp_connected_table[AFI_IP6]);
Chris Caputo228da422009-07-18 05:44:03 +00001453 bgp_connected_table[AFI_IP6] = NULL;
Chris Caputo228da422009-07-18 05:44:03 +00001454}
Lou Berger82dd7072016-01-12 13:41:57 -05001455
1456void
1457bgp_scan_destroy (void)
1458{
1459 if (zlookup == NULL)
1460 return;
1461 THREAD_OFF(bgp_import_thread);
1462 THREAD_OFF(bgp_scan_thread);
1463 THREAD_OFF(zlookup->t_connect);
1464 bgp_scan_finish();
1465 zclient_free (zlookup);
1466 zlookup = NULL;
1467}