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"
45 #include "bgpd/bgp_flowspec_util.h"
46 #include "bgpd/bgp_evpn.h"
47 #include "bgpd/bgp_rd.h"
49 extern struct zclient
*zclient
;
51 static void register_zebra_rnh(struct bgp_nexthop_cache
*bnc
,
52 int is_bgp_static_route
);
53 static void unregister_zebra_rnh(struct bgp_nexthop_cache
*bnc
,
54 int is_bgp_static_route
);
55 static void evaluate_paths(struct bgp_nexthop_cache
*bnc
);
56 static int make_prefix(int afi
, struct bgp_path_info
*pi
, struct prefix
*p
);
58 static int bgp_isvalid_nexthop(struct bgp_nexthop_cache
*bnc
)
60 return (bgp_zebra_num_connects() == 0
61 || (bnc
&& CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
)));
64 static int bgp_isvalid_labeled_nexthop(struct bgp_nexthop_cache
*bnc
)
66 return (bgp_zebra_num_connects() == 0
67 || (bnc
&& CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_LABELED_VALID
)));
70 static void bgp_unlink_nexthop_check(struct bgp_nexthop_cache
*bnc
)
72 if (LIST_EMPTY(&(bnc
->paths
)) && !bnc
->nht_info
) {
73 if (BGP_DEBUG(nht
, NHT
)) {
74 char buf
[PREFIX2STR_BUFFER
];
75 zlog_debug("bgp_unlink_nexthop: freeing bnc %s(%s)",
76 bnc_str(bnc
, buf
, PREFIX2STR_BUFFER
),
77 bnc
->bgp
->name_pretty
);
79 unregister_zebra_rnh(bnc
,
80 CHECK_FLAG(bnc
->flags
, BGP_STATIC_ROUTE
));
81 bgp_dest_set_bgp_nexthop_info(bnc
->dest
, NULL
);
82 bgp_dest_unlock_node(bnc
->dest
);
88 void bgp_unlink_nexthop(struct bgp_path_info
*path
)
90 struct bgp_nexthop_cache
*bnc
= path
->nexthop
;
95 path_nh_map(path
, NULL
, false);
97 bgp_unlink_nexthop_check(bnc
);
100 void bgp_unlink_nexthop_by_peer(struct peer
*peer
)
103 struct bgp_dest
*dest
;
104 struct bgp_nexthop_cache
*bnc
;
105 afi_t afi
= family2afi(peer
->su
.sa
.sa_family
);
107 if (!sockunion2hostprefix(&peer
->su
, &p
))
110 dest
= bgp_node_get(peer
->bgp
->nexthop_cache_table
[afi
], &p
);
112 bnc
= bgp_dest_get_bgp_nexthop_info(dest
);
116 /* cleanup the peer reference */
117 bnc
->nht_info
= NULL
;
119 bgp_unlink_nexthop_check(bnc
);
123 * A route and its nexthop might belong to different VRFs. Therefore,
124 * we need both the bgp_route and bgp_nexthop pointers.
126 int bgp_find_or_add_nexthop(struct bgp
*bgp_route
, struct bgp
*bgp_nexthop
,
127 afi_t afi
, struct bgp_path_info
*pi
,
128 struct peer
*peer
, int connected
)
130 struct bgp_dest
*dest
;
131 struct bgp_nexthop_cache
*bnc
;
133 int is_bgp_static_route
= 0;
134 const struct prefix
*bnc_p
;
137 is_bgp_static_route
= ((pi
->type
== ZEBRA_ROUTE_BGP
)
138 && (pi
->sub_type
== BGP_ROUTE_STATIC
))
142 /* Since Extended Next-hop Encoding (RFC5549) support, we want
144 address-family from the next-hop. */
145 if (!is_bgp_static_route
)
146 afi
= BGP_ATTR_NEXTHOP_AFI_IP6(pi
->attr
) ? AFI_IP6
149 /* Validation for the ipv4 mapped ipv6 nexthop. */
150 if (IS_MAPPED_IPV6(&pi
->attr
->mp_nexthop_global
)) {
154 /* This will return true if the global IPv6 NH is a link local
156 if (make_prefix(afi
, pi
, &p
) < 0)
159 if (!sockunion2hostprefix(&peer
->su
, &p
)) {
160 if (BGP_DEBUG(nht
, NHT
)) {
162 "%s: Attempting to register with unknown AFI %d (not %d or %d)",
163 __func__
, afi
, AFI_IP
, AFI_IP6
);
170 if (is_bgp_static_route
)
171 dest
= bgp_node_get(bgp_nexthop
->import_check_table
[afi
], &p
);
173 dest
= bgp_node_get(bgp_nexthop
->nexthop_cache_table
[afi
], &p
);
175 bnc
= bgp_dest_get_bgp_nexthop_info(dest
);
178 bgp_dest_set_bgp_nexthop_info(dest
, bnc
);
180 bnc
->bgp
= bgp_nexthop
;
181 bgp_dest_lock_node(dest
);
182 if (BGP_DEBUG(nht
, NHT
)) {
183 char buf
[PREFIX2STR_BUFFER
];
185 zlog_debug("Allocated bnc %s(%s) peer %p",
186 bnc_str(bnc
, buf
, PREFIX2STR_BUFFER
),
187 bnc
->bgp
->name_pretty
, peer
);
191 bnc_p
= bgp_dest_get_prefix(bnc
->dest
);
193 bgp_dest_unlock_node(dest
);
194 if (is_bgp_static_route
) {
195 SET_FLAG(bnc
->flags
, BGP_STATIC_ROUTE
);
197 /* If we're toggling the type, re-register */
198 if ((CHECK_FLAG(bgp_route
->flags
, BGP_FLAG_IMPORT_CHECK
))
199 && !CHECK_FLAG(bnc
->flags
, BGP_STATIC_ROUTE_EXACT_MATCH
)) {
200 SET_FLAG(bnc
->flags
, BGP_STATIC_ROUTE_EXACT_MATCH
);
201 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
);
202 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
);
203 } else if ((!CHECK_FLAG(bgp_route
->flags
,
204 BGP_FLAG_IMPORT_CHECK
))
205 && CHECK_FLAG(bnc
->flags
,
206 BGP_STATIC_ROUTE_EXACT_MATCH
)) {
207 UNSET_FLAG(bnc
->flags
, BGP_STATIC_ROUTE_EXACT_MATCH
);
208 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
);
209 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
);
212 /* When nexthop is already known, but now requires 'connected'
214 * re-register it. The reverse scenario where the nexthop currently
216 * 'connected' resolution does not need a re-register (i.e., we treat
217 * 'connected-required' as an override) except in the scenario where
219 * is actually a case of tracking a peer for connectivity (e.g., after
220 * disable connected-check).
221 * NOTE: We don't track the number of paths separately for 'connected-
222 * required' vs 'connected-not-required' as this change is not a common
225 else if (connected
&& !CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
)) {
226 SET_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
);
227 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
);
228 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
);
229 } else if (peer
&& !connected
230 && CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
)) {
231 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
);
232 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
);
233 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
);
235 if (bgp_route
->inst_type
== BGP_INSTANCE_TYPE_VIEW
) {
236 SET_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
);
237 SET_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
);
238 } else if (!CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
)
239 && !is_default_host_route(bnc_p
))
240 register_zebra_rnh(bnc
, is_bgp_static_route
);
242 if (pi
&& pi
->nexthop
!= bnc
) {
243 /* Unlink from existing nexthop cache, if any. This will also
245 * the nexthop cache entry, if appropriate.
247 bgp_unlink_nexthop(pi
);
249 /* updates NHT pi list reference */
250 path_nh_map(pi
, bnc
, true);
252 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
) && bnc
->metric
)
253 (bgp_path_info_extra_get(pi
))->igpmetric
= bnc
->metric
;
255 pi
->extra
->igpmetric
= 0;
257 bnc
->nht_info
= (void *)peer
; /* NHT peer reference */
260 * We are cheating here. Views have no associated underlying
261 * ability to detect nexthops. So when we have a view
262 * just tell everyone the nexthop is valid
264 if (bgp_route
->inst_type
== BGP_INSTANCE_TYPE_VIEW
)
267 return (bgp_isvalid_nexthop(bnc
));
270 void bgp_delete_connected_nexthop(afi_t afi
, struct peer
*peer
)
272 struct bgp_dest
*dest
;
273 struct bgp_nexthop_cache
*bnc
;
279 if (!sockunion2hostprefix(&peer
->su
, &p
))
282 dest
= bgp_node_lookup(
283 peer
->bgp
->nexthop_cache_table
[family2afi(p
.family
)], &p
);
285 if (BGP_DEBUG(nht
, NHT
))
287 "Cannot find connected NHT node for peer %s(%s)",
288 peer
->host
, peer
->bgp
->name_pretty
);
292 bnc
= bgp_dest_get_bgp_nexthop_info(dest
);
294 if (BGP_DEBUG(nht
, NHT
))
296 "Cannot find connected NHT node for peer %s(%s) on route_node as expected",
297 peer
->host
, peer
->bgp
->name_pretty
);
298 bgp_dest_unlock_node(dest
);
301 bgp_dest_unlock_node(dest
);
303 if (bnc
->nht_info
!= peer
) {
304 if (BGP_DEBUG(nht
, NHT
))
306 "Connected NHT %p node for peer %s(%s) points to %p",
307 bnc
, peer
->host
, bnc
->bgp
->name_pretty
,
312 bnc
->nht_info
= NULL
;
314 if (LIST_EMPTY(&(bnc
->paths
))) {
315 if (BGP_DEBUG(nht
, NHT
))
317 "Freeing connected NHT node %p for peer %s(%s)",
318 bnc
, peer
->host
, bnc
->bgp
->name_pretty
);
319 unregister_zebra_rnh(bnc
, 0);
320 bgp_dest_set_bgp_nexthop_info(bnc
->dest
, NULL
);
321 bgp_dest_unlock_node(bnc
->dest
);
326 void bgp_parse_nexthop_update(int command
, vrf_id_t vrf_id
)
328 struct bgp_dest
*dest
= NULL
;
329 struct bgp_nexthop_cache
*bnc
;
330 struct nexthop
*nexthop
;
331 struct nexthop
*oldnh
;
332 struct nexthop
*nhlist_head
= NULL
;
333 struct nexthop
*nhlist_tail
= NULL
;
336 struct zapi_route nhr
;
338 bgp
= bgp_lookup_by_vrf_id(vrf_id
);
342 "parse nexthop update: instance not found for vrf_id %u",
347 if (!zapi_nexthop_update_decode(zclient
->ibuf
, &nhr
)) {
348 if (BGP_DEBUG(nht
, NHT
))
349 zlog_debug("%s[%s]: Failure to decode nexthop update",
350 __func__
, bgp
->name_pretty
);
354 if (command
== ZEBRA_NEXTHOP_UPDATE
)
355 dest
= bgp_node_lookup(
356 bgp
->nexthop_cache_table
[family2afi(nhr
.prefix
.family
)],
358 else if (command
== ZEBRA_IMPORT_CHECK_UPDATE
)
359 dest
= bgp_node_lookup(
360 bgp
->import_check_table
[family2afi(nhr
.prefix
.family
)],
364 if (BGP_DEBUG(nht
, NHT
)) {
365 char buf
[PREFIX2STR_BUFFER
];
366 prefix2str(&nhr
.prefix
, buf
, sizeof(buf
));
367 zlog_debug("parse nexthop update(%s(%s)): rn not found",
368 buf
, bgp
->name_pretty
);
373 bnc
= bgp_dest_get_bgp_nexthop_info(dest
);
375 if (BGP_DEBUG(nht
, NHT
)) {
376 char buf
[PREFIX2STR_BUFFER
];
378 prefix2str(&nhr
.prefix
, buf
, sizeof(buf
));
380 "parse nexthop update(%s(%s)): bnc node info not found",
381 buf
, bgp
->name_pretty
);
383 bgp_dest_unlock_node(dest
);
387 bgp_dest_unlock_node(dest
);
388 bnc
->last_update
= bgp_clock();
389 bnc
->change_flags
= 0;
391 /* debug print the input */
392 if (BGP_DEBUG(nht
, NHT
)) {
393 char buf
[PREFIX2STR_BUFFER
];
394 prefix2str(&nhr
.prefix
, buf
, sizeof(buf
));
396 "%s(%u): Rcvd NH update %s - metric %d/%d #nhops %d/%d flags 0x%x",
397 bnc
->bgp
->name_pretty
, vrf_id
, buf
, nhr
.metric
,
398 bnc
->metric
, nhr
.nexthop_num
, bnc
->nexthop_num
,
402 if (nhr
.metric
!= bnc
->metric
)
403 bnc
->change_flags
|= BGP_NEXTHOP_METRIC_CHANGED
;
405 if (nhr
.nexthop_num
!= bnc
->nexthop_num
)
406 bnc
->change_flags
|= BGP_NEXTHOP_CHANGED
;
408 if (nhr
.nexthop_num
) {
409 struct peer
*peer
= bnc
->nht_info
;
411 /* notify bgp fsm if nbr ip goes from invalid->valid */
412 if (!bnc
->nexthop_num
)
413 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_PEER_NOTIFIED
);
415 bnc
->flags
|= BGP_NEXTHOP_VALID
;
416 bnc
->metric
= nhr
.metric
;
417 bnc
->nexthop_num
= nhr
.nexthop_num
;
419 bnc
->flags
&= ~BGP_NEXTHOP_LABELED_VALID
; /* check below */
421 for (i
= 0; i
< nhr
.nexthop_num
; i
++) {
424 nexthop
= nexthop_from_zapi_nexthop(&nhr
.nexthops
[i
]);
427 * Turn on RA for the v6 nexthops
428 * we receive from bgp. This is to allow us
429 * to work with v4 routing over v6 nexthops
431 if (peer
&& !peer
->ifp
432 && CHECK_FLAG(peer
->flags
,
433 PEER_FLAG_CAPABILITY_ENHE
)
434 && nhr
.prefix
.family
== AF_INET6
435 && nexthop
->type
!= NEXTHOP_TYPE_BLACKHOLE
) {
436 struct interface
*ifp
;
438 ifp
= if_lookup_by_index(nexthop
->ifindex
,
441 zclient_send_interface_radv_req(
442 zclient
, nexthop
->vrf_id
, ifp
,
444 BGP_UNNUM_DEFAULT_RA_INTERVAL
);
446 /* There is at least one label-switched path */
447 if (nexthop
->nh_label
&&
448 nexthop
->nh_label
->num_labels
) {
450 bnc
->flags
|= BGP_NEXTHOP_LABELED_VALID
;
451 num_labels
= nexthop
->nh_label
->num_labels
;
454 if (BGP_DEBUG(nht
, NHT
)) {
455 char buf
[NEXTHOP_STRLEN
];
457 " nhop via %s (%d labels)",
458 nexthop2str(nexthop
, buf
, sizeof(buf
)),
463 nhlist_tail
->next
= nexthop
;
464 nhlist_tail
= nexthop
;
466 nhlist_tail
= nexthop
;
467 nhlist_head
= nexthop
;
470 /* No need to evaluate the nexthop if we have already
472 * that there has been a change.
474 if (bnc
->change_flags
& BGP_NEXTHOP_CHANGED
)
477 for (oldnh
= bnc
->nexthop
; oldnh
; oldnh
= oldnh
->next
)
478 if (nexthop_same(oldnh
, nexthop
))
482 bnc
->change_flags
|= BGP_NEXTHOP_CHANGED
;
484 bnc_nexthop_free(bnc
);
485 bnc
->nexthop
= nhlist_head
;
487 bnc
->flags
&= ~BGP_NEXTHOP_VALID
;
488 bnc
->nexthop_num
= nhr
.nexthop_num
;
490 /* notify bgp fsm if nbr ip goes from valid->invalid */
491 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_PEER_NOTIFIED
);
493 bnc_nexthop_free(bnc
);
501 * Cleanup nexthop registration and status information for BGP nexthops
502 * pertaining to this VRF. This is invoked upon VRF deletion.
504 void bgp_cleanup_nexthops(struct bgp
*bgp
)
507 struct bgp_dest
*dest
;
508 struct bgp_nexthop_cache
*bnc
;
510 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
511 if (!bgp
->nexthop_cache_table
[afi
])
514 for (dest
= bgp_table_top(bgp
->nexthop_cache_table
[afi
]); dest
;
515 dest
= bgp_route_next(dest
)) {
516 bnc
= bgp_dest_get_bgp_nexthop_info(dest
);
520 /* Clear relevant flags. */
521 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
);
522 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
);
523 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_PEER_NOTIFIED
);
529 * make_prefix - make a prefix structure from the path (essentially
532 static int make_prefix(int afi
, struct bgp_path_info
*pi
, struct prefix
*p
)
535 int is_bgp_static
= ((pi
->type
== ZEBRA_ROUTE_BGP
)
536 && (pi
->sub_type
== BGP_ROUTE_STATIC
))
539 struct bgp_dest
*net
= pi
->net
;
540 const struct prefix
*p_orig
= bgp_dest_get_prefix(net
);
543 if (p_orig
->family
== AF_FLOWSPEC
) {
546 return bgp_flowspec_get_first_nh(pi
->peer
->bgp
,
549 memset(p
, 0, sizeof(struct prefix
));
554 p
->u
.prefix4
= p_orig
->u
.prefix4
;
555 p
->prefixlen
= p_orig
->prefixlen
;
557 if (IS_MAPPED_IPV6(&pi
->attr
->mp_nexthop_global
)) {
558 ipv4_mapped_ipv6_to_ipv4(
559 &pi
->attr
->mp_nexthop_global
, &ipv4
);
561 p
->prefixlen
= IPV4_MAX_BITLEN
;
563 p
->u
.prefix4
= pi
->attr
->nexthop
;
564 p
->prefixlen
= IPV4_MAX_BITLEN
;
569 p
->family
= AF_INET6
;
572 p
->u
.prefix6
= p_orig
->u
.prefix6
;
573 p
->prefixlen
= p_orig
->prefixlen
;
575 /* If we receive MP_REACH nexthop with ::(LL)
576 * or LL(LL), use LL address as nexthop cache.
578 if (pi
->attr
->mp_nexthop_len
579 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
580 && (IN6_IS_ADDR_UNSPECIFIED(
581 &pi
->attr
->mp_nexthop_global
)
582 || IN6_IS_ADDR_LINKLOCAL(
583 &pi
->attr
->mp_nexthop_global
)))
584 p
->u
.prefix6
= pi
->attr
->mp_nexthop_local
;
586 p
->u
.prefix6
= pi
->attr
->mp_nexthop_global
;
587 p
->prefixlen
= IPV6_MAX_BITLEN
;
591 if (BGP_DEBUG(nht
, NHT
)) {
593 "%s: Attempting to make prefix with unknown AFI %d (not %d or %d)",
594 __func__
, afi
, AFI_IP
, AFI_IP6
);
602 * sendmsg_zebra_rnh -- Format and send a nexthop register/Unregister
605 * struct bgp_nexthop_cache *bnc -- the nexthop structure.
606 * int command -- command to send to zebra
610 static void sendmsg_zebra_rnh(struct bgp_nexthop_cache
*bnc
, int command
)
612 const struct prefix
*p
;
613 bool exact_match
= false;
619 /* Don't try to register if Zebra doesn't know of this instance. */
620 if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bnc
->bgp
)) {
621 if (BGP_DEBUG(zebra
, ZEBRA
))
623 "%s: No zebra instance to talk to, not installing NHT entry",
628 if (!bgp_zebra_num_connects()) {
629 if (BGP_DEBUG(zebra
, ZEBRA
))
631 "%s: We have not connected yet, cannot send nexthops",
634 p
= bgp_dest_get_prefix(bnc
->dest
);
635 if ((command
== ZEBRA_NEXTHOP_REGISTER
636 || command
== ZEBRA_IMPORT_ROUTE_REGISTER
)
637 && (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
)
638 || CHECK_FLAG(bnc
->flags
, BGP_STATIC_ROUTE_EXACT_MATCH
)))
641 if (BGP_DEBUG(zebra
, ZEBRA
)) {
642 char buf
[PREFIX2STR_BUFFER
];
644 prefix2str(p
, buf
, PREFIX2STR_BUFFER
);
645 zlog_debug("%s: sending cmd %s for %s (vrf %s)",
646 __func__
, zserv_command_string(command
), buf
,
647 bnc
->bgp
->name_pretty
);
650 ret
= zclient_send_rnh(zclient
, command
, p
, exact_match
,
652 /* TBD: handle the failure */
654 flog_warn(EC_BGP_ZEBRA_SEND
,
655 "sendmsg_nexthop: zclient_send_message() failed");
657 if ((command
== ZEBRA_NEXTHOP_REGISTER
)
658 || (command
== ZEBRA_IMPORT_ROUTE_REGISTER
))
659 SET_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
);
660 else if ((command
== ZEBRA_NEXTHOP_UNREGISTER
)
661 || (command
== ZEBRA_IMPORT_ROUTE_UNREGISTER
))
662 UNSET_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
);
667 * register_zebra_rnh - register a NH/route with Zebra for notification
668 * when the route or the route to the nexthop changes.
670 * struct bgp_nexthop_cache *bnc
674 static void register_zebra_rnh(struct bgp_nexthop_cache
*bnc
,
675 int is_bgp_import_route
)
677 /* Check if we have already registered */
678 if (bnc
->flags
& BGP_NEXTHOP_REGISTERED
)
680 if (is_bgp_import_route
)
681 sendmsg_zebra_rnh(bnc
, ZEBRA_IMPORT_ROUTE_REGISTER
);
683 sendmsg_zebra_rnh(bnc
, ZEBRA_NEXTHOP_REGISTER
);
687 * unregister_zebra_rnh -- Unregister the route/nexthop from Zebra.
689 * struct bgp_nexthop_cache *bnc
693 static void unregister_zebra_rnh(struct bgp_nexthop_cache
*bnc
,
694 int is_bgp_import_route
)
696 /* Check if we have already registered */
697 if (!CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
))
700 if (is_bgp_import_route
)
701 sendmsg_zebra_rnh(bnc
, ZEBRA_IMPORT_ROUTE_UNREGISTER
);
703 sendmsg_zebra_rnh(bnc
, ZEBRA_NEXTHOP_UNREGISTER
);
707 * evaluate_paths - Evaluate the paths/nets associated with a nexthop.
709 * struct bgp_nexthop_cache *bnc -- the nexthop structure.
713 static void evaluate_paths(struct bgp_nexthop_cache
*bnc
)
715 struct bgp_dest
*dest
;
716 struct bgp_path_info
*path
;
718 struct peer
*peer
= (struct peer
*)bnc
->nht_info
;
719 struct bgp_table
*table
;
721 struct bgp
*bgp_path
;
722 const struct prefix
*p
;
724 if (BGP_DEBUG(nht
, NHT
)) {
725 char buf
[PREFIX2STR_BUFFER
];
726 bnc_str(bnc
, buf
, PREFIX2STR_BUFFER
);
728 "NH update for %s %s flags 0x%x chgflags 0x%x - evaluate paths",
729 buf
, bnc
->bgp
->name_pretty
, bnc
->flags
,
733 LIST_FOREACH (path
, &(bnc
->paths
), nh_thread
) {
734 if (!(path
->type
== ZEBRA_ROUTE_BGP
735 && ((path
->sub_type
== BGP_ROUTE_NORMAL
)
736 || (path
->sub_type
== BGP_ROUTE_STATIC
)
737 || (path
->sub_type
== BGP_ROUTE_IMPORTED
))))
741 assert(dest
&& bgp_dest_table(dest
));
742 p
= bgp_dest_get_prefix(dest
);
743 afi
= family2afi(p
->family
);
744 table
= bgp_dest_table(dest
);
748 * handle routes from other VRFs (they can have a
749 * nexthop in THIS VRF). bgp_path is the bgp instance
750 * that owns the route referencing this nexthop.
752 bgp_path
= table
->bgp
;
755 * Path becomes valid/invalid depending on whether the nexthop
756 * reachable/unreachable.
758 * In case of unicast routes that were imported from vpn
759 * and that have labels, they are valid only if there are
760 * nexthops with labels
763 bool bnc_is_valid_nexthop
= false;
764 bool path_valid
= false;
766 if (safi
== SAFI_UNICAST
&&
767 path
->sub_type
== BGP_ROUTE_IMPORTED
&&
769 path
->extra
->num_labels
) {
771 bnc_is_valid_nexthop
=
772 bgp_isvalid_labeled_nexthop(bnc
) ? true : false;
774 if (bgp_update_martian_nexthop(
775 bnc
->bgp
, afi
, safi
, path
->type
,
776 path
->sub_type
, path
->attr
, dest
)) {
777 if (BGP_DEBUG(nht
, NHT
))
779 "%s: prefix %pRN (vrf %s), ignoring path due to martian or self-next-hop",
780 __func__
, dest
, bgp_path
->name
);
782 bnc_is_valid_nexthop
=
783 bgp_isvalid_nexthop(bnc
) ? true : false;
786 if (BGP_DEBUG(nht
, NHT
)) {
787 char buf1
[RD_ADDRSTRLEN
];
790 prefix_rd2str((struct prefix_rd
*)bgp_dest_get_prefix(dest
->pdest
),
793 "... eval path %d/%d %pRN RD %s %s flags 0x%x",
794 afi
, safi
, dest
, buf1
,
795 bgp_path
->name_pretty
, path
->flags
);
798 "... eval path %d/%d %pRN %s flags 0x%x",
799 afi
, safi
, dest
, bgp_path
->name_pretty
,
803 /* Skip paths marked for removal or as history. */
804 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)
805 || CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
808 /* Copy the metric to the path. Will be used for bestpath
810 if (bgp_isvalid_nexthop(bnc
) && bnc
->metric
)
811 (bgp_path_info_extra_get(path
))->igpmetric
=
813 else if (path
->extra
)
814 path
->extra
->igpmetric
= 0;
816 if (CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_METRIC_CHANGED
)
817 || CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_CHANGED
))
818 SET_FLAG(path
->flags
, BGP_PATH_IGP_CHANGED
);
820 path_valid
= !!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
);
821 if (path_valid
!= bnc_is_valid_nexthop
) {
823 /* No longer valid, clear flag; also for EVPN
824 * routes, unimport from VRFs if needed.
826 bgp_aggregate_decrement(bgp_path
, p
, path
, afi
,
828 bgp_path_info_unset_flag(dest
, path
,
830 if (safi
== SAFI_EVPN
&&
831 bgp_evpn_is_prefix_nht_supported(bgp_dest_get_prefix(dest
)))
832 bgp_evpn_unimport_route(bgp_path
,
833 afi
, safi
, bgp_dest_get_prefix(dest
), path
);
835 /* Path becomes valid, set flag; also for EVPN
836 * routes, import from VRFs if needed.
838 bgp_path_info_set_flag(dest
, path
,
840 bgp_aggregate_increment(bgp_path
, p
, path
, afi
,
842 if (safi
== SAFI_EVPN
&&
843 bgp_evpn_is_prefix_nht_supported(bgp_dest_get_prefix(dest
)))
844 bgp_evpn_import_route(bgp_path
,
845 afi
, safi
, bgp_dest_get_prefix(dest
), path
);
849 bgp_process(bgp_path
, dest
, afi
, safi
);
853 int valid_nexthops
= bgp_isvalid_nexthop(bnc
);
856 peer
->last_reset
= PEER_DOWN_WAITING_OPEN
;
858 peer
->last_reset
= PEER_DOWN_WAITING_NHT
;
860 if (!CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_PEER_NOTIFIED
)) {
861 if (BGP_DEBUG(nht
, NHT
))
863 "%s: Updating peer (%s(%s)) status with NHT",
864 __func__
, peer
->host
,
865 peer
->bgp
->name_pretty
);
866 bgp_fsm_event_update(peer
, valid_nexthops
);
867 SET_FLAG(bnc
->flags
, BGP_NEXTHOP_PEER_NOTIFIED
);
871 RESET_FLAG(bnc
->change_flags
);
875 * path_nh_map - make or break path-to-nexthop association.
877 * path - pointer to the path structure
878 * bnc - pointer to the nexthop structure
879 * make - if set, make the association. if unset, just break the existing
882 void path_nh_map(struct bgp_path_info
*path
, struct bgp_nexthop_cache
*bnc
,
886 LIST_REMOVE(path
, nh_thread
);
887 path
->nexthop
->path_count
--;
888 path
->nexthop
= NULL
;
891 LIST_INSERT_HEAD(&(bnc
->paths
), path
, nh_thread
);
893 path
->nexthop
->path_count
++;
898 * This function is called to register nexthops to zebra
899 * as that we may have tried to install the nexthops
900 * before we actually have a zebra connection
902 void bgp_nht_register_nexthops(struct bgp
*bgp
)
904 struct bgp_dest
*dest
;
905 struct bgp_nexthop_cache
*bnc
;
908 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
909 if (!bgp
->nexthop_cache_table
[afi
])
912 for (dest
= bgp_table_top(bgp
->nexthop_cache_table
[afi
]); dest
;
913 dest
= bgp_route_next(dest
)) {
914 bnc
= bgp_dest_get_bgp_nexthop_info(dest
);
919 register_zebra_rnh(bnc
, 0);
924 void bgp_nht_reg_enhe_cap_intfs(struct peer
*peer
)
927 struct bgp_dest
*dest
;
928 struct bgp_nexthop_cache
*bnc
;
929 struct nexthop
*nhop
;
930 struct interface
*ifp
;
938 if (!bgp
->nexthop_cache_table
[AFI_IP6
])
941 if (!sockunion2hostprefix(&peer
->su
, &p
)) {
942 zlog_warn("%s: Unable to convert sockunion to prefix for %s",
943 __func__
, peer
->host
);
947 if (p
.family
!= AF_INET6
)
949 dest
= bgp_node_lookup(bgp
->nexthop_cache_table
[AFI_IP6
], &p
);
953 bnc
= bgp_dest_get_bgp_nexthop_info(dest
);
957 if (peer
!= bnc
->nht_info
)
960 for (nhop
= bnc
->nexthop
; nhop
; nhop
= nhop
->next
) {
961 ifp
= if_lookup_by_index(nhop
->ifindex
, nhop
->vrf_id
);
966 zclient_send_interface_radv_req(zclient
,
969 BGP_UNNUM_DEFAULT_RA_INTERVAL
);
973 void bgp_nht_dereg_enhe_cap_intfs(struct peer
*peer
)
976 struct bgp_dest
*dest
;
977 struct bgp_nexthop_cache
*bnc
;
978 struct nexthop
*nhop
;
979 struct interface
*ifp
;
987 if (!bgp
->nexthop_cache_table
[AFI_IP6
])
990 if (!sockunion2hostprefix(&peer
->su
, &p
)) {
991 zlog_warn("%s: Unable to convert sockunion to prefix for %s",
992 __func__
, peer
->host
);
996 if (p
.family
!= AF_INET6
)
999 dest
= bgp_node_lookup(bgp
->nexthop_cache_table
[AFI_IP6
], &p
);
1003 bnc
= bgp_dest_get_bgp_nexthop_info(dest
);
1007 if (peer
!= bnc
->nht_info
)
1010 for (nhop
= bnc
->nexthop
; nhop
; nhop
= nhop
->next
) {
1011 ifp
= if_lookup_by_index(nhop
->ifindex
, nhop
->vrf_id
);
1016 zclient_send_interface_radv_req(zclient
, nhop
->vrf_id
, ifp
, 0,