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