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