]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_nht.c
Merge pull request #9027 from ton31337/fix/missing_unlock_bgp_dest
[mirror_frr.git] / bgpd / bgp_nht.c
CommitLineData
fb018d25
DS
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 *
896014f4
DL
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
fb018d25
DS
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"
7076bb2f 32#include "vrf.h"
039f3a34 33#include "filter.h"
8bcb09a1 34#include "nexthop_group.h"
fb018d25
DS
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"
14454c9f 42#include "bgpd/bgp_errors.h"
fb018d25 43#include "bgpd/bgp_nht.h"
ffd0c037 44#include "bgpd/bgp_fsm.h"
afbb1c59 45#include "bgpd/bgp_zebra.h"
0378bcaa 46#include "bgpd/bgp_flowspec_util.h"
7c312383 47#include "bgpd/bgp_evpn.h"
9e15d76a 48#include "bgpd/bgp_rd.h"
fb018d25
DS
49
50extern struct zclient *zclient;
fb018d25 51
078430f6 52static void register_zebra_rnh(struct bgp_nexthop_cache *bnc,
d62a17ae 53 int is_bgp_static_route);
078430f6
DS
54static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc,
55 int is_bgp_static_route);
40381db7 56static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p);
8761cd6d 57static int bgp_nht_ifp_initial(struct thread *thread);
fb018d25 58
d62a17ae 59static int bgp_isvalid_nexthop(struct bgp_nexthop_cache *bnc)
d4d9d757 60{
d62a17ae 61 return (bgp_zebra_num_connects() == 0
c3b95419
EDP
62 || (bnc && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)
63 && bnc->nexthop_num > 0));
d4d9d757
LB
64}
65
960035b2
PZ
66static int bgp_isvalid_labeled_nexthop(struct bgp_nexthop_cache *bnc)
67{
7f8c7d91
HS
68 /*
69 * In the case of MPLS-VPN, the label is learned from LDP or other
70 * protocols, and nexthop tracking is enabled for the label.
71 * The value is recorded as BGP_NEXTHOP_LABELED_VALID.
72 * In the case of SRv6-VPN, we need to track the reachability to the
73 * SID (in other words, IPv6 address). As in MPLS, we need to record
74 * the value as BGP_NEXTHOP_SID_VALID. However, this function is
75 * currently not implemented, and this function assumes that all
76 * Transit routes for SRv6-VPN are valid.
77 */
960035b2 78 return (bgp_zebra_num_connects() == 0
7f8c7d91
HS
79 || (bnc && bnc->nexthop_num > 0
80 && (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID)
2ba6be5b 81 || bnc->bgp->srv6_enabled)));
960035b2
PZ
82}
83
d62a17ae 84static void bgp_unlink_nexthop_check(struct bgp_nexthop_cache *bnc)
fb018d25 85{
d5c4bac9 86 if (LIST_EMPTY(&(bnc->paths)) && !bnc->nht_info) {
d62a17ae 87 if (BGP_DEBUG(nht, NHT)) {
88 char buf[PREFIX2STR_BUFFER];
84c320dc 89 zlog_debug("%s: freeing bnc %s(%u)(%s)", __func__,
8c1a4c10 90 bnc_str(bnc, buf, PREFIX2STR_BUFFER),
545aeef1 91 bnc->srte_color, bnc->bgp->name_pretty);
d62a17ae 92 }
e37e1e27
PR
93 /* only unregister if this is the last nh for this prefix*/
94 if (!bnc_existing_for_prefix(bnc))
95 unregister_zebra_rnh(
96 bnc, CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE));
d62a17ae 97 bnc_free(bnc);
fb018d25 98 }
fb018d25
DS
99}
100
4b7e6066 101void bgp_unlink_nexthop(struct bgp_path_info *path)
f9164b1d 102{
d62a17ae 103 struct bgp_nexthop_cache *bnc = path->nexthop;
104
105 if (!bnc)
106 return;
f9164b1d 107
7f040da1 108 path_nh_map(path, NULL, false);
f9164b1d 109
d62a17ae 110 bgp_unlink_nexthop_check(bnc);
f9164b1d
PJ
111}
112
996319e6
DS
113void bgp_replace_nexthop_by_peer(struct peer *from, struct peer *to)
114{
115 struct prefix pp;
116 struct prefix pt;
117 struct bgp_nexthop_cache *bncp, *bnct;
118 afi_t afi;
119
120 if (!sockunion2hostprefix(&from->su, &pp))
121 return;
122
123 afi = family2afi(pp.family);
124 bncp = bnc_find(&from->bgp->nexthop_cache_table[afi], &pp, 0);
125
126 if (!sockunion2hostprefix(&to->su, &pt))
127 return;
128
129 bnct = bnc_find(&to->bgp->nexthop_cache_table[afi], &pt, 0);
130
131 if (bnct != bncp)
132 return;
133
134 if (bnct)
135 bnct->nht_info = to;
136}
137
d62a17ae 138void bgp_unlink_nexthop_by_peer(struct peer *peer)
f9164b1d 139{
d62a17ae 140 struct prefix p;
d62a17ae 141 struct bgp_nexthop_cache *bnc;
142 afi_t afi = family2afi(peer->su.sa.sa_family);
143
144 if (!sockunion2hostprefix(&peer->su, &p))
145 return;
146
545aeef1 147 bnc = bnc_find(&peer->bgp->nexthop_cache_table[afi], &p, 0);
14315f2d 148 if (!bnc)
d62a17ae 149 return;
150
d62a17ae 151 /* cleanup the peer reference */
152 bnc->nht_info = NULL;
153
154 bgp_unlink_nexthop_check(bnc);
f9164b1d
PJ
155}
156
960035b2
PZ
157/*
158 * A route and its nexthop might belong to different VRFs. Therefore,
159 * we need both the bgp_route and bgp_nexthop pointers.
160 */
161int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
4053e952 162 afi_t afi, safi_t safi, struct bgp_path_info *pi,
d62a17ae 163 struct peer *peer, int connected)
fb018d25 164{
f663c581 165 struct bgp_nexthop_cache_head *tree = NULL;
d62a17ae 166 struct bgp_nexthop_cache *bnc;
167 struct prefix p;
545aeef1 168 uint32_t srte_color = 0;
d62a17ae 169 int is_bgp_static_route = 0;
8761cd6d 170 ifindex_t ifindex = 0;
d62a17ae 171
40381db7
DS
172 if (pi) {
173 is_bgp_static_route = ((pi->type == ZEBRA_ROUTE_BGP)
174 && (pi->sub_type == BGP_ROUTE_STATIC))
d62a17ae 175 ? 1
176 : 0;
177
178 /* Since Extended Next-hop Encoding (RFC5549) support, we want
179 to derive
180 address-family from the next-hop. */
181 if (!is_bgp_static_route)
40381db7 182 afi = BGP_ATTR_NEXTHOP_AFI_IP6(pi->attr) ? AFI_IP6
d62a17ae 183 : AFI_IP;
184
92d6f769
K
185 /* Validation for the ipv4 mapped ipv6 nexthop. */
186 if (IS_MAPPED_IPV6(&pi->attr->mp_nexthop_global)) {
187 afi = AFI_IP;
188 }
189
2951a7a4 190 /* This will return true if the global IPv6 NH is a link local
d62a17ae 191 * addr */
40381db7 192 if (make_prefix(afi, pi, &p) < 0)
d62a17ae 193 return 1;
545aeef1
RW
194
195 srte_color = pi->attr->srte_color;
d62a17ae 196 } else if (peer) {
8761cd6d
DS
197 /*
198 * Gather the ifindex for if up/down events to be
199 * tagged into this fun
200 */
201 if (afi == AFI_IP6
202 && IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr))
203 ifindex = peer->su.sin6.sin6_scope_id;
204
d62a17ae 205 if (!sockunion2hostprefix(&peer->su, &p)) {
206 if (BGP_DEBUG(nht, NHT)) {
207 zlog_debug(
208 "%s: Attempting to register with unknown AFI %d (not %d or %d)",
15569c58 209 __func__, afi, AFI_IP, AFI_IP6);
d62a17ae 210 }
211 return 0;
212 }
213 } else
214 return 0;
215
216 if (is_bgp_static_route)
f663c581 217 tree = &bgp_nexthop->import_check_table[afi];
d62a17ae 218 else
f663c581 219 tree = &bgp_nexthop->nexthop_cache_table[afi];
d62a17ae 220
545aeef1 221 bnc = bnc_find(tree, &p, srte_color);
14315f2d 222 if (!bnc) {
545aeef1 223 bnc = bnc_new(tree, &p, srte_color);
960035b2 224 bnc->bgp = bgp_nexthop;
8761cd6d 225 bnc->ifindex = ifindex;
d62a17ae 226 if (BGP_DEBUG(nht, NHT)) {
227 char buf[PREFIX2STR_BUFFER];
228
545aeef1 229 zlog_debug("Allocated bnc %s(%u)(%s) peer %p",
8c1a4c10 230 bnc_str(bnc, buf, PREFIX2STR_BUFFER),
545aeef1
RW
231 bnc->srte_color, bnc->bgp->name_pretty,
232 peer);
d62a17ae 233 }
4115b296 234 } else {
235 if (BGP_DEBUG(nht, NHT)) {
236 char buf[PREFIX2STR_BUFFER];
237
238 zlog_debug(
239 "Found existing bnc %s(%s) flags 0x%x ifindex %d #paths %d peer %p",
240 bnc_str(bnc, buf, PREFIX2STR_BUFFER),
241 bnc->bgp->name_pretty, bnc->flags, bnc->ifindex,
242 bnc->path_count, bnc->nht_info);
243 }
fc9a856f 244 }
d62a17ae 245
021b6596
AD
246 if (pi && is_route_parent_evpn(pi))
247 bnc->is_evpn_gwip_nexthop = true;
248
d62a17ae 249 if (is_bgp_static_route) {
250 SET_FLAG(bnc->flags, BGP_STATIC_ROUTE);
251
252 /* If we're toggling the type, re-register */
892fedb6 253 if ((CHECK_FLAG(bgp_route->flags, BGP_FLAG_IMPORT_CHECK))
d62a17ae 254 && !CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)) {
255 SET_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH);
256 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
257 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
892fedb6
DA
258 } else if ((!CHECK_FLAG(bgp_route->flags,
259 BGP_FLAG_IMPORT_CHECK))
d62a17ae 260 && CHECK_FLAG(bnc->flags,
261 BGP_STATIC_ROUTE_EXACT_MATCH)) {
262 UNSET_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH);
263 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
264 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
265 }
078430f6 266 }
d62a17ae 267 /* When nexthop is already known, but now requires 'connected'
268 * resolution,
269 * re-register it. The reverse scenario where the nexthop currently
270 * requires
271 * 'connected' resolution does not need a re-register (i.e., we treat
272 * 'connected-required' as an override) except in the scenario where
273 * this
274 * is actually a case of tracking a peer for connectivity (e.g., after
275 * disable connected-check).
276 * NOTE: We don't track the number of paths separately for 'connected-
277 * required' vs 'connected-not-required' as this change is not a common
278 * scenario.
279 */
280 else if (connected && !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) {
281 SET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED);
282 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
283 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
284 } else if (peer && !connected
285 && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) {
286 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED);
287 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
288 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
078430f6 289 }
4115b296 290 if (peer && (bnc->ifindex != ifindex)) {
291 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
292 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
293 bnc->ifindex = ifindex;
294 }
960035b2 295 if (bgp_route->inst_type == BGP_INSTANCE_TYPE_VIEW) {
1ee0a2df
DS
296 SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
297 SET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
b54892e0 298 } else if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED)
f663c581 299 && !is_default_host_route(&bnc->prefix))
d62a17ae 300 register_zebra_rnh(bnc, is_bgp_static_route);
1eb6c3ea 301
40381db7 302 if (pi && pi->nexthop != bnc) {
d62a17ae 303 /* Unlink from existing nexthop cache, if any. This will also
304 * free
305 * the nexthop cache entry, if appropriate.
306 */
40381db7 307 bgp_unlink_nexthop(pi);
d62a17ae 308
7f040da1
DS
309 /* updates NHT pi list reference */
310 path_nh_map(pi, bnc, true);
d62a17ae 311
312 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric)
40381db7
DS
313 (bgp_path_info_extra_get(pi))->igpmetric = bnc->metric;
314 else if (pi->extra)
315 pi->extra->igpmetric = 0;
996319e6
DS
316 } else if (peer) {
317 /*
318 * Let's not accidently save the peer data for a peer
319 * we are going to throw away in a second or so.
320 * When we come back around we'll fix up this
321 * data properly in replace_nexthop_by_peer
322 */
323 if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
324 bnc->nht_info = (void *)peer; /* NHT peer reference */
325 }
d62a17ae 326
327 /*
328 * We are cheating here. Views have no associated underlying
329 * ability to detect nexthops. So when we have a view
330 * just tell everyone the nexthop is valid
331 */
960035b2 332 if (bgp_route->inst_type == BGP_INSTANCE_TYPE_VIEW)
d62a17ae 333 return 1;
4053e952
PR
334 else if (safi == SAFI_UNICAST && pi
335 && pi->sub_type == BGP_ROUTE_IMPORTED && pi->extra
021b6596 336 && pi->extra->num_labels && !bnc->is_evpn_gwip_nexthop) {
4053e952
PR
337 return bgp_isvalid_labeled_nexthop(bnc);
338 } else
d62a17ae 339 return (bgp_isvalid_nexthop(bnc));
fb018d25
DS
340}
341
d62a17ae 342void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer)
9a233a02 343{
d62a17ae 344 struct bgp_nexthop_cache *bnc;
345 struct prefix p;
346
347 if (!peer)
348 return;
349
d62a17ae 350 if (!sockunion2hostprefix(&peer->su, &p))
351 return;
352
f663c581 353 bnc = bnc_find(&peer->bgp->nexthop_cache_table[family2afi(p.family)],
545aeef1 354 &p, 0);
14315f2d
DS
355 if (!bnc) {
356 if (BGP_DEBUG(nht, NHT))
8c1a4c10 357 zlog_debug(
f663c581 358 "Cannot find connected NHT node for peer %s(%s)",
8c1a4c10 359 peer->host, peer->bgp->name_pretty);
14315f2d
DS
360 return;
361 }
d62a17ae 362
363 if (bnc->nht_info != peer) {
364 if (BGP_DEBUG(nht, NHT))
365 zlog_debug(
8c1a4c10
DS
366 "Connected NHT %p node for peer %s(%s) points to %p",
367 bnc, peer->host, bnc->bgp->name_pretty,
368 bnc->nht_info);
d62a17ae 369 return;
370 }
371
372 bnc->nht_info = NULL;
373
374 if (LIST_EMPTY(&(bnc->paths))) {
375 if (BGP_DEBUG(nht, NHT))
8c1a4c10
DS
376 zlog_debug(
377 "Freeing connected NHT node %p for peer %s(%s)",
378 bnc, peer->host, bnc->bgp->name_pretty);
d62a17ae 379 unregister_zebra_rnh(bnc, 0);
d62a17ae 380 bnc_free(bnc);
381 }
9a233a02
DS
382}
383
545aeef1
RW
384static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc,
385 struct zapi_route *nhr)
fb018d25 386{
d62a17ae 387 struct nexthop *nexthop;
388 struct nexthop *oldnh;
389 struct nexthop *nhlist_head = NULL;
390 struct nexthop *nhlist_tail = NULL;
d62a17ae 391 int i;
021b6596 392 bool evpn_resolved = false;
14315f2d 393
d62a17ae 394 bnc->last_update = bgp_clock();
395 bnc->change_flags = 0;
d62a17ae 396
397 /* debug print the input */
987a720a
DS
398 if (BGP_DEBUG(nht, NHT)) {
399 char bnc_buf[BNC_FLAG_DUMP_SIZE];
400
d62a17ae 401 zlog_debug(
987a720a 402 "%s(%u): Rcvd NH update %pFX(%u) - metric %d/%d #nhops %d/%d flags %s",
2dbe669b 403 bnc->bgp->name_pretty, bnc->bgp->vrf_id, &nhr->prefix,
545aeef1 404 bnc->srte_color, nhr->metric, bnc->metric,
987a720a
DS
405 nhr->nexthop_num, bnc->nexthop_num,
406 bgp_nexthop_dump_bnc_flags(bnc, bnc_buf,
407 sizeof(bnc_buf)));
408 }
d62a17ae 409
545aeef1 410 if (nhr->metric != bnc->metric)
d62a17ae 411 bnc->change_flags |= BGP_NEXTHOP_METRIC_CHANGED;
412
545aeef1 413 if (nhr->nexthop_num != bnc->nexthop_num)
d62a17ae 414 bnc->change_flags |= BGP_NEXTHOP_CHANGED;
415
545aeef1 416 if (nhr->nexthop_num) {
6137a77d
DS
417 struct peer *peer = bnc->nht_info;
418
d62a17ae 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
021b6596
AD
423 if (!bnc->is_evpn_gwip_nexthop)
424 bnc->flags |= BGP_NEXTHOP_VALID;
545aeef1
RW
425 bnc->metric = nhr->metric;
426 bnc->nexthop_num = nhr->nexthop_num;
4a749e2c 427
960035b2
PZ
428 bnc->flags &= ~BGP_NEXTHOP_LABELED_VALID; /* check below */
429
545aeef1 430 for (i = 0; i < nhr->nexthop_num; i++) {
960035b2
PZ
431 int num_labels = 0;
432
545aeef1 433 nexthop = nexthop_from_zapi_nexthop(&nhr->nexthops[i]);
d62a17ae 434
6137a77d
DS
435 /*
436 * Turn on RA for the v6 nexthops
437 * we receive from bgp. This is to allow us
438 * to work with v4 routing over v6 nexthops
439 */
687a2b5d
DS
440 if (peer && !peer->ifp
441 && CHECK_FLAG(peer->flags,
442 PEER_FLAG_CAPABILITY_ENHE)
545aeef1 443 && nhr->prefix.family == AF_INET6
65f803e8 444 && nexthop->type != NEXTHOP_TYPE_BLACKHOLE) {
6137a77d
DS
445 struct interface *ifp;
446
447 ifp = if_lookup_by_index(nexthop->ifindex,
448 nexthop->vrf_id);
8c9769e0
DS
449 if (ifp)
450 zclient_send_interface_radv_req(
451 zclient, nexthop->vrf_id, ifp,
452 true,
453 BGP_UNNUM_DEFAULT_RA_INTERVAL);
6137a77d 454 }
960035b2
PZ
455 /* There is at least one label-switched path */
456 if (nexthop->nh_label &&
457 nexthop->nh_label->num_labels) {
458
459 bnc->flags |= BGP_NEXTHOP_LABELED_VALID;
460 num_labels = nexthop->nh_label->num_labels;
461 }
462
d62a17ae 463 if (BGP_DEBUG(nht, NHT)) {
464 char buf[NEXTHOP_STRLEN];
465 zlog_debug(
960035b2
PZ
466 " nhop via %s (%d labels)",
467 nexthop2str(nexthop, buf, sizeof(buf)),
468 num_labels);
d62a17ae 469 }
470
471 if (nhlist_tail) {
472 nhlist_tail->next = nexthop;
473 nhlist_tail = nexthop;
474 } else {
475 nhlist_tail = nexthop;
476 nhlist_head = nexthop;
477 }
478
479 /* No need to evaluate the nexthop if we have already
480 * determined
481 * that there has been a change.
482 */
483 if (bnc->change_flags & BGP_NEXTHOP_CHANGED)
484 continue;
485
486 for (oldnh = bnc->nexthop; oldnh; oldnh = oldnh->next)
78fba41b 487 if (nexthop_same(oldnh, nexthop))
d62a17ae 488 break;
489
490 if (!oldnh)
491 bnc->change_flags |= BGP_NEXTHOP_CHANGED;
492 }
493 bnc_nexthop_free(bnc);
494 bnc->nexthop = nhlist_head;
021b6596
AD
495
496 /*
497 * Gateway IP nexthop is L3 reachable. Mark it as
498 * BGP_NEXTHOP_VALID only if it is recursively resolved with a
499 * remote EVPN RT-2.
500 * Else, mark it as BGP_NEXTHOP_EVPN_INCOMPLETE.
501 * When its mapping with EVPN RT-2 is established, unset
502 * BGP_NEXTHOP_EVPN_INCOMPLETE and set BGP_NEXTHOP_VALID.
503 */
504 if (bnc->is_evpn_gwip_nexthop) {
505 evpn_resolved = bgp_evpn_is_gateway_ip_resolved(bnc);
506
507 if (BGP_DEBUG(nht, NHT)) {
508 char buf2[PREFIX2STR_BUFFER];
509
510 prefix2str(&bnc->prefix, buf2, sizeof(buf2));
511 zlog_debug(
512 "EVPN gateway IP %s recursive MAC/IP lookup %s",
513 buf2,
514 (evpn_resolved ? "successful"
515 : "failed"));
516 }
517
518 if (evpn_resolved) {
519 bnc->flags |= BGP_NEXTHOP_VALID;
520 bnc->flags &= ~BGP_NEXTHOP_EVPN_INCOMPLETE;
521 bnc->change_flags |= BGP_NEXTHOP_MACIP_CHANGED;
522 } else {
523 bnc->flags |= BGP_NEXTHOP_EVPN_INCOMPLETE;
524 bnc->flags &= ~BGP_NEXTHOP_VALID;
525 }
526 }
d62a17ae 527 } else {
021b6596 528 bnc->flags &= ~BGP_NEXTHOP_EVPN_INCOMPLETE;
d62a17ae 529 bnc->flags &= ~BGP_NEXTHOP_VALID;
c3b95419 530 bnc->flags &= ~BGP_NEXTHOP_LABELED_VALID;
545aeef1 531 bnc->nexthop_num = nhr->nexthop_num;
d62a17ae 532
533 /* notify bgp fsm if nbr ip goes from valid->invalid */
534 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
535
536 bnc_nexthop_free(bnc);
537 bnc->nexthop = NULL;
538 }
539
540 evaluate_paths(bnc);
fb018d25
DS
541}
542
8761cd6d
DS
543static void bgp_nht_ifp_table_handle(struct bgp *bgp,
544 struct bgp_nexthop_cache_head *table,
545 struct interface *ifp, bool up)
546{
547 struct bgp_nexthop_cache *bnc;
548
549 frr_each (bgp_nexthop_cache, table, bnc) {
550 if (bnc->ifindex != ifp->ifindex)
551 continue;
552
553 bnc->last_update = bgp_clock();
554 bnc->change_flags = 0;
555
474cfe4a
DS
556 /*
557 * For interface based routes ( ala the v6 LL routes
558 * that this was written for ) the metric received
559 * for the connected route is 0 not 1.
560 */
561 bnc->metric = 0;
8761cd6d
DS
562 if (up) {
563 SET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
564 SET_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED);
8761cd6d
DS
565 bnc->nexthop_num = 1;
566 } else {
567 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
568 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
569 SET_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED);
570 bnc->nexthop_num = 0;
8761cd6d
DS
571 }
572
573 evaluate_paths(bnc);
574 }
575}
576static void bgp_nht_ifp_handle(struct interface *ifp, bool up)
577{
578 struct bgp *bgp;
579
580 bgp = bgp_lookup_by_vrf_id(ifp->vrf_id);
581 if (!bgp)
582 return;
583
584 bgp_nht_ifp_table_handle(bgp, &bgp->nexthop_cache_table[AFI_IP6], ifp,
585 up);
586 bgp_nht_ifp_table_handle(bgp, &bgp->import_check_table[AFI_IP6], ifp,
587 up);
588}
589
590void bgp_nht_ifp_up(struct interface *ifp)
591{
592 bgp_nht_ifp_handle(ifp, true);
593}
594
595void bgp_nht_ifp_down(struct interface *ifp)
596{
597 bgp_nht_ifp_handle(ifp, false);
598}
599
600static int bgp_nht_ifp_initial(struct thread *thread)
601{
602 ifindex_t ifindex = THREAD_VAL(thread);
603 struct interface *ifp = if_lookup_by_index_all_vrf(ifindex);
604
605 if (!ifp)
606 return 0;
607
4115b296 608 if (BGP_DEBUG(nht, NHT))
609 zlog_debug(
610 "Handle NHT initial update for Intf %s(%d) status %s",
611 ifp->name, ifp->ifindex, if_is_up(ifp) ? "up" : "down");
612
8761cd6d
DS
613 if (if_is_up(ifp))
614 bgp_nht_ifp_up(ifp);
615 else
616 bgp_nht_ifp_down(ifp);
617
618 return 0;
619}
620
621/*
622 * So the bnc code has the ability to handle interface up/down
623 * events to properly handle v6 LL peering.
624 * What is happening here:
625 * The event system for peering expects the nht code to
626 * report on the tracking events after we move to active
627 * So let's give the system a chance to report on that event
628 * in a manner that is expected.
629 */
630void bgp_nht_interface_events(struct peer *peer)
631{
632 struct bgp *bgp = peer->bgp;
633 struct bgp_nexthop_cache_head *table;
634 struct bgp_nexthop_cache *bnc;
635 struct prefix p;
636
637 if (!IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr))
638 return;
639
640 if (!sockunion2hostprefix(&peer->su, &p))
641 return;
642
643 table = &bgp->nexthop_cache_table[AFI_IP6];
644 bnc = bnc_find(table, &p, 0);
645 if (!bnc)
646 return;
647
648 if (bnc->ifindex)
649 thread_add_event(bm->master, bgp_nht_ifp_initial, NULL,
650 bnc->ifindex, NULL);
651}
652
545aeef1
RW
653void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
654{
655 struct bgp_nexthop_cache_head *tree = NULL;
656 struct bgp_nexthop_cache *bnc;
657 struct bgp *bgp;
658 struct zapi_route nhr;
659 afi_t afi;
660
661 bgp = bgp_lookup_by_vrf_id(vrf_id);
662 if (!bgp) {
663 flog_err(
664 EC_BGP_NH_UPD,
665 "parse nexthop update: instance not found for vrf_id %u",
666 vrf_id);
667 return;
668 }
669
670 if (!zapi_nexthop_update_decode(zclient->ibuf, &nhr)) {
cc42c4f0
DS
671 zlog_err("%s[%s]: Failure to decode nexthop update", __func__,
672 bgp->name_pretty);
545aeef1
RW
673 return;
674 }
675
676 afi = family2afi(nhr.prefix.family);
677 if (command == ZEBRA_NEXTHOP_UPDATE)
678 tree = &bgp->nexthop_cache_table[afi];
679 else if (command == ZEBRA_IMPORT_CHECK_UPDATE)
680 tree = &bgp->import_check_table[afi];
681
682 bnc = bnc_find(tree, &nhr.prefix, nhr.srte_color);
683 if (!bnc) {
2dbe669b 684 if (BGP_DEBUG(nht, NHT))
545aeef1 685 zlog_debug(
2dbe669b
DA
686 "parse nexthop update(%pFX(%u)(%s)): bnc info not found",
687 &nhr.prefix, nhr.srte_color, bgp->name_pretty);
545aeef1
RW
688 return;
689 }
690
691 bgp_process_nexthop_update(bnc, &nhr);
692
693 /*
694 * HACK: if any BGP route is dependant on an SR-policy that doesn't
695 * exist, zebra will never send NH updates relative to that policy. In
696 * that case, whenever we receive an update about a colorless NH, update
697 * the corresponding colorful NHs that share the same endpoint but that
698 * are inactive. This ugly hack should work around the problem at the
699 * cost of a performance pernalty. Long term, what should be done is to
700 * make zebra's RNH subsystem aware of SR-TE colors (like bgpd is),
701 * which should provide a better infrastructure to solve this issue in
702 * a more efficient and elegant way.
703 */
704 if (nhr.srte_color == 0) {
705 struct bgp_nexthop_cache *bnc_iter;
706
707 frr_each (bgp_nexthop_cache, &bgp->nexthop_cache_table[afi],
708 bnc_iter) {
709 if (!prefix_same(&bnc->prefix, &bnc_iter->prefix)
710 || bnc_iter->srte_color == 0
711 || CHECK_FLAG(bnc_iter->flags, BGP_NEXTHOP_VALID))
712 continue;
713
714 bgp_process_nexthop_update(bnc_iter, &nhr);
715 }
716 }
717}
718
ee7ca6c0 719/*
720 * Cleanup nexthop registration and status information for BGP nexthops
721 * pertaining to this VRF. This is invoked upon VRF deletion.
722 */
723void bgp_cleanup_nexthops(struct bgp *bgp)
724{
f663c581
RW
725 for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++) {
726 struct bgp_nexthop_cache *bnc;
ee7ca6c0 727
f663c581
RW
728 frr_each (bgp_nexthop_cache, &bgp->nexthop_cache_table[afi],
729 bnc) {
ee7ca6c0 730 /* Clear relevant flags. */
731 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
732 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
733 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
021b6596 734 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_EVPN_INCOMPLETE);
ee7ca6c0 735 }
736 }
737}
738
fb018d25
DS
739/**
740 * make_prefix - make a prefix structure from the path (essentially
741 * path's node.
742 */
40381db7 743static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p)
fb018d25 744{
078430f6 745
40381db7
DS
746 int is_bgp_static = ((pi->type == ZEBRA_ROUTE_BGP)
747 && (pi->sub_type == BGP_ROUTE_STATIC))
d62a17ae 748 ? 1
749 : 0;
9bcb3eef
DS
750 struct bgp_dest *net = pi->net;
751 const struct prefix *p_orig = bgp_dest_get_prefix(net);
92d6f769 752 struct in_addr ipv4;
0378bcaa
PG
753
754 if (p_orig->family == AF_FLOWSPEC) {
755 if (!pi->peer)
756 return -1;
757 return bgp_flowspec_get_first_nh(pi->peer->bgp,
1840384b 758 pi, p, afi);
0378bcaa 759 }
d62a17ae 760 memset(p, 0, sizeof(struct prefix));
761 switch (afi) {
762 case AFI_IP:
763 p->family = AF_INET;
764 if (is_bgp_static) {
b54892e0
DS
765 p->u.prefix4 = p_orig->u.prefix4;
766 p->prefixlen = p_orig->prefixlen;
d62a17ae 767 } else {
92d6f769
K
768 if (IS_MAPPED_IPV6(&pi->attr->mp_nexthop_global)) {
769 ipv4_mapped_ipv6_to_ipv4(
770 &pi->attr->mp_nexthop_global, &ipv4);
771 p->u.prefix4 = ipv4;
772 p->prefixlen = IPV4_MAX_BITLEN;
773 } else {
774 p->u.prefix4 = pi->attr->nexthop;
775 p->prefixlen = IPV4_MAX_BITLEN;
776 }
d62a17ae 777 }
778 break;
779 case AFI_IP6:
d62a17ae 780 p->family = AF_INET6;
781
782 if (is_bgp_static) {
b54892e0
DS
783 p->u.prefix6 = p_orig->u.prefix6;
784 p->prefixlen = p_orig->prefixlen;
d62a17ae 785 } else {
606fdbb1
DA
786 /* If we receive MP_REACH nexthop with ::(LL)
787 * or LL(LL), use LL address as nexthop cache.
788 */
789 if (pi->attr->mp_nexthop_len
790 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
791 && (IN6_IS_ADDR_UNSPECIFIED(
792 &pi->attr->mp_nexthop_global)
793 || IN6_IS_ADDR_LINKLOCAL(
794 &pi->attr->mp_nexthop_global)))
795 p->u.prefix6 = pi->attr->mp_nexthop_local;
17ef5a93
PG
796 /* If we receive MR_REACH with (GA)::(LL)
797 * then check for route-map to choose GA or LL
798 */
799 else if (pi->attr->mp_nexthop_len
800 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
801 if (pi->attr->mp_nexthop_prefer_global)
802 p->u.prefix6 =
803 pi->attr->mp_nexthop_global;
804 else
805 p->u.prefix6 =
806 pi->attr->mp_nexthop_local;
807 } else
606fdbb1 808 p->u.prefix6 = pi->attr->mp_nexthop_global;
d62a17ae 809 p->prefixlen = IPV6_MAX_BITLEN;
810 }
811 break;
812 default:
813 if (BGP_DEBUG(nht, NHT)) {
814 zlog_debug(
815 "%s: Attempting to make prefix with unknown AFI %d (not %d or %d)",
15569c58 816 __func__, afi, AFI_IP, AFI_IP6);
d62a17ae 817 }
818 break;
65740e1b 819 }
d62a17ae 820 return 0;
fb018d25
DS
821}
822
823/**
078430f6 824 * sendmsg_zebra_rnh -- Format and send a nexthop register/Unregister
fb018d25
DS
825 * command to Zebra.
826 * ARGUMENTS:
827 * struct bgp_nexthop_cache *bnc -- the nexthop structure.
078430f6 828 * int command -- command to send to zebra
fb018d25
DS
829 * RETURNS:
830 * void.
831 */
d62a17ae 832static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command)
fb018d25 833{
3c192540 834 bool exact_match = false;
d62a17ae 835 int ret;
836
3c192540 837 if (!zclient)
d62a17ae 838 return;
839
840 /* Don't try to register if Zebra doesn't know of this instance. */
bb4ef1ae
DS
841 if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bnc->bgp)) {
842 if (BGP_DEBUG(zebra, ZEBRA))
15569c58
DA
843 zlog_debug(
844 "%s: No zebra instance to talk to, not installing NHT entry",
845 __func__);
d62a17ae 846 return;
bb4ef1ae 847 }
d62a17ae 848
1ee0a2df
DS
849 if (!bgp_zebra_num_connects()) {
850 if (BGP_DEBUG(zebra, ZEBRA))
15569c58
DA
851 zlog_debug(
852 "%s: We have not connected yet, cannot send nexthops",
853 __func__);
1ee0a2df 854 }
996c9314
LB
855 if ((command == ZEBRA_NEXTHOP_REGISTER
856 || command == ZEBRA_IMPORT_ROUTE_REGISTER)
857 && (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)
858 || CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)))
3c192540 859 exact_match = true;
d62a17ae 860
f663c581
RW
861 if (BGP_DEBUG(zebra, ZEBRA))
862 zlog_debug("%s: sending cmd %s for %pFX (vrf %s)", __func__,
863 zserv_command_string(command), &bnc->prefix,
864 bnc->bgp->name_pretty);
960035b2 865
f663c581 866 ret = zclient_send_rnh(zclient, command, &bnc->prefix, exact_match,
996c9314 867 bnc->bgp->vrf_id);
d62a17ae 868 /* TBD: handle the failure */
7cfdb485 869 if (ret == ZCLIENT_SEND_FAILURE)
e50f7cfd 870 flog_warn(EC_BGP_ZEBRA_SEND,
f162a5b9 871 "sendmsg_nexthop: zclient_send_message() failed");
d62a17ae 872
873 if ((command == ZEBRA_NEXTHOP_REGISTER)
874 || (command == ZEBRA_IMPORT_ROUTE_REGISTER))
875 SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
876 else if ((command == ZEBRA_NEXTHOP_UNREGISTER)
877 || (command == ZEBRA_IMPORT_ROUTE_UNREGISTER))
878 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
879 return;
fb018d25
DS
880}
881
882/**
078430f6
DS
883 * register_zebra_rnh - register a NH/route with Zebra for notification
884 * when the route or the route to the nexthop changes.
fb018d25 885 * ARGUMENTS:
078430f6 886 * struct bgp_nexthop_cache *bnc
fb018d25
DS
887 * RETURNS:
888 * void.
889 */
d62a17ae 890static void register_zebra_rnh(struct bgp_nexthop_cache *bnc,
891 int is_bgp_import_route)
fb018d25 892{
d62a17ae 893 /* Check if we have already registered */
894 if (bnc->flags & BGP_NEXTHOP_REGISTERED)
895 return;
8761cd6d
DS
896
897 if (bnc->ifindex) {
898 SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
899 return;
900 }
901
d62a17ae 902 if (is_bgp_import_route)
903 sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_REGISTER);
904 else
905 sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_REGISTER);
fb018d25
DS
906}
907
908/**
078430f6 909 * unregister_zebra_rnh -- Unregister the route/nexthop from Zebra.
fb018d25 910 * ARGUMENTS:
078430f6 911 * struct bgp_nexthop_cache *bnc
fb018d25
DS
912 * RETURNS:
913 * void.
914 */
d62a17ae 915static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc,
916 int is_bgp_import_route)
fb018d25 917{
d62a17ae 918 /* Check if we have already registered */
919 if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
920 return;
921
8761cd6d
DS
922 if (bnc->ifindex) {
923 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
924 return;
925 }
926
d62a17ae 927 if (is_bgp_import_route)
928 sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_UNREGISTER);
929 else
930 sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_UNREGISTER);
fb018d25
DS
931}
932
933/**
934 * evaluate_paths - Evaluate the paths/nets associated with a nexthop.
935 * ARGUMENTS:
936 * struct bgp_nexthop_cache *bnc -- the nexthop structure.
937 * RETURNS:
938 * void.
939 */
021b6596 940void evaluate_paths(struct bgp_nexthop_cache *bnc)
fb018d25 941{
9bcb3eef 942 struct bgp_dest *dest;
4b7e6066 943 struct bgp_path_info *path;
d62a17ae 944 int afi;
945 struct peer *peer = (struct peer *)bnc->nht_info;
946 struct bgp_table *table;
947 safi_t safi;
960035b2 948 struct bgp *bgp_path;
b54892e0 949 const struct prefix *p;
d62a17ae 950
951 if (BGP_DEBUG(nht, NHT)) {
952 char buf[PREFIX2STR_BUFFER];
987a720a 953 char bnc_buf[BNC_FLAG_DUMP_SIZE];
df2a41a9 954 char chg_buf[BNC_FLAG_DUMP_SIZE];
987a720a 955
d62a17ae 956 bnc_str(bnc, buf, PREFIX2STR_BUFFER);
957 zlog_debug(
df2a41a9 958 "NH update for %s(%u)(%s) - flags %s chgflags %s- evaluate paths",
987a720a 959 buf, bnc->srte_color, bnc->bgp->name_pretty,
df2a41a9
DS
960 bgp_nexthop_dump_bnc_flags(bnc, bnc_buf,
961 sizeof(bnc_buf)),
962 bgp_nexthop_dump_bnc_change_flags(bnc, chg_buf,
963 sizeof(bnc_buf)));
fb018d25
DS
964 }
965
a2addae8 966 LIST_FOREACH (path, &(bnc->paths), nh_thread) {
d62a17ae 967 if (!(path->type == ZEBRA_ROUTE_BGP
968 && ((path->sub_type == BGP_ROUTE_NORMAL)
960035b2
PZ
969 || (path->sub_type == BGP_ROUTE_STATIC)
970 || (path->sub_type == BGP_ROUTE_IMPORTED))))
d62a17ae 971 continue;
972
9bcb3eef
DS
973 dest = path->net;
974 assert(dest && bgp_dest_table(dest));
975 p = bgp_dest_get_prefix(dest);
b54892e0 976 afi = family2afi(p->family);
9bcb3eef 977 table = bgp_dest_table(dest);
d62a17ae 978 safi = table->safi;
979
960035b2
PZ
980 /*
981 * handle routes from other VRFs (they can have a
982 * nexthop in THIS VRF). bgp_path is the bgp instance
983 * that owns the route referencing this nexthop.
984 */
985 bgp_path = table->bgp;
986
987 /*
988 * Path becomes valid/invalid depending on whether the nexthop
d62a17ae 989 * reachable/unreachable.
960035b2
PZ
990 *
991 * In case of unicast routes that were imported from vpn
992 * and that have labels, they are valid only if there are
993 * nexthops with labels
a2299aba
AD
994 *
995 * If the nexthop is EVPN gateway-IP,
996 * do not check for a valid label.
d62a17ae 997 */
960035b2 998
34ea39b6 999 bool bnc_is_valid_nexthop = false;
1000 bool path_valid = false;
960035b2 1001
021b6596
AD
1002 if (safi == SAFI_UNICAST && path->sub_type == BGP_ROUTE_IMPORTED
1003 && path->extra && path->extra->num_labels
1004 && (path->attr->evpn_overlay.type
1005 != OVERLAY_INDEX_GATEWAY_IP)) {
960035b2 1006 bnc_is_valid_nexthop =
34ea39b6 1007 bgp_isvalid_labeled_nexthop(bnc) ? true : false;
960035b2 1008 } else {
e7cbe5e5
NT
1009 if (bgp_update_martian_nexthop(
1010 bnc->bgp, afi, safi, path->type,
9bcb3eef 1011 path->sub_type, path->attr, dest)) {
e7cbe5e5
NT
1012 if (BGP_DEBUG(nht, NHT))
1013 zlog_debug(
56ca3b5b 1014 "%s: prefix %pBD (vrf %s), ignoring path due to martian or self-next-hop",
9bcb3eef 1015 __func__, dest, bgp_path->name);
e7cbe5e5
NT
1016 } else
1017 bnc_is_valid_nexthop =
34ea39b6 1018 bgp_isvalid_nexthop(bnc) ? true : false;
960035b2
PZ
1019 }
1020
9e15d76a 1021 if (BGP_DEBUG(nht, NHT)) {
1022 char buf1[RD_ADDRSTRLEN];
960035b2 1023
9bcb3eef
DS
1024 if (dest->pdest) {
1025 prefix_rd2str((struct prefix_rd *)bgp_dest_get_prefix(dest->pdest),
9e15d76a 1026 buf1, sizeof(buf1));
1027 zlog_debug(
56ca3b5b 1028 "... eval path %d/%d %pBD RD %s %s flags 0x%x",
9bcb3eef 1029 afi, safi, dest, buf1,
9e15d76a 1030 bgp_path->name_pretty, path->flags);
1031 } else
1032 zlog_debug(
56ca3b5b 1033 "... eval path %d/%d %pBD %s flags 0x%x",
9bcb3eef 1034 afi, safi, dest, bgp_path->name_pretty,
9e15d76a 1035 path->flags);
1036 }
d62a17ae 1037
0139efe0 1038 /* Skip paths marked for removal or as history. */
1039 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)
1040 || CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
1041 continue;
1042
d62a17ae 1043 /* Copy the metric to the path. Will be used for bestpath
1044 * computation */
1045 if (bgp_isvalid_nexthop(bnc) && bnc->metric)
18ee8310
DS
1046 (bgp_path_info_extra_get(path))->igpmetric =
1047 bnc->metric;
d62a17ae 1048 else if (path->extra)
1049 path->extra->igpmetric = 0;
1050
1051 if (CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED)
545aeef1
RW
1052 || CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED)
1053 || path->attr->srte_color != 0)
1defdda8 1054 SET_FLAG(path->flags, BGP_PATH_IGP_CHANGED);
d62a17ae 1055
d4980edf 1056 path_valid = CHECK_FLAG(path->flags, BGP_PATH_VALID);
34ea39b6 1057 if (path_valid != bnc_is_valid_nexthop) {
1058 if (path_valid) {
1059 /* No longer valid, clear flag; also for EVPN
1060 * routes, unimport from VRFs if needed.
1061 */
1062 bgp_aggregate_decrement(bgp_path, p, path, afi,
1063 safi);
9bcb3eef 1064 bgp_path_info_unset_flag(dest, path,
34ea39b6 1065 BGP_PATH_VALID);
1066 if (safi == SAFI_EVPN &&
9bcb3eef 1067 bgp_evpn_is_prefix_nht_supported(bgp_dest_get_prefix(dest)))
34ea39b6 1068 bgp_evpn_unimport_route(bgp_path,
9bcb3eef 1069 afi, safi, bgp_dest_get_prefix(dest), path);
34ea39b6 1070 } else {
1071 /* Path becomes valid, set flag; also for EVPN
1072 * routes, import from VRFs if needed.
1073 */
9bcb3eef 1074 bgp_path_info_set_flag(dest, path,
34ea39b6 1075 BGP_PATH_VALID);
1076 bgp_aggregate_increment(bgp_path, p, path, afi,
1077 safi);
1078 if (safi == SAFI_EVPN &&
9bcb3eef 1079 bgp_evpn_is_prefix_nht_supported(bgp_dest_get_prefix(dest)))
34ea39b6 1080 bgp_evpn_import_route(bgp_path,
9bcb3eef 1081 afi, safi, bgp_dest_get_prefix(dest), path);
34ea39b6 1082 }
7c312383
AD
1083 }
1084
9bcb3eef 1085 bgp_process(bgp_path, dest, afi, safi);
d62a17ae 1086 }
fc9a856f 1087
1e91f1d1
DS
1088 if (peer) {
1089 int valid_nexthops = bgp_isvalid_nexthop(bnc);
1090
824065c4
DS
1091 if (valid_nexthops) {
1092 /*
1093 * Peering cannot occur across a blackhole nexthop
1094 */
e817f2cc 1095 if (bnc->nexthop_num == 1 && bnc->nexthop
824065c4
DS
1096 && bnc->nexthop->type == NEXTHOP_TYPE_BLACKHOLE) {
1097 peer->last_reset = PEER_DOWN_WAITING_NHT;
1098 valid_nexthops = 0;
1099 } else
1100 peer->last_reset = PEER_DOWN_WAITING_OPEN;
1101 } else
1e91f1d1
DS
1102 peer->last_reset = PEER_DOWN_WAITING_NHT;
1103
1104 if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED)) {
1105 if (BGP_DEBUG(nht, NHT))
15569c58 1106 zlog_debug(
8761cd6d 1107 "%s: Updating peer (%s(%s)) status with NHT nexthops %d",
15569c58 1108 __func__, peer->host,
8761cd6d
DS
1109 peer->bgp->name_pretty,
1110 !!valid_nexthops);
f8dcd38d 1111 bgp_fsm_nht_update(peer, !!valid_nexthops);
1e91f1d1
DS
1112 SET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
1113 }
d62a17ae 1114 }
fc9a856f 1115
d62a17ae 1116 RESET_FLAG(bnc->change_flags);
fb018d25
DS
1117}
1118
1119/**
1120 * path_nh_map - make or break path-to-nexthop association.
1121 * ARGUMENTS:
1122 * path - pointer to the path structure
1123 * bnc - pointer to the nexthop structure
1124 * make - if set, make the association. if unset, just break the existing
1125 * association.
1126 */
7f040da1
DS
1127void path_nh_map(struct bgp_path_info *path, struct bgp_nexthop_cache *bnc,
1128 bool make)
fb018d25 1129{
d62a17ae 1130 if (path->nexthop) {
1131 LIST_REMOVE(path, nh_thread);
1132 path->nexthop->path_count--;
1133 path->nexthop = NULL;
1134 }
1135 if (make) {
1136 LIST_INSERT_HEAD(&(bnc->paths), path, nh_thread);
1137 path->nexthop = bnc;
1138 path->nexthop->path_count++;
1139 }
fb018d25 1140}
1ee0a2df
DS
1141
1142/*
1143 * This function is called to register nexthops to zebra
1144 * as that we may have tried to install the nexthops
1145 * before we actually have a zebra connection
1146 */
1147void bgp_nht_register_nexthops(struct bgp *bgp)
1148{
f663c581
RW
1149 for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++) {
1150 struct bgp_nexthop_cache *bnc;
1ee0a2df 1151
f663c581
RW
1152 frr_each (bgp_nexthop_cache, &bgp->nexthop_cache_table[afi],
1153 bnc) {
1ee0a2df
DS
1154 register_zebra_rnh(bnc, 0);
1155 }
1156 }
1157}
1ea03b90 1158
b3a3290e 1159void bgp_nht_reg_enhe_cap_intfs(struct peer *peer)
1ea03b90
DS
1160{
1161 struct bgp *bgp;
1ea03b90
DS
1162 struct bgp_nexthop_cache *bnc;
1163 struct nexthop *nhop;
1164 struct interface *ifp;
1165 struct prefix p;
1166
1167 if (peer->ifp)
1168 return;
1169
1170 bgp = peer->bgp;
1ea03b90 1171 if (!sockunion2hostprefix(&peer->su, &p)) {
b3a3290e
DS
1172 zlog_warn("%s: Unable to convert sockunion to prefix for %s",
1173 __func__, peer->host);
1ea03b90
DS
1174 return;
1175 }
1176
1177 if (p.family != AF_INET6)
1178 return;
1ea03b90 1179
545aeef1 1180 bnc = bnc_find(&bgp->nexthop_cache_table[AFI_IP6], &p, 0);
1ea03b90
DS
1181 if (!bnc)
1182 return;
1183
1184 if (peer != bnc->nht_info)
1185 return;
1186
1187 for (nhop = bnc->nexthop; nhop; nhop = nhop->next) {
8c9769e0
DS
1188 ifp = if_lookup_by_index(nhop->ifindex, nhop->vrf_id);
1189
1190 if (!ifp)
1191 continue;
1192
1ea03b90
DS
1193 zclient_send_interface_radv_req(zclient,
1194 nhop->vrf_id,
1195 ifp, true,
1196 BGP_UNNUM_DEFAULT_RA_INTERVAL);
1197 }
1198}
b3a3290e
DS
1199
1200void bgp_nht_dereg_enhe_cap_intfs(struct peer *peer)
1201{
1202 struct bgp *bgp;
b3a3290e
DS
1203 struct bgp_nexthop_cache *bnc;
1204 struct nexthop *nhop;
1205 struct interface *ifp;
1206 struct prefix p;
1207
1208 if (peer->ifp)
1209 return;
1210
1211 bgp = peer->bgp;
1212
b3a3290e
DS
1213 if (!sockunion2hostprefix(&peer->su, &p)) {
1214 zlog_warn("%s: Unable to convert sockunion to prefix for %s",
1215 __func__, peer->host);
1216 return;
1217 }
1218
1219 if (p.family != AF_INET6)
1220 return;
1221
545aeef1 1222 bnc = bnc_find(&bgp->nexthop_cache_table[AFI_IP6], &p, 0);
b3a3290e
DS
1223 if (!bnc)
1224 return;
1225
1226 if (peer != bnc->nht_info)
1227 return;
1228
1229 for (nhop = bnc->nexthop; nhop; nhop = nhop->next) {
1230 ifp = if_lookup_by_index(nhop->ifindex, nhop->vrf_id);
1231
68cecc3b
DS
1232 if (!ifp)
1233 continue;
1234
b3a3290e
DS
1235 zclient_send_interface_radv_req(zclient, nhop->vrf_id, ifp, 0,
1236 0);
1237 }
1238}
c589d847
AK
1239
1240/****************************************************************************
1241 * L3 NHGs are used for fast failover of nexthops in the dplane. These are
1242 * the APIs for allocating L3 NHG ids. Management of the L3 NHG itself is
1243 * left to the application using it.
1244 * PS: Currently EVPN host routes is the only app using L3 NHG for fast
1245 * failover of remote ES links.
1246 ***************************************************************************/
1247static bitfield_t bgp_nh_id_bitmap;
8bcb09a1 1248static uint32_t bgp_l3nhg_start;
c589d847 1249
8bcb09a1
AK
1250/* XXX - currently we do nothing on the callbacks */
1251static void bgp_l3nhg_add_cb(const char *name)
1252{
1253}
1254static void bgp_l3nhg_add_nexthop_cb(const struct nexthop_group_cmd *nhgc,
1255 const struct nexthop *nhop)
1256{
1257}
1258static void bgp_l3nhg_del_nexthop_cb(const struct nexthop_group_cmd *nhgc,
1259 const struct nexthop *nhop)
1260{
1261}
1262static void bgp_l3nhg_del_cb(const char *name)
c589d847 1263{
c589d847
AK
1264}
1265
8bcb09a1 1266static void bgp_l3nhg_zebra_init(void)
c589d847 1267{
8bcb09a1
AK
1268 static bool bgp_l3nhg_zebra_inited;
1269 if (bgp_l3nhg_zebra_inited)
c589d847
AK
1270 return;
1271
8bcb09a1
AK
1272 bgp_l3nhg_zebra_inited = true;
1273 bgp_l3nhg_start = zclient_get_nhg_start(ZEBRA_ROUTE_BGP);
1274 nexthop_group_init(bgp_l3nhg_add_cb, bgp_l3nhg_add_nexthop_cb,
1275 bgp_l3nhg_del_nexthop_cb, bgp_l3nhg_del_cb);
c589d847
AK
1276}
1277
8bcb09a1
AK
1278
1279#define min(A, B) ((A) < (B) ? (A) : (B))
c589d847
AK
1280void bgp_l3nhg_init(void)
1281{
8bcb09a1
AK
1282 uint32_t id_max;
1283
1284 id_max = min(ZEBRA_NHG_PROTO_SPACING - 1, 16 * 1024);
1285 bf_init(bgp_nh_id_bitmap, id_max);
c589d847 1286 bf_assign_zero_index(bgp_nh_id_bitmap);
8bcb09a1
AK
1287
1288 if (BGP_DEBUG(nht, NHT) || BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1289 zlog_debug("bgp l3_nhg range %u - %u", bgp_l3nhg_start + 1,
1290 bgp_l3nhg_start + id_max);
c589d847
AK
1291}
1292
1293void bgp_l3nhg_finish(void)
1294{
1295 bf_free(bgp_nh_id_bitmap);
1296}
8bcb09a1
AK
1297
1298uint32_t bgp_l3nhg_id_alloc(void)
1299{
1300 uint32_t nhg_id = 0;
1301
1302 bgp_l3nhg_zebra_init();
1303 bf_assign_index(bgp_nh_id_bitmap, nhg_id);
1304 if (nhg_id)
1305 nhg_id += bgp_l3nhg_start;
1306
1307 return nhg_id;
1308}
1309
1310void bgp_l3nhg_id_free(uint32_t nhg_id)
1311{
1312 if (!nhg_id || (nhg_id <= bgp_l3nhg_start))
1313 return;
1314
1315 nhg_id -= bgp_l3nhg_start;
1316
1317 bf_release_index(bgp_nh_id_bitmap, nhg_id);
1318}