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