1 /* BGP Nexthop tracking
2 * Copyright (C) 2013 Cumulus Networks, Inc.
4 * This file is part of GNU Zebra.
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
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.
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
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_errors.h"
42 #include "bgpd/bgp_nht.h"
43 #include "bgpd/bgp_fsm.h"
44 #include "bgpd/bgp_zebra.h"
46 extern struct zclient
*zclient
;
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
,
57 static int bgp_isvalid_nexthop(struct bgp_nexthop_cache
*bnc
)
59 return (bgp_zebra_num_connects() == 0
60 || (bnc
&& CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
)));
63 static int bgp_isvalid_labeled_nexthop(struct bgp_nexthop_cache
*bnc
)
65 return (bgp_zebra_num_connects() == 0
66 || (bnc
&& CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_LABELED_VALID
)));
69 int bgp_find_nexthop(struct bgp_info
*path
, int connected
)
71 struct bgp_nexthop_cache
*bnc
= path
->nexthop
;
77 * We are cheating here. Views have no associated underlying
78 * ability to detect nexthops. So when we have a view
79 * just tell everyone the nexthop is valid
81 if (path
->peer
&& path
->peer
->bgp
->inst_type
== BGP_INSTANCE_TYPE_VIEW
)
84 if (connected
&& !(CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
)))
87 return (bgp_isvalid_nexthop(bnc
));
90 static void bgp_unlink_nexthop_check(struct bgp_nexthop_cache
*bnc
)
92 if (LIST_EMPTY(&(bnc
->paths
)) && !bnc
->nht_info
) {
93 if (BGP_DEBUG(nht
, NHT
)) {
94 char buf
[PREFIX2STR_BUFFER
];
95 zlog_debug("bgp_unlink_nexthop: freeing bnc %s",
96 bnc_str(bnc
, buf
, PREFIX2STR_BUFFER
));
98 unregister_zebra_rnh(bnc
,
99 CHECK_FLAG(bnc
->flags
, BGP_STATIC_ROUTE
));
100 bnc
->node
->info
= NULL
;
101 bgp_unlock_node(bnc
->node
);
107 void bgp_unlink_nexthop(struct bgp_info
*path
)
109 struct bgp_nexthop_cache
*bnc
= path
->nexthop
;
114 path_nh_map(path
, NULL
, 0);
116 bgp_unlink_nexthop_check(bnc
);
119 void bgp_unlink_nexthop_by_peer(struct peer
*peer
)
123 struct bgp_nexthop_cache
*bnc
;
124 afi_t afi
= family2afi(peer
->su
.sa
.sa_family
);
126 if (!sockunion2hostprefix(&peer
->su
, &p
))
129 rn
= bgp_node_get(peer
->bgp
->nexthop_cache_table
[afi
], &p
);
136 /* cleanup the peer reference */
137 bnc
->nht_info
= NULL
;
139 bgp_unlink_nexthop_check(bnc
);
143 * A route and its nexthop might belong to different VRFs. Therefore,
144 * we need both the bgp_route and bgp_nexthop pointers.
146 int bgp_find_or_add_nexthop(struct bgp
*bgp_route
, struct bgp
*bgp_nexthop
,
147 afi_t afi
, struct bgp_info
*ri
,
148 struct peer
*peer
, int connected
)
151 struct bgp_nexthop_cache
*bnc
;
153 int is_bgp_static_route
= 0;
156 is_bgp_static_route
= ((ri
->type
== ZEBRA_ROUTE_BGP
)
157 && (ri
->sub_type
== BGP_ROUTE_STATIC
))
161 /* Since Extended Next-hop Encoding (RFC5549) support, we want
163 address-family from the next-hop. */
164 if (!is_bgp_static_route
)
165 afi
= BGP_ATTR_NEXTHOP_AFI_IP6(ri
->attr
) ? AFI_IP6
168 /* This will return TRUE if the global IPv6 NH is a link local
170 if (make_prefix(afi
, ri
, &p
) < 0)
173 /* Don't register link local NH */
175 && IN6_IS_ADDR_LINKLOCAL(&peer
->su
.sin6
.sin6_addr
))
178 if (!sockunion2hostprefix(&peer
->su
, &p
)) {
179 if (BGP_DEBUG(nht
, NHT
)) {
181 "%s: Attempting to register with unknown AFI %d (not %d or %d)",
182 __FUNCTION__
, afi
, AFI_IP
, AFI_IP6
);
189 if (is_bgp_static_route
)
190 rn
= bgp_node_get(bgp_nexthop
->import_check_table
[afi
], &p
);
192 rn
= bgp_node_get(bgp_nexthop
->nexthop_cache_table
[afi
], &p
);
198 bnc
->bgp
= bgp_nexthop
;
200 if (BGP_DEBUG(nht
, NHT
)) {
201 char buf
[PREFIX2STR_BUFFER
];
203 zlog_debug("Allocated bnc %s peer %p",
204 bnc_str(bnc
, buf
, PREFIX2STR_BUFFER
), peer
);
210 if (is_bgp_static_route
) {
211 SET_FLAG(bnc
->flags
, BGP_STATIC_ROUTE
);
213 /* If we're toggling the type, re-register */
214 if ((bgp_flag_check(bgp_route
, BGP_FLAG_IMPORT_CHECK
))
215 && !CHECK_FLAG(bnc
->flags
, BGP_STATIC_ROUTE_EXACT_MATCH
)) {
216 SET_FLAG(bnc
->flags
, BGP_STATIC_ROUTE_EXACT_MATCH
);
217 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
);
218 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
);
219 } else if ((!bgp_flag_check(bgp_route
, BGP_FLAG_IMPORT_CHECK
))
220 && CHECK_FLAG(bnc
->flags
,
221 BGP_STATIC_ROUTE_EXACT_MATCH
)) {
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
);
227 /* When nexthop is already known, but now requires 'connected'
229 * re-register it. The reverse scenario where the nexthop currently
231 * 'connected' resolution does not need a re-register (i.e., we treat
232 * 'connected-required' as an override) except in the scenario where
234 * is actually a case of tracking a peer for connectivity (e.g., after
235 * disable connected-check).
236 * NOTE: We don't track the number of paths separately for 'connected-
237 * required' vs 'connected-not-required' as this change is not a common
240 else if (connected
&& !CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
)) {
241 SET_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
);
242 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
);
243 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
);
244 } else if (peer
&& !connected
245 && CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
)) {
246 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
);
247 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
);
248 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
);
250 if (bgp_route
->inst_type
== BGP_INSTANCE_TYPE_VIEW
) {
251 bnc
->flags
|= BGP_NEXTHOP_REGISTERED
;
252 bnc
->flags
|= BGP_NEXTHOP_VALID
;
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 /* Unlink from existing nexthop cache, if any. This will also
258 * the nexthop cache entry, if appropriate.
260 bgp_unlink_nexthop(ri
);
262 path_nh_map(ri
, bnc
, 1); /* updates NHT ri list reference */
264 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
) && bnc
->metric
)
265 (bgp_info_extra_get(ri
))->igpmetric
= bnc
->metric
;
267 ri
->extra
->igpmetric
= 0;
269 bnc
->nht_info
= (void *)peer
; /* NHT peer reference */
272 * We are cheating here. Views have no associated underlying
273 * ability to detect nexthops. So when we have a view
274 * just tell everyone the nexthop is valid
276 if (bgp_route
->inst_type
== BGP_INSTANCE_TYPE_VIEW
)
279 return (bgp_isvalid_nexthop(bnc
));
282 void bgp_delete_connected_nexthop(afi_t afi
, struct peer
*peer
)
285 struct bgp_nexthop_cache
*bnc
;
291 /* We don't register link local address for NHT */
292 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&peer
->su
.sin6
.sin6_addr
))
295 if (!sockunion2hostprefix(&peer
->su
, &p
))
298 rn
= bgp_node_lookup(
299 peer
->bgp
->nexthop_cache_table
[family2afi(p
.family
)], &p
);
300 if (!rn
|| !rn
->info
) {
301 if (BGP_DEBUG(nht
, NHT
))
302 zlog_debug("Cannot find connected NHT node for peer %s",
312 if (bnc
->nht_info
!= peer
) {
313 if (BGP_DEBUG(nht
, NHT
))
315 "Connected NHT %p node for peer %s points to %p",
316 bnc
, peer
->host
, bnc
->nht_info
);
320 bnc
->nht_info
= NULL
;
322 if (LIST_EMPTY(&(bnc
->paths
))) {
323 if (BGP_DEBUG(nht
, NHT
))
324 zlog_debug("Freeing connected NHT node %p for peer %s",
326 unregister_zebra_rnh(bnc
, 0);
327 bnc
->node
->info
= NULL
;
328 bgp_unlock_node(bnc
->node
);
333 void bgp_parse_nexthop_update(int command
, vrf_id_t vrf_id
)
335 struct bgp_node
*rn
= NULL
;
336 struct bgp_nexthop_cache
*bnc
;
337 struct nexthop
*nexthop
;
338 struct nexthop
*oldnh
;
339 struct nexthop
*nhlist_head
= NULL
;
340 struct nexthop
*nhlist_tail
= NULL
;
343 struct zapi_route nhr
;
345 bgp
= bgp_lookup_by_vrf_id(vrf_id
);
349 "parse nexthop update: instance not found for vrf_id %u",
354 if (!zapi_nexthop_update_decode(zclient
->ibuf
, &nhr
)) {
355 if (BGP_DEBUG(nht
, NHT
))
356 zlog_debug("%s: Failure to decode nexthop update",
357 __PRETTY_FUNCTION__
);
361 if (command
== ZEBRA_NEXTHOP_UPDATE
)
362 rn
= bgp_node_lookup(
363 bgp
->nexthop_cache_table
[family2afi(nhr
.prefix
.family
)],
365 else if (command
== ZEBRA_IMPORT_CHECK_UPDATE
)
366 rn
= bgp_node_lookup(
367 bgp
->import_check_table
[family2afi(nhr
.prefix
.family
)],
370 if (!rn
|| !rn
->info
) {
371 if (BGP_DEBUG(nht
, NHT
)) {
372 char buf
[PREFIX2STR_BUFFER
];
373 prefix2str(&nhr
.prefix
, buf
, sizeof(buf
));
374 zlog_debug("parse nexthop update(%s): rn not found",
384 bnc
->last_update
= bgp_clock();
385 bnc
->change_flags
= 0;
387 /* debug print the input */
388 if (BGP_DEBUG(nht
, NHT
)) {
389 char buf
[PREFIX2STR_BUFFER
];
390 prefix2str(&nhr
.prefix
, buf
, sizeof(buf
));
392 "%u: Rcvd NH update %s - metric %d/%d #nhops %d/%d flags 0x%x",
393 vrf_id
, buf
, nhr
.metric
, bnc
->metric
, nhr
.nexthop_num
,
394 bnc
->nexthop_num
, bnc
->flags
);
397 if (nhr
.metric
!= bnc
->metric
)
398 bnc
->change_flags
|= BGP_NEXTHOP_METRIC_CHANGED
;
400 if (nhr
.nexthop_num
!= bnc
->nexthop_num
)
401 bnc
->change_flags
|= BGP_NEXTHOP_CHANGED
;
403 if (nhr
.nexthop_num
) {
404 /* notify bgp fsm if nbr ip goes from invalid->valid */
405 if (!bnc
->nexthop_num
)
406 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_PEER_NOTIFIED
);
408 bnc
->flags
|= BGP_NEXTHOP_VALID
;
409 bnc
->metric
= nhr
.metric
;
410 bnc
->nexthop_num
= nhr
.nexthop_num
;
412 bnc
->flags
&= ~BGP_NEXTHOP_LABELED_VALID
; /* check below */
414 for (i
= 0; i
< nhr
.nexthop_num
; i
++) {
417 nexthop
= nexthop_from_zapi_nexthop(&nhr
.nexthops
[i
]);
419 /* There is at least one label-switched path */
420 if (nexthop
->nh_label
&&
421 nexthop
->nh_label
->num_labels
) {
423 bnc
->flags
|= BGP_NEXTHOP_LABELED_VALID
;
424 num_labels
= nexthop
->nh_label
->num_labels
;
427 if (BGP_DEBUG(nht
, NHT
)) {
428 char buf
[NEXTHOP_STRLEN
];
430 " nhop via %s (%d labels)",
431 nexthop2str(nexthop
, buf
, sizeof(buf
)),
436 nhlist_tail
->next
= nexthop
;
437 nhlist_tail
= nexthop
;
439 nhlist_tail
= nexthop
;
440 nhlist_head
= nexthop
;
443 /* No need to evaluate the nexthop if we have already
445 * that there has been a change.
447 if (bnc
->change_flags
& BGP_NEXTHOP_CHANGED
)
450 for (oldnh
= bnc
->nexthop
; oldnh
; oldnh
= oldnh
->next
)
451 if (nexthop_same_no_recurse(oldnh
, nexthop
) &&
452 nexthop_labels_match(oldnh
, nexthop
))
456 bnc
->change_flags
|= BGP_NEXTHOP_CHANGED
;
458 bnc_nexthop_free(bnc
);
459 bnc
->nexthop
= nhlist_head
;
461 bnc
->flags
&= ~BGP_NEXTHOP_VALID
;
462 bnc
->nexthop_num
= nhr
.nexthop_num
;
464 /* notify bgp fsm if nbr ip goes from valid->invalid */
465 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_PEER_NOTIFIED
);
467 bnc_nexthop_free(bnc
);
475 * Cleanup nexthop registration and status information for BGP nexthops
476 * pertaining to this VRF. This is invoked upon VRF deletion.
478 void bgp_cleanup_nexthops(struct bgp
*bgp
)
482 struct bgp_nexthop_cache
*bnc
;
484 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
485 if (!bgp
->nexthop_cache_table
[afi
])
488 for (rn
= bgp_table_top(bgp
->nexthop_cache_table
[afi
]); rn
;
489 rn
= bgp_route_next(rn
)) {
494 /* Clear relevant flags. */
495 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
);
496 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
);
497 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_PEER_NOTIFIED
);
503 * make_prefix - make a prefix structure from the path (essentially
506 static int make_prefix(int afi
, struct bgp_info
*ri
, struct prefix
*p
)
509 int is_bgp_static
= ((ri
->type
== ZEBRA_ROUTE_BGP
)
510 && (ri
->sub_type
== BGP_ROUTE_STATIC
))
514 memset(p
, 0, sizeof(struct prefix
));
519 p
->u
.prefix4
= ri
->net
->p
.u
.prefix4
;
520 p
->prefixlen
= ri
->net
->p
.prefixlen
;
522 p
->u
.prefix4
= ri
->attr
->nexthop
;
523 p
->prefixlen
= IPV4_MAX_BITLEN
;
527 /* We don't register link local NH */
528 if (ri
->attr
->mp_nexthop_len
!= BGP_ATTR_NHLEN_IPV6_GLOBAL
529 || IN6_IS_ADDR_LINKLOCAL(&ri
->attr
->mp_nexthop_global
))
532 p
->family
= AF_INET6
;
535 p
->u
.prefix6
= ri
->net
->p
.u
.prefix6
;
536 p
->prefixlen
= ri
->net
->p
.prefixlen
;
538 p
->u
.prefix6
= ri
->attr
->mp_nexthop_global
;
539 p
->prefixlen
= IPV6_MAX_BITLEN
;
543 if (BGP_DEBUG(nht
, NHT
)) {
545 "%s: Attempting to make prefix with unknown AFI %d (not %d or %d)",
546 __FUNCTION__
, afi
, AFI_IP
, AFI_IP6
);
554 * sendmsg_zebra_rnh -- Format and send a nexthop register/Unregister
557 * struct bgp_nexthop_cache *bnc -- the nexthop structure.
558 * int command -- command to send to zebra
562 static void sendmsg_zebra_rnh(struct bgp_nexthop_cache
*bnc
, int command
)
565 bool exact_match
= false;
571 /* Don't try to register if Zebra doesn't know of this instance. */
572 if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bnc
->bgp
))
576 if ((command
== ZEBRA_NEXTHOP_REGISTER
577 || command
== ZEBRA_IMPORT_ROUTE_REGISTER
)
578 && (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
)
579 || CHECK_FLAG(bnc
->flags
, BGP_STATIC_ROUTE_EXACT_MATCH
)))
582 if (BGP_DEBUG(zebra
, ZEBRA
)) {
583 char buf
[PREFIX2STR_BUFFER
];
585 prefix2str(p
, buf
, PREFIX2STR_BUFFER
);
586 zlog_debug("%s: sending cmd %s for %s (vrf %s)",
587 __func__
, zserv_command_string(command
), buf
,
591 ret
= zclient_send_rnh(zclient
, command
, p
, exact_match
,
593 /* TBD: handle the failure */
595 flog_warn(EC_BGP_ZEBRA_SEND
,
596 "sendmsg_nexthop: zclient_send_message() failed");
598 if ((command
== ZEBRA_NEXTHOP_REGISTER
)
599 || (command
== ZEBRA_IMPORT_ROUTE_REGISTER
))
600 SET_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
);
601 else if ((command
== ZEBRA_NEXTHOP_UNREGISTER
)
602 || (command
== ZEBRA_IMPORT_ROUTE_UNREGISTER
))
603 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
);
608 * register_zebra_rnh - register a NH/route with Zebra for notification
609 * when the route or the route to the nexthop changes.
611 * struct bgp_nexthop_cache *bnc
615 static void register_zebra_rnh(struct bgp_nexthop_cache
*bnc
,
616 int is_bgp_import_route
)
618 /* Check if we have already registered */
619 if (bnc
->flags
& BGP_NEXTHOP_REGISTERED
)
621 if (is_bgp_import_route
)
622 sendmsg_zebra_rnh(bnc
, ZEBRA_IMPORT_ROUTE_REGISTER
);
624 sendmsg_zebra_rnh(bnc
, ZEBRA_NEXTHOP_REGISTER
);
628 * unregister_zebra_rnh -- Unregister the route/nexthop from Zebra.
630 * struct bgp_nexthop_cache *bnc
634 static void unregister_zebra_rnh(struct bgp_nexthop_cache
*bnc
,
635 int is_bgp_import_route
)
637 /* Check if we have already registered */
638 if (!CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
))
641 if (is_bgp_import_route
)
642 sendmsg_zebra_rnh(bnc
, ZEBRA_IMPORT_ROUTE_UNREGISTER
);
644 sendmsg_zebra_rnh(bnc
, ZEBRA_NEXTHOP_UNREGISTER
);
648 * evaluate_paths - Evaluate the paths/nets associated with a nexthop.
650 * struct bgp_nexthop_cache *bnc -- the nexthop structure.
654 static void evaluate_paths(struct bgp_nexthop_cache
*bnc
)
657 struct bgp_info
*path
;
659 struct peer
*peer
= (struct peer
*)bnc
->nht_info
;
660 struct bgp_table
*table
;
662 struct bgp
*bgp_path
;
664 if (BGP_DEBUG(nht
, NHT
)) {
665 char buf
[PREFIX2STR_BUFFER
];
666 bnc_str(bnc
, buf
, PREFIX2STR_BUFFER
);
668 "NH update for %s - flags 0x%x chgflags 0x%x - evaluate paths",
669 buf
, bnc
->flags
, bnc
->change_flags
);
672 LIST_FOREACH (path
, &(bnc
->paths
), nh_thread
) {
673 if (!(path
->type
== ZEBRA_ROUTE_BGP
674 && ((path
->sub_type
== BGP_ROUTE_NORMAL
)
675 || (path
->sub_type
== BGP_ROUTE_STATIC
)
676 || (path
->sub_type
== BGP_ROUTE_IMPORTED
))))
680 assert(rn
&& bgp_node_table(rn
));
681 afi
= family2afi(rn
->p
.family
);
682 table
= bgp_node_table(rn
);
686 * handle routes from other VRFs (they can have a
687 * nexthop in THIS VRF). bgp_path is the bgp instance
688 * that owns the route referencing this nexthop.
690 bgp_path
= table
->bgp
;
693 * Path becomes valid/invalid depending on whether the nexthop
694 * reachable/unreachable.
696 * In case of unicast routes that were imported from vpn
697 * and that have labels, they are valid only if there are
698 * nexthops with labels
701 int bnc_is_valid_nexthop
= 0;
703 if (safi
== SAFI_UNICAST
&&
704 path
->sub_type
== BGP_ROUTE_IMPORTED
&&
706 path
->extra
->num_labels
) {
708 bnc_is_valid_nexthop
=
709 bgp_isvalid_labeled_nexthop(bnc
) ? 1 : 0;
711 bnc_is_valid_nexthop
=
712 bgp_isvalid_nexthop(bnc
) ? 1 : 0;
715 if (BGP_DEBUG(nht
, NHT
)) {
716 char buf
[PREFIX_STRLEN
];
718 prefix2str(&rn
->p
, buf
, PREFIX_STRLEN
);
719 zlog_debug("%s: prefix %s (vrf %s) %svalid",
720 __func__
, buf
, bgp_path
->name
,
721 (bnc_is_valid_nexthop
? "" : "not "));
724 if ((CHECK_FLAG(path
->flags
, BGP_INFO_VALID
) ? 1 : 0)
725 != bnc_is_valid_nexthop
) {
726 if (CHECK_FLAG(path
->flags
, BGP_INFO_VALID
)) {
727 bgp_aggregate_decrement(bgp_path
, &rn
->p
,
729 bgp_info_unset_flag(rn
, path
, BGP_INFO_VALID
);
731 bgp_info_set_flag(rn
, path
, BGP_INFO_VALID
);
732 bgp_aggregate_increment(bgp_path
, &rn
->p
,
737 /* Copy the metric to the path. Will be used for bestpath
739 if (bgp_isvalid_nexthop(bnc
) && bnc
->metric
)
740 (bgp_info_extra_get(path
))->igpmetric
= bnc
->metric
;
741 else if (path
->extra
)
742 path
->extra
->igpmetric
= 0;
744 if (CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_METRIC_CHANGED
)
745 || CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_CHANGED
))
746 SET_FLAG(path
->flags
, BGP_INFO_IGP_CHANGED
);
748 bgp_process(bgp_path
, rn
, afi
, safi
);
751 if (peer
&& !CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_PEER_NOTIFIED
)) {
752 if (BGP_DEBUG(nht
, NHT
))
753 zlog_debug("%s: Updating peer (%s) status with NHT",
754 __FUNCTION__
, peer
->host
);
755 bgp_fsm_nht_update(peer
, bgp_isvalid_nexthop(bnc
));
756 SET_FLAG(bnc
->flags
, BGP_NEXTHOP_PEER_NOTIFIED
);
759 RESET_FLAG(bnc
->change_flags
);
763 * path_nh_map - make or break path-to-nexthop association.
765 * path - pointer to the path structure
766 * bnc - pointer to the nexthop structure
767 * make - if set, make the association. if unset, just break the existing
770 static void path_nh_map(struct bgp_info
*path
, struct bgp_nexthop_cache
*bnc
,
774 LIST_REMOVE(path
, nh_thread
);
775 path
->nexthop
->path_count
--;
776 path
->nexthop
= NULL
;
779 LIST_INSERT_HEAD(&(bnc
->paths
), path
, nh_thread
);
781 path
->nexthop
->path_count
++;