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