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