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