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