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