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