]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_nht.c
1ca0483678bdc1961fe69e4ad255c9ae7e0766e2
[mirror_frr.git] / bgpd / bgp_nht.c
1 /* BGP Nexthop tracking
2 * Copyright (C) 2013 Cumulus Networks, Inc.
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22 #include <zebra.h>
23
24 #include "command.h"
25 #include "thread.h"
26 #include "prefix.h"
27 #include "zclient.h"
28 #include "stream.h"
29 #include "network.h"
30 #include "log.h"
31 #include "memory.h"
32 #include "nexthop.h"
33 #include "vrf.h"
34 #include "filter.h"
35
36 #include "bgpd/bgpd.h"
37 #include "bgpd/bgp_table.h"
38 #include "bgpd/bgp_route.h"
39 #include "bgpd/bgp_attr.h"
40 #include "bgpd/bgp_nexthop.h"
41 #include "bgpd/bgp_debug.h"
42 #include "bgpd/bgp_nht.h"
43 #include "bgpd/bgp_fsm.h"
44 #include "bgpd/bgp_zebra.h"
45
46 extern struct zclient *zclient;
47
48 static void register_zebra_rnh(struct bgp_nexthop_cache *bnc,
49 int is_bgp_static_route);
50 static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc,
51 int is_bgp_static_route);
52 static void evaluate_paths(struct bgp_nexthop_cache *bnc);
53 static int make_prefix(int afi, struct bgp_info *ri, struct prefix *p);
54 static void path_nh_map(struct bgp_info *path, struct bgp_nexthop_cache *bnc,
55 int keep);
56
57 static int
58 bgp_isvalid_nexthop (struct bgp_nexthop_cache *bnc)
59 {
60 return (bgp_zebra_num_connects() == 0 ||
61 (bnc && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)));
62 }
63
64 int
65 bgp_find_nexthop (struct bgp_info *path, int connected)
66 {
67 struct bgp_nexthop_cache *bnc = path->nexthop;
68
69 if (!bnc)
70 return 0;
71
72 if (connected && !(CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)))
73 return 0;
74
75 return (bgp_isvalid_nexthop(bnc));
76 }
77
78 static void
79 bgp_unlink_nexthop_check (struct bgp_nexthop_cache *bnc)
80 {
81 if (LIST_EMPTY(&(bnc->paths)) && !bnc->nht_info)
82 {
83 if (BGP_DEBUG(nht, NHT))
84 {
85 char buf[PREFIX2STR_BUFFER];
86 zlog_debug("bgp_unlink_nexthop: freeing bnc %s",
87 bnc_str(bnc, buf, PREFIX2STR_BUFFER));
88 }
89 unregister_zebra_rnh(bnc, CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE));
90 bnc->node->info = NULL;
91 bgp_unlock_node(bnc->node);
92 bnc->node = NULL;
93 bnc_free(bnc);
94 }
95 }
96
97 void
98 bgp_unlink_nexthop (struct bgp_info *path)
99 {
100 struct bgp_nexthop_cache *bnc = path->nexthop;
101
102 if (!bnc)
103 return;
104
105 path_nh_map(path, NULL, 0);
106
107 bgp_unlink_nexthop_check (bnc);
108 }
109
110 void
111 bgp_unlink_nexthop_by_peer (struct peer *peer)
112 {
113 struct prefix p;
114 struct bgp_node *rn;
115 struct bgp_nexthop_cache *bnc;
116 afi_t afi = family2afi(peer->su.sa.sa_family);
117
118 if (! sockunion2hostprefix (&peer->su, &p))
119 return;
120
121 rn = bgp_node_get (peer->bgp->nexthop_cache_table[afi], &p);
122
123 if (!rn->info)
124 return;
125
126 bnc = rn->info;
127
128 /* cleanup the peer reference */
129 bnc->nht_info = NULL;
130
131 bgp_unlink_nexthop_check (bnc);
132 }
133
134 int
135 bgp_find_or_add_nexthop (struct bgp *bgp, afi_t afi, struct bgp_info *ri,
136 struct peer *peer, int connected)
137 {
138 struct bgp_node *rn;
139 struct bgp_nexthop_cache *bnc;
140 struct prefix p;
141 int is_bgp_static_route = 0;
142
143 if (ri)
144 {
145 is_bgp_static_route = ((ri->type == ZEBRA_ROUTE_BGP) &&
146 (ri->sub_type == BGP_ROUTE_STATIC)) ? 1 : 0;
147
148 /* Since Extended Next-hop Encoding (RFC5549) support, we want to derive
149 address-family from the next-hop. */
150 if (!is_bgp_static_route)
151 afi = BGP_ATTR_NEXTHOP_AFI_IP6(ri->attr) ? AFI_IP6 : AFI_IP;
152
153 /* This will return TRUE if the global IPv6 NH is a link local addr */
154 if (make_prefix(afi, ri, &p) < 0)
155 return 1;
156 }
157 else if (peer)
158 {
159 /* Don't register link local NH */
160 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&peer->su.sin6.sin6_addr))
161 return 1;
162
163 if (! sockunion2hostprefix (&peer->su, &p))
164 {
165 if (BGP_DEBUG(nht, NHT))
166 {
167 zlog_debug("%s: Attempting to register with unknown AFI %d (not %d or %d)",
168 __FUNCTION__, afi, AFI_IP, AFI_IP6);
169 }
170 return 0;
171 }
172 }
173 else
174 return 0;
175
176 if (is_bgp_static_route)
177 rn = bgp_node_get (bgp->import_check_table[afi], &p);
178 else
179 rn = bgp_node_get (bgp->nexthop_cache_table[afi], &p);
180
181 if (!rn->info)
182 {
183 bnc = bnc_new();
184 rn->info = bnc;
185 bnc->node = rn;
186 bnc->bgp = bgp;
187 bgp_lock_node(rn);
188 if (BGP_DEBUG(nht, NHT))
189 {
190 char buf[PREFIX2STR_BUFFER];
191
192 zlog_debug("Allocated bnc %s peer %p",
193 bnc_str(bnc, buf, PREFIX2STR_BUFFER), peer);
194 }
195 }
196
197 bnc = rn->info;
198 bgp_unlock_node (rn);
199
200 if (is_bgp_static_route)
201 {
202 SET_FLAG(bnc->flags, BGP_STATIC_ROUTE);
203
204 /* If we're toggling the type, re-register */
205 if ((bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)) &&
206 !CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH))
207 {
208 SET_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH);
209 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
210 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
211 }
212 else if ((!bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)) &&
213 CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH))
214 {
215 UNSET_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH);
216 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
217 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
218 }
219 }
220 /* When nexthop is already known, but now requires 'connected' resolution,
221 * re-register it. The reverse scenario where the nexthop currently requires
222 * 'connected' resolution does not need a re-register (i.e., we treat
223 * 'connected-required' as an override) except in the scenario where this
224 * is actually a case of tracking a peer for connectivity (e.g., after
225 * disable connected-check).
226 * NOTE: We don't track the number of paths separately for 'connected-
227 * required' vs 'connected-not-required' as this change is not a common
228 * scenario.
229 */
230 else if (connected && ! CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
231 {
232 SET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED);
233 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
234 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
235 }
236 else if (peer && !connected && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
237 {
238 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED);
239 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
240 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
241 }
242
243 if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
244 register_zebra_rnh(bnc, is_bgp_static_route);
245
246 if (ri && ri->nexthop != bnc)
247 {
248 /* Unlink from existing nexthop cache, if any. This will also free
249 * the nexthop cache entry, if appropriate.
250 */
251 bgp_unlink_nexthop (ri);
252
253 path_nh_map(ri, bnc, 1); /* updates NHT ri list reference */
254
255 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric)
256 (bgp_info_extra_get(ri))->igpmetric = bnc->metric;
257 else if (ri->extra)
258 ri->extra->igpmetric = 0;
259 }
260 else if (peer)
261 bnc->nht_info = (void *)peer; /* NHT peer reference */
262
263 return (bgp_isvalid_nexthop(bnc));
264 }
265
266 void
267 bgp_delete_connected_nexthop (afi_t afi, struct peer *peer)
268 {
269 struct bgp_node *rn;
270 struct bgp_nexthop_cache *bnc;
271 struct prefix p;
272
273 if (!peer)
274 return;
275
276 /* We don't register link local address for NHT */
277 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&peer->su.sin6.sin6_addr))
278 return;
279
280 if (! sockunion2hostprefix (&peer->su, &p))
281 return;
282
283 rn = bgp_node_lookup(peer->bgp->nexthop_cache_table[family2afi(p.family)], &p);
284 if (!rn || !rn->info)
285 {
286 if (BGP_DEBUG(nht, NHT))
287 zlog_debug("Cannot find connected NHT node for peer %s", peer->host);
288 if (rn)
289 bgp_unlock_node (rn);
290 return;
291 }
292
293 bnc = rn->info;
294 bgp_unlock_node(rn);
295
296 if (bnc->nht_info != peer)
297 {
298 if (BGP_DEBUG(nht, NHT))
299 zlog_debug("Connected NHT %p node for peer %s points to %p",
300 bnc, peer->host, bnc->nht_info);
301 return;
302 }
303
304 bnc->nht_info = NULL;
305
306 if (LIST_EMPTY(&(bnc->paths)))
307 {
308 if (BGP_DEBUG(nht, NHT))
309 zlog_debug("Freeing connected NHT node %p for peer %s",
310 bnc, peer->host);
311 unregister_zebra_rnh(bnc, 0);
312 bnc->node->info = NULL;
313 bgp_unlock_node(bnc->node);
314 bnc_free(bnc);
315 }
316 }
317
318 void
319 bgp_parse_nexthop_update (int command, vrf_id_t vrf_id)
320 {
321 struct stream *s;
322 struct bgp_node *rn = NULL;
323 struct bgp_nexthop_cache *bnc;
324 struct nexthop *nexthop;
325 struct nexthop *oldnh;
326 struct nexthop *nhlist_head = NULL;
327 struct nexthop *nhlist_tail = NULL;
328 uint32_t metric;
329 u_char nexthop_num;
330 struct prefix p;
331 int i;
332 struct bgp *bgp;
333
334 bgp = bgp_lookup_by_vrf_id (vrf_id);
335 if (!bgp)
336 {
337 zlog_err("parse nexthop update: instance not found for vrf_id %d", vrf_id);
338 return;
339 }
340
341 s = zclient->ibuf;
342
343 memset(&p, 0, sizeof(struct prefix));
344 p.family = stream_getw(s);
345 p.prefixlen = stream_getc(s);
346 switch (p.family)
347 {
348 case AF_INET:
349 p.u.prefix4.s_addr = stream_get_ipv4 (s);
350 break;
351 case AF_INET6:
352 stream_get(&p.u.prefix6, s, 16);
353 break;
354 default:
355 break;
356 }
357
358 if (command == ZEBRA_NEXTHOP_UPDATE)
359 rn = bgp_node_lookup(bgp->nexthop_cache_table[family2afi(p.family)], &p);
360 else if (command == ZEBRA_IMPORT_CHECK_UPDATE)
361 rn = bgp_node_lookup(bgp->import_check_table[family2afi(p.family)], &p);
362
363 if (!rn || !rn->info)
364 {
365 if (BGP_DEBUG(nht, NHT))
366 {
367 char buf[PREFIX2STR_BUFFER];
368 prefix2str(&p, buf, sizeof(buf));
369 zlog_debug("parse nexthop update(%s): rn not found", buf);
370 }
371 if (rn)
372 bgp_unlock_node (rn);
373 return;
374 }
375
376 bnc = rn->info;
377 bgp_unlock_node (rn);
378 bnc->last_update = bgp_clock();
379 bnc->change_flags = 0;
380 metric = stream_getl (s);
381 nexthop_num = stream_getc (s);
382
383 /* debug print the input */
384 if (BGP_DEBUG(nht, NHT))
385 {
386 char buf[PREFIX2STR_BUFFER];
387 prefix2str(&p, buf, sizeof (buf));
388 zlog_debug("%d: NH update for %s - metric %d (cur %d) #nhops %d (cur %d)",
389 vrf_id, buf, metric, bnc->metric, nexthop_num, bnc->nexthop_num);
390 }
391
392 if (metric != bnc->metric)
393 bnc->change_flags |= BGP_NEXTHOP_METRIC_CHANGED;
394
395 if(nexthop_num != bnc->nexthop_num)
396 bnc->change_flags |= BGP_NEXTHOP_CHANGED;
397
398 if (nexthop_num)
399 {
400 /* notify bgp fsm if nbr ip goes from invalid->valid */
401 if (!bnc->nexthop_num)
402 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
403
404 bnc->flags |= BGP_NEXTHOP_VALID;
405 bnc->metric = metric;
406 bnc->nexthop_num = nexthop_num;
407
408 for (i = 0; i < nexthop_num; i++)
409 {
410 nexthop = nexthop_new();
411 nexthop->type = stream_getc (s);
412 switch (nexthop->type)
413 {
414 case NEXTHOP_TYPE_IPV4:
415 nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
416 break;
417 case NEXTHOP_TYPE_IFINDEX:
418 nexthop->ifindex = stream_getl (s);
419 break;
420 case NEXTHOP_TYPE_IPV4_IFINDEX:
421 nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
422 nexthop->ifindex = stream_getl (s);
423 break;
424 case NEXTHOP_TYPE_IPV6:
425 stream_get (&nexthop->gate.ipv6, s, 16);
426 break;
427 case NEXTHOP_TYPE_IPV6_IFINDEX:
428 stream_get (&nexthop->gate.ipv6, s, 16);
429 nexthop->ifindex = stream_getl (s);
430 break;
431 default:
432 /* do nothing */
433 break;
434 }
435
436 if (BGP_DEBUG(nht, NHT))
437 {
438 char buf[NEXTHOP_STRLEN];
439 zlog_debug(" nhop via %s",
440 nexthop2str (nexthop, buf, sizeof (buf)));
441 }
442
443 if (nhlist_tail)
444 {
445 nhlist_tail->next = nexthop;
446 nhlist_tail = nexthop;
447 }
448 else
449 {
450 nhlist_tail = nexthop;
451 nhlist_head = nexthop;
452 }
453
454 /* No need to evaluate the nexthop if we have already determined
455 * that there has been a change.
456 */
457 if (bnc->change_flags & BGP_NEXTHOP_CHANGED)
458 continue;
459
460 for (oldnh = bnc->nexthop; oldnh; oldnh = oldnh->next)
461 if (nexthop_same_no_recurse(oldnh, nexthop))
462 break;
463
464 if (!oldnh)
465 bnc->change_flags |= BGP_NEXTHOP_CHANGED;
466 }
467 bnc_nexthop_free(bnc);
468 bnc->nexthop = nhlist_head;
469 }
470 else
471 {
472 bnc->flags &= ~BGP_NEXTHOP_VALID;
473 bnc->nexthop_num = nexthop_num;
474
475 /* notify bgp fsm if nbr ip goes from valid->invalid */
476 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
477
478 bnc_nexthop_free(bnc);
479 bnc->nexthop = NULL;
480 }
481
482 evaluate_paths(bnc);
483 }
484
485 /**
486 * make_prefix - make a prefix structure from the path (essentially
487 * path's node.
488 */
489 static int
490 make_prefix (int afi, struct bgp_info *ri, struct prefix *p)
491 {
492
493 int is_bgp_static = ((ri->type == ZEBRA_ROUTE_BGP) &&
494 (ri->sub_type == BGP_ROUTE_STATIC)) ? 1 : 0;
495
496 memset (p, 0, sizeof (struct prefix));
497 switch (afi)
498 {
499 case AFI_IP:
500 p->family = AF_INET;
501 if (is_bgp_static)
502 {
503 p->u.prefix4 = ri->net->p.u.prefix4;
504 p->prefixlen = ri->net->p.prefixlen;
505 }
506 else
507 {
508 p->u.prefix4 = ri->attr->nexthop;
509 p->prefixlen = IPV4_MAX_BITLEN;
510 }
511 break;
512 #ifdef HAVE_IPV6
513 case AFI_IP6:
514 /* We don't register link local NH */
515 if (ri->attr->extra->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL
516 || IN6_IS_ADDR_LINKLOCAL (&ri->attr->extra->mp_nexthop_global))
517 return -1;
518
519 p->family = AF_INET6;
520
521 if (is_bgp_static)
522 {
523 p->u.prefix6 = ri->net->p.u.prefix6;
524 p->prefixlen = ri->net->p.prefixlen;
525 }
526 else
527 {
528 p->u.prefix6 = ri->attr->extra->mp_nexthop_global;
529 p->prefixlen = IPV6_MAX_BITLEN;
530 }
531 break;
532 #endif
533 default:
534 if (BGP_DEBUG(nht, NHT))
535 {
536 zlog_debug("%s: Attempting to make prefix with unknown AFI %d (not %d or %d)",
537 __FUNCTION__, afi, AFI_IP, AFI_IP6);
538 }
539 break;
540 }
541 return 0;
542 }
543
544 /**
545 * sendmsg_zebra_rnh -- Format and send a nexthop register/Unregister
546 * command to Zebra.
547 * ARGUMENTS:
548 * struct bgp_nexthop_cache *bnc -- the nexthop structure.
549 * int command -- command to send to zebra
550 * RETURNS:
551 * void.
552 */
553 static void
554 sendmsg_zebra_rnh (struct bgp_nexthop_cache *bnc, int command)
555 {
556 struct stream *s;
557 struct prefix *p;
558 int ret;
559
560 /* Check socket. */
561 if (!zclient || zclient->sock < 0)
562 return;
563
564 /* Don't try to register if Zebra doesn't know of this instance. */
565 if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bnc->bgp))
566 return;
567
568 p = &(bnc->node->p);
569 s = zclient->obuf;
570 stream_reset (s);
571 zclient_create_header (s, command, bnc->bgp->vrf_id);
572 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED) ||
573 CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH))
574 stream_putc(s, 1);
575 else
576 stream_putc(s, 0);
577
578 stream_putw(s, PREFIX_FAMILY(p));
579 stream_putc(s, p->prefixlen);
580 switch (PREFIX_FAMILY(p))
581 {
582 case AF_INET:
583 stream_put_in_addr (s, &p->u.prefix4);
584 break;
585 #ifdef HAVE_IPV6
586 case AF_INET6:
587 stream_put(s, &(p->u.prefix6), 16);
588 break;
589 #endif
590 default:
591 break;
592 }
593 stream_putw_at (s, 0, stream_get_endp (s));
594
595 ret = zclient_send_message(zclient);
596 /* TBD: handle the failure */
597 if (ret < 0)
598 zlog_warn("sendmsg_nexthop: zclient_send_message() failed");
599
600 if ((command == ZEBRA_NEXTHOP_REGISTER) ||
601 (command == ZEBRA_IMPORT_ROUTE_REGISTER))
602 SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
603 else if ((command == ZEBRA_NEXTHOP_UNREGISTER) ||
604 (command == ZEBRA_IMPORT_ROUTE_UNREGISTER))
605 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
606 return;
607 }
608
609 /**
610 * register_zebra_rnh - register a NH/route with Zebra for notification
611 * when the route or the route to the nexthop changes.
612 * ARGUMENTS:
613 * struct bgp_nexthop_cache *bnc
614 * RETURNS:
615 * void.
616 */
617 static void
618 register_zebra_rnh (struct bgp_nexthop_cache *bnc, int is_bgp_import_route)
619 {
620 /* Check if we have already registered */
621 if (bnc->flags & BGP_NEXTHOP_REGISTERED)
622 return;
623 if (is_bgp_import_route)
624 sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_REGISTER);
625 else
626 sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_REGISTER);
627 }
628
629 /**
630 * unregister_zebra_rnh -- Unregister the route/nexthop from Zebra.
631 * ARGUMENTS:
632 * struct bgp_nexthop_cache *bnc
633 * RETURNS:
634 * void.
635 */
636 static void
637 unregister_zebra_rnh (struct bgp_nexthop_cache *bnc, int is_bgp_import_route)
638 {
639 /* Check if we have already registered */
640 if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
641 return;
642
643 if (is_bgp_import_route)
644 sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_UNREGISTER);
645 else
646 sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_UNREGISTER);
647 }
648
649 /**
650 * evaluate_paths - Evaluate the paths/nets associated with a nexthop.
651 * ARGUMENTS:
652 * struct bgp_nexthop_cache *bnc -- the nexthop structure.
653 * RETURNS:
654 * void.
655 */
656 static void
657 evaluate_paths (struct bgp_nexthop_cache *bnc)
658 {
659 struct bgp_node *rn;
660 struct bgp_info *path;
661 struct bgp *bgp = bnc->bgp;
662 int afi;
663 struct peer *peer = (struct peer *)bnc->nht_info;
664
665 if (BGP_DEBUG(nht, NHT))
666 {
667 char buf[PREFIX2STR_BUFFER];
668 bnc_str(bnc, buf, PREFIX2STR_BUFFER);
669 zlog_debug("NH update for %s - flags 0x%x chgflags 0x%x - evaluate paths",
670 buf, bnc->flags, bnc->change_flags);
671 }
672
673 LIST_FOREACH(path, &(bnc->paths), nh_thread)
674 {
675 if (!(path->type == ZEBRA_ROUTE_BGP &&
676 ((path->sub_type == BGP_ROUTE_NORMAL) ||
677 (path->sub_type == BGP_ROUTE_STATIC))))
678 continue;
679
680 rn = path->net;
681 afi = family2afi(rn->p.family);
682
683 /* Path becomes valid/invalid depending on whether the nexthop
684 * reachable/unreachable.
685 */
686 if ((CHECK_FLAG(path->flags, BGP_INFO_VALID) ? 1 : 0) !=
687 (bgp_isvalid_nexthop(bnc) ? 1 : 0))
688 {
689 if (CHECK_FLAG (path->flags, BGP_INFO_VALID))
690 {
691 bgp_aggregate_decrement (bgp, &rn->p, path,
692 afi, SAFI_UNICAST);
693 bgp_info_unset_flag (rn, path, BGP_INFO_VALID);
694 }
695 else
696 {
697 bgp_info_set_flag (rn, path, BGP_INFO_VALID);
698 bgp_aggregate_increment (bgp, &rn->p, path,
699 afi, SAFI_UNICAST);
700 }
701 }
702
703 /* Copy the metric to the path. Will be used for bestpath computation */
704 if (bgp_isvalid_nexthop(bnc) && bnc->metric)
705 (bgp_info_extra_get(path))->igpmetric = bnc->metric;
706 else if (path->extra)
707 path->extra->igpmetric = 0;
708
709 if (CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED) ||
710 CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED))
711 SET_FLAG(path->flags, BGP_INFO_IGP_CHANGED);
712
713 bgp_process(bgp, rn, afi, SAFI_UNICAST);
714 }
715
716 if (peer && !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED))
717 {
718 if (BGP_DEBUG(nht, NHT))
719 zlog_debug("%s: Updating peer (%s) status with NHT", __FUNCTION__, peer->host);
720 bgp_fsm_nht_update(peer, bgp_isvalid_nexthop(bnc));
721 SET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
722 }
723
724 RESET_FLAG(bnc->change_flags);
725 }
726
727 /**
728 * path_nh_map - make or break path-to-nexthop association.
729 * ARGUMENTS:
730 * path - pointer to the path structure
731 * bnc - pointer to the nexthop structure
732 * make - if set, make the association. if unset, just break the existing
733 * association.
734 */
735 static void
736 path_nh_map (struct bgp_info *path, struct bgp_nexthop_cache *bnc, int make)
737 {
738 if (path->nexthop)
739 {
740 LIST_REMOVE(path, nh_thread);
741 path->nexthop->path_count--;
742 path->nexthop = NULL;
743 }
744 if (make)
745 {
746 LIST_INSERT_HEAD(&(bnc->paths), path, nh_thread);
747 path->nexthop = bnc;
748 path->nexthop->path_count++;
749 }
750 }