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