]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_nht.c
Merge pull request #2992 from opensourcerouting/large_as_path_fix
[mirror_frr.git] / bgpd / bgp_nht.c
CommitLineData
fb018d25
DS
1/* BGP Nexthop tracking
2 * Copyright (C) 2013 Cumulus Networks, Inc.
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
896014f4
DL
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
fb018d25
DS
19 */
20
21#include <zebra.h>
22
23#include "command.h"
24#include "thread.h"
25#include "prefix.h"
26#include "zclient.h"
27#include "stream.h"
28#include "network.h"
29#include "log.h"
30#include "memory.h"
31#include "nexthop.h"
7076bb2f 32#include "vrf.h"
039f3a34 33#include "filter.h"
fb018d25
DS
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"
14454c9f 41#include "bgpd/bgp_errors.h"
fb018d25 42#include "bgpd/bgp_nht.h"
ffd0c037 43#include "bgpd/bgp_fsm.h"
afbb1c59 44#include "bgpd/bgp_zebra.h"
fb018d25
DS
45
46extern struct zclient *zclient;
fb018d25 47
078430f6 48static void register_zebra_rnh(struct bgp_nexthop_cache *bnc,
d62a17ae 49 int is_bgp_static_route);
078430f6
DS
50static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc,
51 int is_bgp_static_route);
fb018d25
DS
52static void evaluate_paths(struct bgp_nexthop_cache *bnc);
53static int make_prefix(int afi, struct bgp_info *ri, struct prefix *p);
54static void path_nh_map(struct bgp_info *path, struct bgp_nexthop_cache *bnc,
55 int keep);
56
d62a17ae 57static int bgp_isvalid_nexthop(struct bgp_nexthop_cache *bnc)
d4d9d757 58{
d62a17ae 59 return (bgp_zebra_num_connects() == 0
60 || (bnc && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)));
d4d9d757
LB
61}
62
960035b2
PZ
63static 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
d62a17ae 69int bgp_find_nexthop(struct bgp_info *path, int connected)
fb018d25 70{
d62a17ae 71 struct bgp_nexthop_cache *bnc = path->nexthop;
fb018d25 72
d62a17ae 73 if (!bnc)
74 return 0;
fb018d25 75
d62a17ae 76 /*
77 * We are cheating here. Views have no associated underlying
78 * ability to detect nexthops. So when we have a view
79 * just tell everyone the nexthop is valid
80 */
81 if (path->peer && path->peer->bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
82 return 1;
3f3971a9 83
d62a17ae 84 if (connected && !(CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)))
85 return 0;
fb018d25 86
d62a17ae 87 return (bgp_isvalid_nexthop(bnc));
fb018d25
DS
88}
89
d62a17ae 90static void bgp_unlink_nexthop_check(struct bgp_nexthop_cache *bnc)
fb018d25 91{
d5c4bac9 92 if (LIST_EMPTY(&(bnc->paths)) && !bnc->nht_info) {
d62a17ae 93 if (BGP_DEBUG(nht, NHT)) {
94 char buf[PREFIX2STR_BUFFER];
95 zlog_debug("bgp_unlink_nexthop: freeing bnc %s",
96 bnc_str(bnc, buf, PREFIX2STR_BUFFER));
97 }
98 unregister_zebra_rnh(bnc,
99 CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE));
14315f2d 100 bgp_nexthop_set_node_info(bnc->node, NULL);
d62a17ae 101 bgp_unlock_node(bnc->node);
102 bnc->node = NULL;
103 bnc_free(bnc);
fb018d25 104 }
fb018d25
DS
105}
106
d62a17ae 107void bgp_unlink_nexthop(struct bgp_info *path)
f9164b1d 108{
d62a17ae 109 struct bgp_nexthop_cache *bnc = path->nexthop;
110
111 if (!bnc)
112 return;
f9164b1d 113
d62a17ae 114 path_nh_map(path, NULL, 0);
f9164b1d 115
d62a17ae 116 bgp_unlink_nexthop_check(bnc);
f9164b1d
PJ
117}
118
d62a17ae 119void bgp_unlink_nexthop_by_peer(struct peer *peer)
f9164b1d 120{
d62a17ae 121 struct prefix p;
122 struct bgp_node *rn;
123 struct bgp_nexthop_cache *bnc;
124 afi_t afi = family2afi(peer->su.sa.sa_family);
125
126 if (!sockunion2hostprefix(&peer->su, &p))
127 return;
128
129 rn = bgp_node_get(peer->bgp->nexthop_cache_table[afi], &p);
130
14315f2d
DS
131 bnc = bgp_nexthop_get_node_info(rn);
132 if (!bnc)
d62a17ae 133 return;
134
d62a17ae 135 /* cleanup the peer reference */
136 bnc->nht_info = NULL;
137
138 bgp_unlink_nexthop_check(bnc);
f9164b1d
PJ
139}
140
960035b2
PZ
141/*
142 * A route and its nexthop might belong to different VRFs. Therefore,
143 * we need both the bgp_route and bgp_nexthop pointers.
144 */
145int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
146 afi_t afi, struct bgp_info *ri,
d62a17ae 147 struct peer *peer, int connected)
fb018d25 148{
d62a17ae 149 struct bgp_node *rn;
150 struct bgp_nexthop_cache *bnc;
151 struct prefix p;
152 int is_bgp_static_route = 0;
153
154 if (ri) {
155 is_bgp_static_route = ((ri->type == ZEBRA_ROUTE_BGP)
156 && (ri->sub_type == BGP_ROUTE_STATIC))
157 ? 1
158 : 0;
159
160 /* Since Extended Next-hop Encoding (RFC5549) support, we want
161 to derive
162 address-family from the next-hop. */
163 if (!is_bgp_static_route)
164 afi = BGP_ATTR_NEXTHOP_AFI_IP6(ri->attr) ? AFI_IP6
165 : AFI_IP;
166
167 /* This will return TRUE if the global IPv6 NH is a link local
168 * addr */
169 if (make_prefix(afi, ri, &p) < 0)
170 return 1;
171 } else if (peer) {
172 /* Don't register link local NH */
173 if (afi == AFI_IP6
174 && IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr))
175 return 1;
176
177 if (!sockunion2hostprefix(&peer->su, &p)) {
178 if (BGP_DEBUG(nht, NHT)) {
179 zlog_debug(
180 "%s: Attempting to register with unknown AFI %d (not %d or %d)",
181 __FUNCTION__, afi, AFI_IP, AFI_IP6);
182 }
183 return 0;
184 }
185 } else
186 return 0;
187
188 if (is_bgp_static_route)
960035b2 189 rn = bgp_node_get(bgp_nexthop->import_check_table[afi], &p);
d62a17ae 190 else
960035b2 191 rn = bgp_node_get(bgp_nexthop->nexthop_cache_table[afi], &p);
d62a17ae 192
14315f2d
DS
193 bnc = bgp_nexthop_get_node_info(rn);
194 if (!bnc) {
d62a17ae 195 bnc = bnc_new();
14315f2d 196 bgp_nexthop_set_node_info(rn, bnc);
d62a17ae 197 bnc->node = rn;
960035b2 198 bnc->bgp = bgp_nexthop;
d62a17ae 199 bgp_lock_node(rn);
200 if (BGP_DEBUG(nht, NHT)) {
201 char buf[PREFIX2STR_BUFFER];
202
203 zlog_debug("Allocated bnc %s peer %p",
204 bnc_str(bnc, buf, PREFIX2STR_BUFFER), peer);
205 }
fc9a856f 206 }
d62a17ae 207
d62a17ae 208 bgp_unlock_node(rn);
209 if (is_bgp_static_route) {
210 SET_FLAG(bnc->flags, BGP_STATIC_ROUTE);
211
212 /* If we're toggling the type, re-register */
960035b2 213 if ((bgp_flag_check(bgp_route, BGP_FLAG_IMPORT_CHECK))
d62a17ae 214 && !CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)) {
215 SET_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH);
216 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
217 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
960035b2 218 } else if ((!bgp_flag_check(bgp_route, BGP_FLAG_IMPORT_CHECK))
d62a17ae 219 && CHECK_FLAG(bnc->flags,
220 BGP_STATIC_ROUTE_EXACT_MATCH)) {
221 UNSET_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH);
222 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
223 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
224 }
078430f6 225 }
d62a17ae 226 /* When nexthop is already known, but now requires 'connected'
227 * resolution,
228 * re-register it. The reverse scenario where the nexthop currently
229 * requires
230 * 'connected' resolution does not need a re-register (i.e., we treat
231 * 'connected-required' as an override) except in the scenario where
232 * this
233 * is actually a case of tracking a peer for connectivity (e.g., after
234 * disable connected-check).
235 * NOTE: We don't track the number of paths separately for 'connected-
236 * required' vs 'connected-not-required' as this change is not a common
237 * scenario.
238 */
239 else if (connected && !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) {
240 SET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED);
241 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
242 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
243 } else if (peer && !connected
244 && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) {
245 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED);
246 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
247 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
078430f6 248 }
960035b2 249 if (bgp_route->inst_type == BGP_INSTANCE_TYPE_VIEW) {
d62a17ae 250 bnc->flags |= BGP_NEXTHOP_REGISTERED;
251 bnc->flags |= BGP_NEXTHOP_VALID;
252 } else if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
253 register_zebra_rnh(bnc, is_bgp_static_route);
254 if (ri && ri->nexthop != bnc) {
255 /* Unlink from existing nexthop cache, if any. This will also
256 * free
257 * the nexthop cache entry, if appropriate.
258 */
259 bgp_unlink_nexthop(ri);
260
261 path_nh_map(ri, bnc, 1); /* updates NHT ri list reference */
262
263 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric)
264 (bgp_info_extra_get(ri))->igpmetric = bnc->metric;
265 else if (ri->extra)
266 ri->extra->igpmetric = 0;
267 } else if (peer)
268 bnc->nht_info = (void *)peer; /* NHT peer reference */
269
270 /*
271 * We are cheating here. Views have no associated underlying
272 * ability to detect nexthops. So when we have a view
273 * just tell everyone the nexthop is valid
274 */
960035b2 275 if (bgp_route->inst_type == BGP_INSTANCE_TYPE_VIEW)
d62a17ae 276 return 1;
277 else
278 return (bgp_isvalid_nexthop(bnc));
fb018d25
DS
279}
280
d62a17ae 281void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer)
9a233a02 282{
d62a17ae 283 struct bgp_node *rn;
284 struct bgp_nexthop_cache *bnc;
285 struct prefix p;
286
287 if (!peer)
288 return;
289
290 /* We don't register link local address for NHT */
291 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr))
292 return;
293
294 if (!sockunion2hostprefix(&peer->su, &p))
295 return;
296
297 rn = bgp_node_lookup(
298 peer->bgp->nexthop_cache_table[family2afi(p.family)], &p);
14315f2d 299 if (!rn) {
d62a17ae 300 if (BGP_DEBUG(nht, NHT))
301 zlog_debug("Cannot find connected NHT node for peer %s",
302 peer->host);
d62a17ae 303 return;
304 }
305
14315f2d
DS
306 bnc = bgp_nexthop_get_node_info(rn);
307 if (!bnc) {
308 if (BGP_DEBUG(nht, NHT))
309 zlog_debug("Cannot find connected NHT node for peer %s on route_node as expected",
310 peer->host);
311 bgp_unlock_node(rn);
312 return;
313 }
d62a17ae 314 bgp_unlock_node(rn);
315
316 if (bnc->nht_info != peer) {
317 if (BGP_DEBUG(nht, NHT))
318 zlog_debug(
319 "Connected NHT %p node for peer %s points to %p",
320 bnc, peer->host, bnc->nht_info);
321 return;
322 }
323
324 bnc->nht_info = NULL;
325
326 if (LIST_EMPTY(&(bnc->paths))) {
327 if (BGP_DEBUG(nht, NHT))
328 zlog_debug("Freeing connected NHT node %p for peer %s",
329 bnc, peer->host);
330 unregister_zebra_rnh(bnc, 0);
14315f2d 331 bgp_nexthop_set_node_info(bnc->node, NULL);
d62a17ae 332 bgp_unlock_node(bnc->node);
333 bnc_free(bnc);
334 }
9a233a02
DS
335}
336
d62a17ae 337void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
fb018d25 338{
d62a17ae 339 struct bgp_node *rn = NULL;
340 struct bgp_nexthop_cache *bnc;
341 struct nexthop *nexthop;
342 struct nexthop *oldnh;
343 struct nexthop *nhlist_head = NULL;
344 struct nexthop *nhlist_tail = NULL;
d62a17ae 345 int i;
346 struct bgp *bgp;
4a749e2c 347 struct zapi_route nhr;
d62a17ae 348
349 bgp = bgp_lookup_by_vrf_id(vrf_id);
350 if (!bgp) {
af4c2728 351 flog_err(
e50f7cfd 352 EC_BGP_NH_UPD,
a8bf7d9c 353 "parse nexthop update: instance not found for vrf_id %u",
d62a17ae 354 vrf_id);
355 return;
fb018d25 356 }
d62a17ae 357
7d30a959
DS
358 if (!zapi_nexthop_update_decode(zclient->ibuf, &nhr)) {
359 if (BGP_DEBUG(nht, NHT))
360 zlog_debug("%s: Failure to decode nexthop update",
361 __PRETTY_FUNCTION__);
362 return;
363 }
d62a17ae 364
365 if (command == ZEBRA_NEXTHOP_UPDATE)
366 rn = bgp_node_lookup(
4a749e2c
DS
367 bgp->nexthop_cache_table[family2afi(nhr.prefix.family)],
368 &nhr.prefix);
d62a17ae 369 else if (command == ZEBRA_IMPORT_CHECK_UPDATE)
370 rn = bgp_node_lookup(
4a749e2c
DS
371 bgp->import_check_table[family2afi(nhr.prefix.family)],
372 &nhr.prefix);
d62a17ae 373
14315f2d 374 if (!rn) {
d62a17ae 375 if (BGP_DEBUG(nht, NHT)) {
376 char buf[PREFIX2STR_BUFFER];
4a749e2c 377 prefix2str(&nhr.prefix, buf, sizeof(buf));
d62a17ae 378 zlog_debug("parse nexthop update(%s): rn not found",
379 buf);
380 }
d62a17ae 381 return;
fb018d25 382 }
d62a17ae 383
14315f2d
DS
384 bnc = bgp_nexthop_get_node_info(rn);
385 if (!bnc) {
386 if (BGP_DEBUG(nht, NHT)) {
387 char buf[PREFIX2STR_BUFFER];
388
389 prefix2str(&nhr.prefix, buf, sizeof(buf));
390 zlog_debug("parse nexthop update(%s): bnc node info not found",
391 buf);
392 }
393 bgp_unlock_node(rn);
394 return;
395 }
396
d62a17ae 397 bgp_unlock_node(rn);
398 bnc->last_update = bgp_clock();
399 bnc->change_flags = 0;
d62a17ae 400
401 /* debug print the input */
402 if (BGP_DEBUG(nht, NHT)) {
403 char buf[PREFIX2STR_BUFFER];
4a749e2c 404 prefix2str(&nhr.prefix, buf, sizeof(buf));
d62a17ae 405 zlog_debug(
a8bf7d9c 406 "%u: Rcvd NH update %s - metric %d/%d #nhops %d/%d flags 0x%x",
4a749e2c 407 vrf_id, buf, nhr.metric, bnc->metric, nhr.nexthop_num,
d62a17ae 408 bnc->nexthop_num, bnc->flags);
409 }
410
4a749e2c 411 if (nhr.metric != bnc->metric)
d62a17ae 412 bnc->change_flags |= BGP_NEXTHOP_METRIC_CHANGED;
413
4a749e2c 414 if (nhr.nexthop_num != bnc->nexthop_num)
d62a17ae 415 bnc->change_flags |= BGP_NEXTHOP_CHANGED;
416
4a749e2c 417 if (nhr.nexthop_num) {
d62a17ae 418 /* notify bgp fsm if nbr ip goes from invalid->valid */
419 if (!bnc->nexthop_num)
420 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
421
422 bnc->flags |= BGP_NEXTHOP_VALID;
4a749e2c
DS
423 bnc->metric = nhr.metric;
424 bnc->nexthop_num = nhr.nexthop_num;
425
960035b2
PZ
426 bnc->flags &= ~BGP_NEXTHOP_LABELED_VALID; /* check below */
427
4a749e2c 428 for (i = 0; i < nhr.nexthop_num; i++) {
960035b2
PZ
429 int num_labels = 0;
430
4a749e2c 431 nexthop = nexthop_from_zapi_nexthop(&nhr.nexthops[i]);
d62a17ae 432
960035b2
PZ
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
d62a17ae 441 if (BGP_DEBUG(nht, NHT)) {
442 char buf[NEXTHOP_STRLEN];
443 zlog_debug(
960035b2
PZ
444 " nhop via %s (%d labels)",
445 nexthop2str(nexthop, buf, sizeof(buf)),
446 num_labels);
d62a17ae 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)
960035b2
PZ
465 if (nexthop_same_no_recurse(oldnh, nexthop) &&
466 nexthop_labels_match(oldnh, nexthop))
d62a17ae 467 break;
468
469 if (!oldnh)
470 bnc->change_flags |= BGP_NEXTHOP_CHANGED;
471 }
472 bnc_nexthop_free(bnc);
473 bnc->nexthop = nhlist_head;
474 } else {
475 bnc->flags &= ~BGP_NEXTHOP_VALID;
4a749e2c 476 bnc->nexthop_num = nhr.nexthop_num;
d62a17ae 477
478 /* notify bgp fsm if nbr ip goes from valid->invalid */
479 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
480
481 bnc_nexthop_free(bnc);
482 bnc->nexthop = NULL;
483 }
484
485 evaluate_paths(bnc);
fb018d25
DS
486}
487
ee7ca6c0 488/*
489 * Cleanup nexthop registration and status information for BGP nexthops
490 * pertaining to this VRF. This is invoked upon VRF deletion.
491 */
492void bgp_cleanup_nexthops(struct bgp *bgp)
493{
494 afi_t afi;
495 struct bgp_node *rn;
496 struct bgp_nexthop_cache *bnc;
497
498 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
499 if (!bgp->nexthop_cache_table[afi])
500 continue;
501
502 for (rn = bgp_table_top(bgp->nexthop_cache_table[afi]); rn;
503 rn = bgp_route_next(rn)) {
14315f2d 504 bnc = bgp_nexthop_get_node_info(rn);
57f7feb6 505 if (!bnc)
ee7ca6c0 506 continue;
507
508 /* Clear relevant flags. */
509 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
510 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
511 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
512 }
513 }
514}
515
fb018d25
DS
516/**
517 * make_prefix - make a prefix structure from the path (essentially
518 * path's node.
519 */
d62a17ae 520static int make_prefix(int afi, struct bgp_info *ri, struct prefix *p)
fb018d25 521{
078430f6 522
d62a17ae 523 int is_bgp_static = ((ri->type == ZEBRA_ROUTE_BGP)
524 && (ri->sub_type == BGP_ROUTE_STATIC))
525 ? 1
526 : 0;
527
528 memset(p, 0, sizeof(struct prefix));
529 switch (afi) {
530 case AFI_IP:
531 p->family = AF_INET;
532 if (is_bgp_static) {
533 p->u.prefix4 = ri->net->p.u.prefix4;
534 p->prefixlen = ri->net->p.prefixlen;
535 } else {
536 p->u.prefix4 = ri->attr->nexthop;
537 p->prefixlen = IPV4_MAX_BITLEN;
538 }
539 break;
540 case AFI_IP6:
541 /* We don't register link local NH */
542 if (ri->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL
543 || IN6_IS_ADDR_LINKLOCAL(&ri->attr->mp_nexthop_global))
544 return -1;
545
546 p->family = AF_INET6;
547
548 if (is_bgp_static) {
549 p->u.prefix6 = ri->net->p.u.prefix6;
550 p->prefixlen = ri->net->p.prefixlen;
551 } else {
552 p->u.prefix6 = ri->attr->mp_nexthop_global;
553 p->prefixlen = IPV6_MAX_BITLEN;
554 }
555 break;
556 default:
557 if (BGP_DEBUG(nht, NHT)) {
558 zlog_debug(
559 "%s: Attempting to make prefix with unknown AFI %d (not %d or %d)",
560 __FUNCTION__, afi, AFI_IP, AFI_IP6);
561 }
562 break;
65740e1b 563 }
d62a17ae 564 return 0;
fb018d25
DS
565}
566
567/**
078430f6 568 * sendmsg_zebra_rnh -- Format and send a nexthop register/Unregister
fb018d25
DS
569 * command to Zebra.
570 * ARGUMENTS:
571 * struct bgp_nexthop_cache *bnc -- the nexthop structure.
078430f6 572 * int command -- command to send to zebra
fb018d25
DS
573 * RETURNS:
574 * void.
575 */
d62a17ae 576static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command)
fb018d25 577{
d62a17ae 578 struct prefix *p;
3c192540 579 bool exact_match = false;
d62a17ae 580 int ret;
581
3c192540 582 if (!zclient)
d62a17ae 583 return;
584
585 /* Don't try to register if Zebra doesn't know of this instance. */
586 if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bnc->bgp))
587 return;
588
589 p = &(bnc->node->p);
996c9314
LB
590 if ((command == ZEBRA_NEXTHOP_REGISTER
591 || command == ZEBRA_IMPORT_ROUTE_REGISTER)
592 && (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)
593 || CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)))
3c192540 594 exact_match = true;
d62a17ae 595
960035b2
PZ
596 if (BGP_DEBUG(zebra, ZEBRA)) {
597 char buf[PREFIX2STR_BUFFER];
598
599 prefix2str(p, buf, PREFIX2STR_BUFFER);
600 zlog_debug("%s: sending cmd %s for %s (vrf %s)",
601 __func__, zserv_command_string(command), buf,
602 bnc->bgp->name);
603 }
604
996c9314
LB
605 ret = zclient_send_rnh(zclient, command, p, exact_match,
606 bnc->bgp->vrf_id);
d62a17ae 607 /* TBD: handle the failure */
608 if (ret < 0)
e50f7cfd 609 flog_warn(EC_BGP_ZEBRA_SEND,
f162a5b9 610 "sendmsg_nexthop: zclient_send_message() failed");
d62a17ae 611
612 if ((command == ZEBRA_NEXTHOP_REGISTER)
613 || (command == ZEBRA_IMPORT_ROUTE_REGISTER))
614 SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
615 else if ((command == ZEBRA_NEXTHOP_UNREGISTER)
616 || (command == ZEBRA_IMPORT_ROUTE_UNREGISTER))
617 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
618 return;
fb018d25
DS
619}
620
621/**
078430f6
DS
622 * register_zebra_rnh - register a NH/route with Zebra for notification
623 * when the route or the route to the nexthop changes.
fb018d25 624 * ARGUMENTS:
078430f6 625 * struct bgp_nexthop_cache *bnc
fb018d25
DS
626 * RETURNS:
627 * void.
628 */
d62a17ae 629static void register_zebra_rnh(struct bgp_nexthop_cache *bnc,
630 int is_bgp_import_route)
fb018d25 631{
d62a17ae 632 /* Check if we have already registered */
633 if (bnc->flags & BGP_NEXTHOP_REGISTERED)
634 return;
635 if (is_bgp_import_route)
636 sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_REGISTER);
637 else
638 sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_REGISTER);
fb018d25
DS
639}
640
641/**
078430f6 642 * unregister_zebra_rnh -- Unregister the route/nexthop from Zebra.
fb018d25 643 * ARGUMENTS:
078430f6 644 * struct bgp_nexthop_cache *bnc
fb018d25
DS
645 * RETURNS:
646 * void.
647 */
d62a17ae 648static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc,
649 int is_bgp_import_route)
fb018d25 650{
d62a17ae 651 /* Check if we have already registered */
652 if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
653 return;
654
655 if (is_bgp_import_route)
656 sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_UNREGISTER);
657 else
658 sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_UNREGISTER);
fb018d25
DS
659}
660
661/**
662 * evaluate_paths - Evaluate the paths/nets associated with a nexthop.
663 * ARGUMENTS:
664 * struct bgp_nexthop_cache *bnc -- the nexthop structure.
665 * RETURNS:
666 * void.
667 */
d62a17ae 668static void evaluate_paths(struct bgp_nexthop_cache *bnc)
fb018d25 669{
d62a17ae 670 struct bgp_node *rn;
671 struct bgp_info *path;
d62a17ae 672 int afi;
673 struct peer *peer = (struct peer *)bnc->nht_info;
674 struct bgp_table *table;
675 safi_t safi;
960035b2 676 struct bgp *bgp_path;
d62a17ae 677
678 if (BGP_DEBUG(nht, NHT)) {
679 char buf[PREFIX2STR_BUFFER];
680 bnc_str(bnc, buf, PREFIX2STR_BUFFER);
681 zlog_debug(
682 "NH update for %s - flags 0x%x chgflags 0x%x - evaluate paths",
683 buf, bnc->flags, bnc->change_flags);
fb018d25
DS
684 }
685
a2addae8 686 LIST_FOREACH (path, &(bnc->paths), nh_thread) {
d62a17ae 687 if (!(path->type == ZEBRA_ROUTE_BGP
688 && ((path->sub_type == BGP_ROUTE_NORMAL)
960035b2
PZ
689 || (path->sub_type == BGP_ROUTE_STATIC)
690 || (path->sub_type == BGP_ROUTE_IMPORTED))))
d62a17ae 691 continue;
692
693 rn = path->net;
694 assert(rn && bgp_node_table(rn));
695 afi = family2afi(rn->p.family);
696 table = bgp_node_table(rn);
697 safi = table->safi;
698
960035b2
PZ
699 /*
700 * handle routes from other VRFs (they can have a
701 * nexthop in THIS VRF). bgp_path is the bgp instance
702 * that owns the route referencing this nexthop.
703 */
704 bgp_path = table->bgp;
705
706 /*
707 * Path becomes valid/invalid depending on whether the nexthop
d62a17ae 708 * reachable/unreachable.
960035b2
PZ
709 *
710 * In case of unicast routes that were imported from vpn
711 * and that have labels, they are valid only if there are
712 * nexthops with labels
d62a17ae 713 */
960035b2
PZ
714
715 int bnc_is_valid_nexthop = 0;
716
717 if (safi == SAFI_UNICAST &&
718 path->sub_type == BGP_ROUTE_IMPORTED &&
719 path->extra &&
720 path->extra->num_labels) {
721
722 bnc_is_valid_nexthop =
723 bgp_isvalid_labeled_nexthop(bnc) ? 1 : 0;
724 } else {
725 bnc_is_valid_nexthop =
726 bgp_isvalid_nexthop(bnc) ? 1 : 0;
727 }
728
729 if (BGP_DEBUG(nht, NHT)) {
730 char buf[PREFIX_STRLEN];
731
732 prefix2str(&rn->p, buf, PREFIX_STRLEN);
733 zlog_debug("%s: prefix %s (vrf %s) %svalid",
734 __func__, buf, bgp_path->name,
735 (bnc_is_valid_nexthop ? "" : "not "));
736 }
737
d62a17ae 738 if ((CHECK_FLAG(path->flags, BGP_INFO_VALID) ? 1 : 0)
960035b2 739 != bnc_is_valid_nexthop) {
d62a17ae 740 if (CHECK_FLAG(path->flags, BGP_INFO_VALID)) {
960035b2
PZ
741 bgp_aggregate_decrement(bgp_path, &rn->p,
742 path, afi, safi);
d62a17ae 743 bgp_info_unset_flag(rn, path, BGP_INFO_VALID);
744 } else {
745 bgp_info_set_flag(rn, path, BGP_INFO_VALID);
960035b2
PZ
746 bgp_aggregate_increment(bgp_path, &rn->p,
747 path, afi, safi);
d62a17ae 748 }
749 }
750
751 /* Copy the metric to the path. Will be used for bestpath
752 * computation */
753 if (bgp_isvalid_nexthop(bnc) && bnc->metric)
754 (bgp_info_extra_get(path))->igpmetric = bnc->metric;
755 else if (path->extra)
756 path->extra->igpmetric = 0;
757
758 if (CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED)
759 || CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED))
760 SET_FLAG(path->flags, BGP_INFO_IGP_CHANGED);
761
960035b2 762 bgp_process(bgp_path, rn, afi, safi);
d62a17ae 763 }
fc9a856f 764
d62a17ae 765 if (peer && !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED)) {
766 if (BGP_DEBUG(nht, NHT))
767 zlog_debug("%s: Updating peer (%s) status with NHT",
768 __FUNCTION__, peer->host);
769 bgp_fsm_nht_update(peer, bgp_isvalid_nexthop(bnc));
770 SET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
771 }
fc9a856f 772
d62a17ae 773 RESET_FLAG(bnc->change_flags);
fb018d25
DS
774}
775
776/**
777 * path_nh_map - make or break path-to-nexthop association.
778 * ARGUMENTS:
779 * path - pointer to the path structure
780 * bnc - pointer to the nexthop structure
781 * make - if set, make the association. if unset, just break the existing
782 * association.
783 */
d62a17ae 784static void path_nh_map(struct bgp_info *path, struct bgp_nexthop_cache *bnc,
785 int make)
fb018d25 786{
d62a17ae 787 if (path->nexthop) {
788 LIST_REMOVE(path, nh_thread);
789 path->nexthop->path_count--;
790 path->nexthop = NULL;
791 }
792 if (make) {
793 LIST_INSERT_HEAD(&(bnc->paths), path, nh_thread);
794 path->nexthop = bnc;
795 path->nexthop->path_count++;
796 }
fb018d25 797}