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