]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_nht.c
Merge pull request #5787 from karamalla0406/rmac_check
[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
35 #include "bgpd/bgpd.h"
36 #include "bgpd/bgp_table.h"
37 #include "bgpd/bgp_route.h"
38 #include "bgpd/bgp_attr.h"
39 #include "bgpd/bgp_nexthop.h"
40 #include "bgpd/bgp_debug.h"
41 #include "bgpd/bgp_errors.h"
42 #include "bgpd/bgp_nht.h"
43 #include "bgpd/bgp_fsm.h"
44 #include "bgpd/bgp_zebra.h"
45 #include "bgpd/bgp_flowspec_util.h"
46 #include "bgpd/bgp_evpn.h"
47
48 extern struct zclient *zclient;
49
50 static void register_zebra_rnh(struct bgp_nexthop_cache *bnc,
51 int is_bgp_static_route);
52 static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc,
53 int is_bgp_static_route);
54 static void evaluate_paths(struct bgp_nexthop_cache *bnc);
55 static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p);
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 }
62
63 static int bgp_isvalid_labeled_nexthop(struct bgp_nexthop_cache *bnc)
64 {
65 return (bgp_zebra_num_connects() == 0
66 || (bnc && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID)));
67 }
68
69 static void bgp_unlink_nexthop_check(struct bgp_nexthop_cache *bnc)
70 {
71 if (LIST_EMPTY(&(bnc->paths)) && !bnc->nht_info) {
72 if (BGP_DEBUG(nht, NHT)) {
73 char buf[PREFIX2STR_BUFFER];
74 zlog_debug("bgp_unlink_nexthop: freeing bnc %s(%s)",
75 bnc_str(bnc, buf, PREFIX2STR_BUFFER),
76 bnc->bgp->name_pretty);
77 }
78 unregister_zebra_rnh(bnc,
79 CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE));
80 bgp_node_set_bgp_nexthop_info(bnc->node, NULL);
81 bgp_unlock_node(bnc->node);
82 bnc->node = NULL;
83 bnc_free(bnc);
84 }
85 }
86
87 void bgp_unlink_nexthop(struct bgp_path_info *path)
88 {
89 struct bgp_nexthop_cache *bnc = path->nexthop;
90
91 if (!bnc)
92 return;
93
94 path_nh_map(path, NULL, false);
95
96 bgp_unlink_nexthop_check(bnc);
97 }
98
99 void bgp_unlink_nexthop_by_peer(struct peer *peer)
100 {
101 struct prefix p;
102 struct bgp_node *rn;
103 struct bgp_nexthop_cache *bnc;
104 afi_t afi = family2afi(peer->su.sa.sa_family);
105
106 if (!sockunion2hostprefix(&peer->su, &p))
107 return;
108
109 rn = bgp_node_get(peer->bgp->nexthop_cache_table[afi], &p);
110
111 bnc = bgp_node_get_bgp_nexthop_info(rn);
112 if (!bnc)
113 return;
114
115 /* cleanup the peer reference */
116 bnc->nht_info = NULL;
117
118 bgp_unlink_nexthop_check(bnc);
119 }
120
121 /*
122 * A route and its nexthop might belong to different VRFs. Therefore,
123 * we need both the bgp_route and bgp_nexthop pointers.
124 */
125 int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
126 afi_t afi, struct bgp_path_info *pi,
127 struct peer *peer, int connected)
128 {
129 struct bgp_node *rn;
130 struct bgp_nexthop_cache *bnc;
131 struct prefix p;
132 int is_bgp_static_route = 0;
133
134 if (pi) {
135 is_bgp_static_route = ((pi->type == ZEBRA_ROUTE_BGP)
136 && (pi->sub_type == BGP_ROUTE_STATIC))
137 ? 1
138 : 0;
139
140 /* Since Extended Next-hop Encoding (RFC5549) support, we want
141 to derive
142 address-family from the next-hop. */
143 if (!is_bgp_static_route)
144 afi = BGP_ATTR_NEXTHOP_AFI_IP6(pi->attr) ? AFI_IP6
145 : AFI_IP;
146
147 /* This will return true if the global IPv6 NH is a link local
148 * addr */
149 if (make_prefix(afi, pi, &p) < 0)
150 return 1;
151 } else if (peer) {
152 if (!sockunion2hostprefix(&peer->su, &p)) {
153 if (BGP_DEBUG(nht, NHT)) {
154 zlog_debug(
155 "%s: Attempting to register with unknown AFI %d (not %d or %d)",
156 __FUNCTION__, afi, AFI_IP, AFI_IP6);
157 }
158 return 0;
159 }
160 } else
161 return 0;
162
163 if (is_bgp_static_route)
164 rn = bgp_node_get(bgp_nexthop->import_check_table[afi], &p);
165 else
166 rn = bgp_node_get(bgp_nexthop->nexthop_cache_table[afi], &p);
167
168 bnc = bgp_node_get_bgp_nexthop_info(rn);
169 if (!bnc) {
170 bnc = bnc_new();
171 bgp_node_set_bgp_nexthop_info(rn, bnc);
172 bnc->node = rn;
173 bnc->bgp = bgp_nexthop;
174 bgp_lock_node(rn);
175 if (BGP_DEBUG(nht, NHT)) {
176 char buf[PREFIX2STR_BUFFER];
177
178 zlog_debug("Allocated bnc %s(%s) peer %p",
179 bnc_str(bnc, buf, PREFIX2STR_BUFFER),
180 bnc->bgp->name_pretty, peer);
181 }
182 }
183
184 bgp_unlock_node(rn);
185 if (is_bgp_static_route) {
186 SET_FLAG(bnc->flags, BGP_STATIC_ROUTE);
187
188 /* If we're toggling the type, re-register */
189 if ((CHECK_FLAG(bgp_route->flags, BGP_FLAG_IMPORT_CHECK))
190 && !CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)) {
191 SET_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH);
192 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
193 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
194 } else if ((!CHECK_FLAG(bgp_route->flags,
195 BGP_FLAG_IMPORT_CHECK))
196 && CHECK_FLAG(bnc->flags,
197 BGP_STATIC_ROUTE_EXACT_MATCH)) {
198 UNSET_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH);
199 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
200 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
201 }
202 }
203 /* When nexthop is already known, but now requires 'connected'
204 * resolution,
205 * re-register it. The reverse scenario where the nexthop currently
206 * requires
207 * 'connected' resolution does not need a re-register (i.e., we treat
208 * 'connected-required' as an override) except in the scenario where
209 * this
210 * is actually a case of tracking a peer for connectivity (e.g., after
211 * disable connected-check).
212 * NOTE: We don't track the number of paths separately for 'connected-
213 * required' vs 'connected-not-required' as this change is not a common
214 * scenario.
215 */
216 else if (connected && !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) {
217 SET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED);
218 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
219 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
220 } else if (peer && !connected
221 && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) {
222 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED);
223 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
224 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
225 }
226 if (bgp_route->inst_type == BGP_INSTANCE_TYPE_VIEW) {
227 SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
228 SET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
229 } else if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED) &&
230 !is_default_host_route(&bnc->node->p))
231 register_zebra_rnh(bnc, is_bgp_static_route);
232
233 if (pi && pi->nexthop != bnc) {
234 /* Unlink from existing nexthop cache, if any. This will also
235 * free
236 * the nexthop cache entry, if appropriate.
237 */
238 bgp_unlink_nexthop(pi);
239
240 /* updates NHT pi list reference */
241 path_nh_map(pi, bnc, true);
242
243 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric)
244 (bgp_path_info_extra_get(pi))->igpmetric = bnc->metric;
245 else if (pi->extra)
246 pi->extra->igpmetric = 0;
247 } else if (peer)
248 bnc->nht_info = (void *)peer; /* NHT peer reference */
249
250 /*
251 * We are cheating here. Views have no associated underlying
252 * ability to detect nexthops. So when we have a view
253 * just tell everyone the nexthop is valid
254 */
255 if (bgp_route->inst_type == BGP_INSTANCE_TYPE_VIEW)
256 return 1;
257 else
258 return (bgp_isvalid_nexthop(bnc));
259 }
260
261 void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer)
262 {
263 struct bgp_node *rn;
264 struct bgp_nexthop_cache *bnc;
265 struct prefix p;
266
267 if (!peer)
268 return;
269
270 if (!sockunion2hostprefix(&peer->su, &p))
271 return;
272
273 rn = bgp_node_lookup(
274 peer->bgp->nexthop_cache_table[family2afi(p.family)], &p);
275 if (!rn) {
276 if (BGP_DEBUG(nht, NHT))
277 zlog_debug(
278 "Cannot find connected NHT node for peer %s(%s)",
279 peer->host, peer->bgp->name_pretty);
280 return;
281 }
282
283 bnc = bgp_node_get_bgp_nexthop_info(rn);
284 if (!bnc) {
285 if (BGP_DEBUG(nht, NHT))
286 zlog_debug(
287 "Cannot find connected NHT node for peer %s(%s) on route_node as expected",
288 peer->host, peer->bgp->name_pretty);
289 bgp_unlock_node(rn);
290 return;
291 }
292 bgp_unlock_node(rn);
293
294 if (bnc->nht_info != peer) {
295 if (BGP_DEBUG(nht, NHT))
296 zlog_debug(
297 "Connected NHT %p node for peer %s(%s) points to %p",
298 bnc, peer->host, bnc->bgp->name_pretty,
299 bnc->nht_info);
300 return;
301 }
302
303 bnc->nht_info = NULL;
304
305 if (LIST_EMPTY(&(bnc->paths))) {
306 if (BGP_DEBUG(nht, NHT))
307 zlog_debug(
308 "Freeing connected NHT node %p for peer %s(%s)",
309 bnc, peer->host, bnc->bgp->name_pretty);
310 unregister_zebra_rnh(bnc, 0);
311 bgp_node_set_bgp_nexthop_info(bnc->node, NULL);
312 bgp_unlock_node(bnc->node);
313 bnc_free(bnc);
314 }
315 }
316
317 void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
318 {
319 struct bgp_node *rn = NULL;
320 struct bgp_nexthop_cache *bnc;
321 struct nexthop *nexthop;
322 struct nexthop *oldnh;
323 struct nexthop *nhlist_head = NULL;
324 struct nexthop *nhlist_tail = NULL;
325 int i;
326 struct bgp *bgp;
327 struct zapi_route nhr;
328
329 bgp = bgp_lookup_by_vrf_id(vrf_id);
330 if (!bgp) {
331 flog_err(
332 EC_BGP_NH_UPD,
333 "parse nexthop update: instance not found for vrf_id %u",
334 vrf_id);
335 return;
336 }
337
338 if (!zapi_nexthop_update_decode(zclient->ibuf, &nhr)) {
339 if (BGP_DEBUG(nht, NHT))
340 zlog_debug("%s[%s]: Failure to decode nexthop update",
341 __PRETTY_FUNCTION__, bgp->name_pretty);
342 return;
343 }
344
345 if (command == ZEBRA_NEXTHOP_UPDATE)
346 rn = bgp_node_lookup(
347 bgp->nexthop_cache_table[family2afi(nhr.prefix.family)],
348 &nhr.prefix);
349 else if (command == ZEBRA_IMPORT_CHECK_UPDATE)
350 rn = bgp_node_lookup(
351 bgp->import_check_table[family2afi(nhr.prefix.family)],
352 &nhr.prefix);
353
354 if (!rn) {
355 if (BGP_DEBUG(nht, NHT)) {
356 char buf[PREFIX2STR_BUFFER];
357 prefix2str(&nhr.prefix, buf, sizeof(buf));
358 zlog_debug("parse nexthop update(%s(%s)): rn not found",
359 buf, bgp->name_pretty);
360 }
361 return;
362 }
363
364 bnc = bgp_node_get_bgp_nexthop_info(rn);
365 if (!bnc) {
366 if (BGP_DEBUG(nht, NHT)) {
367 char buf[PREFIX2STR_BUFFER];
368
369 prefix2str(&nhr.prefix, buf, sizeof(buf));
370 zlog_debug(
371 "parse nexthop update(%s(%s)): bnc node info not found",
372 buf, bgp->name_pretty);
373 }
374 bgp_unlock_node(rn);
375 return;
376 }
377
378 bgp_unlock_node(rn);
379 bnc->last_update = bgp_clock();
380 bnc->change_flags = 0;
381
382 /* debug print the input */
383 if (BGP_DEBUG(nht, NHT)) {
384 char buf[PREFIX2STR_BUFFER];
385 prefix2str(&nhr.prefix, buf, sizeof(buf));
386 zlog_debug(
387 "%s(%u): Rcvd NH update %s - metric %d/%d #nhops %d/%d flags 0x%x",
388 bnc->bgp->name_pretty, vrf_id, buf, nhr.metric,
389 bnc->metric, nhr.nexthop_num, bnc->nexthop_num,
390 bnc->flags);
391 }
392
393 if (nhr.metric != bnc->metric)
394 bnc->change_flags |= BGP_NEXTHOP_METRIC_CHANGED;
395
396 if (nhr.nexthop_num != bnc->nexthop_num)
397 bnc->change_flags |= BGP_NEXTHOP_CHANGED;
398
399 if (nhr.nexthop_num) {
400 struct peer *peer = bnc->nht_info;
401
402 /* notify bgp fsm if nbr ip goes from invalid->valid */
403 if (!bnc->nexthop_num)
404 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
405
406 bnc->flags |= BGP_NEXTHOP_VALID;
407 bnc->metric = nhr.metric;
408 bnc->nexthop_num = nhr.nexthop_num;
409
410 bnc->flags &= ~BGP_NEXTHOP_LABELED_VALID; /* check below */
411
412 for (i = 0; i < nhr.nexthop_num; i++) {
413 int num_labels = 0;
414
415 nexthop = nexthop_from_zapi_nexthop(&nhr.nexthops[i]);
416
417 /*
418 * Turn on RA for the v6 nexthops
419 * we receive from bgp. This is to allow us
420 * to work with v4 routing over v6 nexthops
421 */
422 if (peer && !peer->ifp
423 && CHECK_FLAG(peer->flags,
424 PEER_FLAG_CAPABILITY_ENHE)
425 && nhr.prefix.family == AF_INET6
426 && nexthop->type != NEXTHOP_TYPE_BLACKHOLE) {
427 struct interface *ifp;
428
429 ifp = if_lookup_by_index(nexthop->ifindex,
430 nexthop->vrf_id);
431 zclient_send_interface_radv_req(
432 zclient, nexthop->vrf_id, ifp, true,
433 BGP_UNNUM_DEFAULT_RA_INTERVAL);
434 }
435 /* There is at least one label-switched path */
436 if (nexthop->nh_label &&
437 nexthop->nh_label->num_labels) {
438
439 bnc->flags |= BGP_NEXTHOP_LABELED_VALID;
440 num_labels = nexthop->nh_label->num_labels;
441 }
442
443 if (BGP_DEBUG(nht, NHT)) {
444 char buf[NEXTHOP_STRLEN];
445 zlog_debug(
446 " nhop via %s (%d labels)",
447 nexthop2str(nexthop, buf, sizeof(buf)),
448 num_labels);
449 }
450
451 if (nhlist_tail) {
452 nhlist_tail->next = nexthop;
453 nhlist_tail = nexthop;
454 } else {
455 nhlist_tail = nexthop;
456 nhlist_head = nexthop;
457 }
458
459 /* No need to evaluate the nexthop if we have already
460 * determined
461 * that there has been a change.
462 */
463 if (bnc->change_flags & BGP_NEXTHOP_CHANGED)
464 continue;
465
466 for (oldnh = bnc->nexthop; oldnh; oldnh = oldnh->next)
467 if (nexthop_same(oldnh, nexthop))
468 break;
469
470 if (!oldnh)
471 bnc->change_flags |= BGP_NEXTHOP_CHANGED;
472 }
473 bnc_nexthop_free(bnc);
474 bnc->nexthop = nhlist_head;
475 } else {
476 bnc->flags &= ~BGP_NEXTHOP_VALID;
477 bnc->nexthop_num = nhr.nexthop_num;
478
479 /* notify bgp fsm if nbr ip goes from valid->invalid */
480 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
481
482 bnc_nexthop_free(bnc);
483 bnc->nexthop = NULL;
484 }
485
486 evaluate_paths(bnc);
487 }
488
489 /*
490 * Cleanup nexthop registration and status information for BGP nexthops
491 * pertaining to this VRF. This is invoked upon VRF deletion.
492 */
493 void bgp_cleanup_nexthops(struct bgp *bgp)
494 {
495 afi_t afi;
496 struct bgp_node *rn;
497 struct bgp_nexthop_cache *bnc;
498
499 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
500 if (!bgp->nexthop_cache_table[afi])
501 continue;
502
503 for (rn = bgp_table_top(bgp->nexthop_cache_table[afi]); rn;
504 rn = bgp_route_next(rn)) {
505 bnc = bgp_node_get_bgp_nexthop_info(rn);
506 if (!bnc)
507 continue;
508
509 /* Clear relevant flags. */
510 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
511 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
512 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
513 }
514 }
515 }
516
517 /**
518 * make_prefix - make a prefix structure from the path (essentially
519 * path's node.
520 */
521 static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p)
522 {
523
524 int is_bgp_static = ((pi->type == ZEBRA_ROUTE_BGP)
525 && (pi->sub_type == BGP_ROUTE_STATIC))
526 ? 1
527 : 0;
528 struct bgp_node *net = pi->net;
529 struct prefix *p_orig = &net->p;
530
531 if (p_orig->family == AF_FLOWSPEC) {
532 if (!pi->peer)
533 return -1;
534 return bgp_flowspec_get_first_nh(pi->peer->bgp,
535 pi, p);
536 }
537 memset(p, 0, sizeof(struct prefix));
538 switch (afi) {
539 case AFI_IP:
540 p->family = AF_INET;
541 if (is_bgp_static) {
542 p->u.prefix4 = pi->net->p.u.prefix4;
543 p->prefixlen = pi->net->p.prefixlen;
544 } else {
545 p->u.prefix4 = pi->attr->nexthop;
546 p->prefixlen = IPV4_MAX_BITLEN;
547 }
548 break;
549 case AFI_IP6:
550 p->family = AF_INET6;
551
552 if (is_bgp_static) {
553 p->u.prefix6 = pi->net->p.u.prefix6;
554 p->prefixlen = pi->net->p.prefixlen;
555 } else {
556 p->u.prefix6 = pi->attr->mp_nexthop_global;
557 p->prefixlen = IPV6_MAX_BITLEN;
558 }
559 break;
560 default:
561 if (BGP_DEBUG(nht, NHT)) {
562 zlog_debug(
563 "%s: Attempting to make prefix with unknown AFI %d (not %d or %d)",
564 __FUNCTION__, afi, AFI_IP, AFI_IP6);
565 }
566 break;
567 }
568 return 0;
569 }
570
571 /**
572 * sendmsg_zebra_rnh -- Format and send a nexthop register/Unregister
573 * command to Zebra.
574 * ARGUMENTS:
575 * struct bgp_nexthop_cache *bnc -- the nexthop structure.
576 * int command -- command to send to zebra
577 * RETURNS:
578 * void.
579 */
580 static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command)
581 {
582 struct prefix *p;
583 bool exact_match = false;
584 int ret;
585
586 if (!zclient)
587 return;
588
589 /* Don't try to register if Zebra doesn't know of this instance. */
590 if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bnc->bgp)) {
591 if (BGP_DEBUG(zebra, ZEBRA))
592 zlog_debug("%s: No zebra instance to talk to, not installing NHT entry",
593 __PRETTY_FUNCTION__);
594 return;
595 }
596
597 if (!bgp_zebra_num_connects()) {
598 if (BGP_DEBUG(zebra, ZEBRA))
599 zlog_debug("%s: We have not connected yet, cannot send nexthops",
600 __PRETTY_FUNCTION__);
601 }
602 p = &(bnc->node->p);
603 if ((command == ZEBRA_NEXTHOP_REGISTER
604 || command == ZEBRA_IMPORT_ROUTE_REGISTER)
605 && (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)
606 || CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)))
607 exact_match = true;
608
609 if (BGP_DEBUG(zebra, ZEBRA)) {
610 char buf[PREFIX2STR_BUFFER];
611
612 prefix2str(p, buf, PREFIX2STR_BUFFER);
613 zlog_debug("%s: sending cmd %s for %s (vrf %s)",
614 __func__, zserv_command_string(command), buf,
615 bnc->bgp->name_pretty);
616 }
617
618 ret = zclient_send_rnh(zclient, command, p, exact_match,
619 bnc->bgp->vrf_id);
620 /* TBD: handle the failure */
621 if (ret < 0)
622 flog_warn(EC_BGP_ZEBRA_SEND,
623 "sendmsg_nexthop: zclient_send_message() failed");
624
625 if ((command == ZEBRA_NEXTHOP_REGISTER)
626 || (command == ZEBRA_IMPORT_ROUTE_REGISTER))
627 SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
628 else if ((command == ZEBRA_NEXTHOP_UNREGISTER)
629 || (command == ZEBRA_IMPORT_ROUTE_UNREGISTER))
630 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
631 return;
632 }
633
634 /**
635 * register_zebra_rnh - register a NH/route with Zebra for notification
636 * when the route or the route to the nexthop changes.
637 * ARGUMENTS:
638 * struct bgp_nexthop_cache *bnc
639 * RETURNS:
640 * void.
641 */
642 static void register_zebra_rnh(struct bgp_nexthop_cache *bnc,
643 int is_bgp_import_route)
644 {
645 /* Check if we have already registered */
646 if (bnc->flags & BGP_NEXTHOP_REGISTERED)
647 return;
648 if (is_bgp_import_route)
649 sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_REGISTER);
650 else
651 sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_REGISTER);
652 }
653
654 /**
655 * unregister_zebra_rnh -- Unregister the route/nexthop from Zebra.
656 * ARGUMENTS:
657 * struct bgp_nexthop_cache *bnc
658 * RETURNS:
659 * void.
660 */
661 static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc,
662 int is_bgp_import_route)
663 {
664 /* Check if we have already registered */
665 if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
666 return;
667
668 if (is_bgp_import_route)
669 sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_UNREGISTER);
670 else
671 sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_UNREGISTER);
672 }
673
674 /**
675 * evaluate_paths - Evaluate the paths/nets associated with a nexthop.
676 * ARGUMENTS:
677 * struct bgp_nexthop_cache *bnc -- the nexthop structure.
678 * RETURNS:
679 * void.
680 */
681 static void evaluate_paths(struct bgp_nexthop_cache *bnc)
682 {
683 struct bgp_node *rn;
684 struct bgp_path_info *path;
685 int afi;
686 struct peer *peer = (struct peer *)bnc->nht_info;
687 struct bgp_table *table;
688 safi_t safi;
689 struct bgp *bgp_path;
690
691 if (BGP_DEBUG(nht, NHT)) {
692 char buf[PREFIX2STR_BUFFER];
693 bnc_str(bnc, buf, PREFIX2STR_BUFFER);
694 zlog_debug(
695 "NH update for %s(%s) - flags 0x%x chgflags 0x%x - evaluate paths",
696 buf, bnc->bgp->name_pretty, bnc->flags,
697 bnc->change_flags);
698 }
699
700 LIST_FOREACH (path, &(bnc->paths), nh_thread) {
701 if (!(path->type == ZEBRA_ROUTE_BGP
702 && ((path->sub_type == BGP_ROUTE_NORMAL)
703 || (path->sub_type == BGP_ROUTE_STATIC)
704 || (path->sub_type == BGP_ROUTE_IMPORTED))))
705 continue;
706
707 rn = path->net;
708 assert(rn && bgp_node_table(rn));
709 afi = family2afi(rn->p.family);
710 table = bgp_node_table(rn);
711 safi = table->safi;
712
713 /*
714 * handle routes from other VRFs (they can have a
715 * nexthop in THIS VRF). bgp_path is the bgp instance
716 * that owns the route referencing this nexthop.
717 */
718 bgp_path = table->bgp;
719
720 /*
721 * Path becomes valid/invalid depending on whether the nexthop
722 * reachable/unreachable.
723 *
724 * In case of unicast routes that were imported from vpn
725 * and that have labels, they are valid only if there are
726 * nexthops with labels
727 */
728
729 int bnc_is_valid_nexthop = 0;
730
731 if (safi == SAFI_UNICAST &&
732 path->sub_type == BGP_ROUTE_IMPORTED &&
733 path->extra &&
734 path->extra->num_labels) {
735
736 bnc_is_valid_nexthop =
737 bgp_isvalid_labeled_nexthop(bnc) ? 1 : 0;
738 } else {
739 bnc_is_valid_nexthop =
740 bgp_isvalid_nexthop(bnc) ? 1 : 0;
741 }
742
743 if (BGP_DEBUG(nht, NHT)) {
744 char buf[PREFIX_STRLEN];
745
746 prefix2str(&rn->p, buf, PREFIX_STRLEN);
747 zlog_debug("%s: prefix %s (vrf %s) %svalid",
748 __func__, buf, bgp_path->name,
749 (bnc_is_valid_nexthop ? "" : "not "));
750 }
751
752 if ((CHECK_FLAG(path->flags, BGP_PATH_VALID) ? 1 : 0)
753 != bnc_is_valid_nexthop) {
754 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
755 bgp_aggregate_decrement(bgp_path, &rn->p,
756 path, afi, safi);
757 bgp_path_info_unset_flag(rn, path,
758 BGP_PATH_VALID);
759 } else {
760 bgp_path_info_set_flag(rn, path,
761 BGP_PATH_VALID);
762 bgp_aggregate_increment(bgp_path, &rn->p,
763 path, afi, safi);
764 }
765 }
766
767 /* Copy the metric to the path. Will be used for bestpath
768 * computation */
769 if (bgp_isvalid_nexthop(bnc) && bnc->metric)
770 (bgp_path_info_extra_get(path))->igpmetric =
771 bnc->metric;
772 else if (path->extra)
773 path->extra->igpmetric = 0;
774
775 if (CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED)
776 || CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED))
777 SET_FLAG(path->flags, BGP_PATH_IGP_CHANGED);
778
779 if (safi == SAFI_EVPN &&
780 bgp_evpn_is_prefix_nht_supported(&rn->p)) {
781 if (CHECK_FLAG(path->flags, BGP_PATH_VALID))
782 bgp_evpn_import_route(bgp_path, afi, safi,
783 &rn->p, path);
784 else
785 bgp_evpn_unimport_route(bgp_path, afi, safi,
786 &rn->p, path);
787 }
788
789 bgp_process(bgp_path, rn, afi, safi);
790 }
791
792 if (peer) {
793 int valid_nexthops = bgp_isvalid_nexthop(bnc);
794
795 if (valid_nexthops)
796 peer->last_reset = PEER_DOWN_WAITING_OPEN;
797 else
798 peer->last_reset = PEER_DOWN_WAITING_NHT;
799
800 if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED)) {
801 if (BGP_DEBUG(nht, NHT))
802 zlog_debug("%s: Updating peer (%s(%s)) status with NHT",
803 __FUNCTION__, peer->host,
804 peer->bgp->name_pretty);
805 bgp_fsm_event_update(peer, valid_nexthops);
806 SET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
807 }
808 }
809
810 RESET_FLAG(bnc->change_flags);
811 }
812
813 /**
814 * path_nh_map - make or break path-to-nexthop association.
815 * ARGUMENTS:
816 * path - pointer to the path structure
817 * bnc - pointer to the nexthop structure
818 * make - if set, make the association. if unset, just break the existing
819 * association.
820 */
821 void path_nh_map(struct bgp_path_info *path, struct bgp_nexthop_cache *bnc,
822 bool make)
823 {
824 if (path->nexthop) {
825 LIST_REMOVE(path, nh_thread);
826 path->nexthop->path_count--;
827 path->nexthop = NULL;
828 }
829 if (make) {
830 LIST_INSERT_HEAD(&(bnc->paths), path, nh_thread);
831 path->nexthop = bnc;
832 path->nexthop->path_count++;
833 }
834 }
835
836 /*
837 * This function is called to register nexthops to zebra
838 * as that we may have tried to install the nexthops
839 * before we actually have a zebra connection
840 */
841 void bgp_nht_register_nexthops(struct bgp *bgp)
842 {
843 struct bgp_node *rn;
844 struct bgp_nexthop_cache *bnc;
845 afi_t afi;
846
847 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
848 if (!bgp->nexthop_cache_table[afi])
849 continue;
850
851 for (rn = bgp_table_top(bgp->nexthop_cache_table[afi]); rn;
852 rn = bgp_route_next(rn)) {
853 bnc = bgp_node_get_bgp_nexthop_info(rn);
854
855 if (!bnc)
856 continue;
857
858 register_zebra_rnh(bnc, 0);
859 }
860 }
861 }
862
863 void bgp_nht_register_enhe_capability_interfaces(struct peer *peer)
864 {
865 struct bgp *bgp;
866 struct bgp_node *rn;
867 struct bgp_nexthop_cache *bnc;
868 struct nexthop *nhop;
869 struct interface *ifp;
870 struct prefix p;
871
872 if (peer->ifp)
873 return;
874
875 bgp = peer->bgp;
876
877 if (!bgp->nexthop_cache_table[AFI_IP6])
878 return;
879
880 if (!sockunion2hostprefix(&peer->su, &p)) {
881 if (BGP_DEBUG(nht, NHT))
882 zlog_debug("%s: Unable to convert prefix to sockunion",
883 __PRETTY_FUNCTION__);
884 return;
885 }
886
887 if (p.family != AF_INET6)
888 return;
889 rn = bgp_node_lookup(bgp->nexthop_cache_table[AFI_IP6], &p);
890 if (!rn)
891 return;
892
893 bnc = bgp_node_get_bgp_nexthop_info(rn);
894 if (!bnc)
895 return;
896
897 if (peer != bnc->nht_info)
898 return;
899
900 for (nhop = bnc->nexthop; nhop; nhop = nhop->next) {
901 ifp = if_lookup_by_index(nhop->ifindex,
902 nhop->vrf_id);
903 zclient_send_interface_radv_req(zclient,
904 nhop->vrf_id,
905 ifp, true,
906 BGP_UNNUM_DEFAULT_RA_INTERVAL);
907 }
908 }