]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_nht.c
bgpd: Enhance path selection logs
[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 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
24#include "command.h"
25#include "thread.h"
26#include "prefix.h"
27#include "zclient.h"
28#include "stream.h"
29#include "network.h"
30#include "log.h"
31#include "memory.h"
32#include "nexthop.h"
7076bb2f 33#include "vrf.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"
41#include "bgpd/bgp_nht.h"
ffd0c037 42#include "bgpd/bgp_fsm.h"
fb018d25
DS
43
44extern struct zclient *zclient;
fb018d25 45
078430f6
DS
46static void register_zebra_rnh(struct bgp_nexthop_cache *bnc,
47 int is_bgp_static_route);
48static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc,
49 int is_bgp_static_route);
fb018d25
DS
50static void evaluate_paths(struct bgp_nexthop_cache *bnc);
51static int make_prefix(int afi, struct bgp_info *ri, struct prefix *p);
52static void path_nh_map(struct bgp_info *path, struct bgp_nexthop_cache *bnc,
53 int keep);
54
55int
fc9a856f 56bgp_find_nexthop (struct bgp_info *path, int connected)
fb018d25
DS
57{
58 struct bgp_nexthop_cache *bnc = path->nexthop;
59
60 if (!bnc)
61 return 0;
62
fc9a856f
DS
63 if (connected && !(CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)))
64 return 0;
fb018d25
DS
65
66 return (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID));
67}
68
69void
70bgp_unlink_nexthop (struct bgp_info *path)
71{
72 struct bgp_nexthop_cache *bnc = path->nexthop;
73
74 if (!bnc)
75 return;
76
77 path_nh_map(path, NULL, 0);
78
fc9a856f 79 if (LIST_EMPTY(&(bnc->paths)) && !bnc->nht_info)
fb018d25
DS
80 {
81 if (BGP_DEBUG(nht, NHT))
82 {
4690c7d7 83 char buf[PREFIX2STR_BUFFER];
fb018d25 84 zlog_debug("bgp_unlink_nexthop: freeing bnc %s",
4690c7d7 85 bnc_str(bnc, buf, PREFIX2STR_BUFFER));
fb018d25 86 }
078430f6 87 unregister_zebra_rnh(bnc, CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE));
fb018d25
DS
88 bnc->node->info = NULL;
89 bgp_unlock_node(bnc->node);
90 bnc_free(bnc);
91 }
92}
93
94int
75aead62
DS
95bgp_find_or_add_nexthop (struct bgp *bgp, afi_t afi, struct bgp_info *ri,
96 struct peer *peer, int connected)
fb018d25
DS
97{
98 struct bgp_node *rn;
99 struct bgp_nexthop_cache *bnc;
100 struct prefix p;
078430f6 101 int is_bgp_static_route = 0;
fb018d25 102
fc9a856f
DS
103 if (ri)
104 {
8a92a8a0
DS
105 is_bgp_static_route = ((ri->type == ZEBRA_ROUTE_BGP) &&
106 (ri->sub_type == BGP_ROUTE_STATIC)) ? 1 : 0;
107
108 /* Since Extended Next-hop Encoding (RFC5549) support, we want to derive
109 address-family from the next-hop. */
110 if (!is_bgp_static_route)
111 afi = BGP_ATTR_NEXTHOP_AFI_IP6(ri->attr) ? AFI_IP6 : AFI_IP;
112
65740e1b 113 /* This will return TRUE if the global IPv6 NH is a link local addr */
fc9a856f
DS
114 if (make_prefix(afi, ri, &p) < 0)
115 return 1;
116 }
117 else if (peer)
118 {
119 if (afi == AFI_IP)
120 {
121 p.family = AF_INET;
122 p.prefixlen = IPV4_MAX_BITLEN;
123 p.u.prefix4 = peer->su.sin.sin_addr;
124 }
125 else if (afi == AFI_IP6)
126 {
127 p.family = AF_INET6;
128 p.prefixlen = IPV6_MAX_BITLEN;
129 p.u.prefix6 = peer->su.sin6.sin6_addr;
65740e1b
DS
130
131 /* Don't register link local NH */
132 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
133 return 1;
134 }
135 else
136 {
137 if (BGP_DEBUG(nht, NHT))
138 {
139 zlog_debug("%s: Attempting to register with unknown AFI %d (not %d or %d)",
140 __FUNCTION__, afi, AFI_IP, AFI_IP6);
141 }
142 return 0;
fc9a856f
DS
143 }
144 }
65740e1b
DS
145 else
146 return 0;
fc9a856f 147
078430f6 148 if (is_bgp_static_route)
6aeb9e78 149 rn = bgp_node_get (bgp->import_check_table[afi], &p);
078430f6 150 else
6aeb9e78 151 rn = bgp_node_get (bgp->nexthop_cache_table[afi], &p);
fb018d25
DS
152
153 if (!rn->info)
154 {
155 bnc = bnc_new();
156 rn->info = bnc;
157 bnc->node = rn;
75aead62 158 bnc->bgp = bgp;
fb018d25 159 bgp_lock_node(rn);
9a233a02
DS
160 if (BGP_DEBUG(nht, NHT))
161 {
4690c7d7 162 char buf[PREFIX2STR_BUFFER];
9a233a02 163
078430f6 164 zlog_debug("Allocated bnc %s peer %p",
4690c7d7 165 bnc_str(bnc, buf, PREFIX2STR_BUFFER), peer);
9a233a02 166 }
fb018d25 167 }
fc9a856f 168
fb018d25
DS
169 bnc = rn->info;
170 bgp_unlock_node (rn);
fb018d25 171
078430f6
DS
172 if (is_bgp_static_route)
173 {
174 SET_FLAG(bnc->flags, BGP_STATIC_ROUTE);
175
176 /* If we're toggling the type, re-register */
5623e905 177 if ((bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)) &&
078430f6
DS
178 !CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH))
179 {
180 SET_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH);
181 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
182 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
183 }
5623e905 184 else if ((!bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)) &&
078430f6
DS
185 CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH))
186 {
187 UNSET_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH);
188 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
189 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
190 }
191 }
25c38b24 192 /* When nexthop is already known, but now requires 'connected' resolution,
193 * re-register it. The reverse scenario where the nexthop currently requires
194 * 'connected' resolution does not need a re-register (i.e., we treat
195 * 'connected-required' as an override) except in the scenario where this
196 * is actually a case of tracking a peer for connectivity (e.g., after
197 * disable connected-check).
198 * NOTE: We don't track the number of paths separately for 'connected-
199 * required' vs 'connected-not-required' as this change is not a common
200 * scenario.
201 */
078430f6
DS
202 else if (connected && ! CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
203 {
204 SET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED);
205 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
206 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
207 }
25c38b24 208 else if (peer && !connected && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
078430f6
DS
209 {
210 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED);
211 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
212 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
213 }
214
fc9a856f 215 if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
078430f6 216 register_zebra_rnh(bnc, is_bgp_static_route);
fb018d25 217
22a29185 218 if (ri && ri->nexthop != bnc)
fc9a856f 219 {
22a29185
DS
220 /* Unlink from existing nexthop cache, if any. This will also free
221 * the nexthop cache entry, if appropriate.
222 */
223 bgp_unlink_nexthop (ri);
224
225 /* Link to new nexthop cache. */
fc9a856f 226 path_nh_map(ri, bnc, 1);
fb018d25 227
fc9a856f
DS
228 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric)
229 (bgp_info_extra_get(ri))->igpmetric = bnc->metric;
230 else if (ri->extra)
231 ri->extra->igpmetric = 0;
232 }
233 else if (peer)
234 bnc->nht_info = (void *)peer;
fb018d25
DS
235
236 return (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID));
237}
238
9a233a02
DS
239void
240bgp_delete_connected_nexthop (afi_t afi, struct peer *peer)
241{
242 struct bgp_node *rn;
243 struct bgp_nexthop_cache *bnc;
244 struct prefix p;
245
65740e1b
DS
246 if (!peer)
247 return;
248
9a233a02
DS
249 if (afi == AFI_IP)
250 {
251 p.family = AF_INET;
252 p.prefixlen = IPV4_MAX_BITLEN;
253 p.u.prefix4 = peer->su.sin.sin_addr;
254 }
255 else if (afi == AFI_IP6)
256 {
257 p.family = AF_INET6;
258 p.prefixlen = IPV6_MAX_BITLEN;
259 p.u.prefix6 = peer->su.sin6.sin6_addr;
65740e1b
DS
260
261 /* We don't register link local address for NHT */
262 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
263 return;
9a233a02 264 }
65740e1b
DS
265 else
266 return;
9a233a02 267
6aeb9e78 268 rn = bgp_node_lookup(peer->bgp->nexthop_cache_table[family2afi(p.family)], &p);
9a233a02
DS
269 if (!rn || !rn->info)
270 {
271 if (BGP_DEBUG(nht, NHT))
272 zlog_debug("Cannot find connected NHT node for peer %s", peer->host);
273 if (rn)
274 bgp_unlock_node (rn);
275 return;
276 }
277
278 bnc = rn->info;
279 bgp_unlock_node(rn);
280
281 if (bnc->nht_info != peer)
282 {
283 if (BGP_DEBUG(nht, NHT))
284 zlog_debug("Connected NHT %p node for peer %s points to %p",
285 bnc, peer->host, bnc->nht_info);
286 return;
287 }
288
289 bnc->nht_info = NULL;
290
291 if (LIST_EMPTY(&(bnc->paths)))
292 {
293 if (BGP_DEBUG(nht, NHT))
294 zlog_debug("Freeing connected NHT node %p for peer %s",
295 bnc, peer->host);
078430f6 296 unregister_zebra_rnh(bnc, 0);
9a233a02
DS
297 bnc->node->info = NULL;
298 bgp_unlock_node(bnc->node);
299 bnc_free(bnc);
300 }
301}
302
fb018d25 303void
7076bb2f 304bgp_parse_nexthop_update (int command, vrf_id_t vrf_id)
fb018d25
DS
305{
306 struct stream *s;
ffd0c037 307 struct bgp_node *rn = NULL;
fb018d25
DS
308 struct bgp_nexthop_cache *bnc;
309 struct nexthop *nexthop;
310 struct nexthop *oldnh;
311 struct nexthop *nhlist_head = NULL;
312 struct nexthop *nhlist_tail = NULL;
313 uint32_t metric;
314 u_char nexthop_num;
315 struct prefix p;
316 int i;
6aeb9e78
DS
317 struct bgp *bgp;
318
319 bgp = bgp_lookup_by_vrf_id (vrf_id);
320 if (!bgp)
321 {
322 zlog_err("parse nexthop update: instance not found for vrf_id %d", vrf_id);
323 return;
324 }
fb018d25
DS
325
326 s = zclient->ibuf;
327
328 memset(&p, 0, sizeof(struct prefix));
329 p.family = stream_getw(s);
330 p.prefixlen = stream_getc(s);
331 switch (p.family)
332 {
333 case AF_INET:
334 p.u.prefix4.s_addr = stream_get_ipv4 (s);
335 break;
336 case AF_INET6:
337 stream_get(&p.u.prefix6, s, 16);
338 break;
339 default:
340 break;
341 }
342
078430f6 343 if (command == ZEBRA_NEXTHOP_UPDATE)
6aeb9e78 344 rn = bgp_node_lookup(bgp->nexthop_cache_table[family2afi(p.family)], &p);
078430f6 345 else if (command == ZEBRA_IMPORT_CHECK_UPDATE)
6aeb9e78 346 rn = bgp_node_lookup(bgp->import_check_table[family2afi(p.family)], &p);
078430f6 347
fb018d25
DS
348 if (!rn || !rn->info)
349 {
350 if (BGP_DEBUG(nht, NHT))
351 {
4690c7d7
DS
352 char buf[PREFIX2STR_BUFFER];
353 prefix2str(&p, buf, sizeof(buf));
fb018d25
DS
354 zlog_debug("parse nexthop update(%s): rn not found", buf);
355 }
7898cb4f
DS
356 if (rn)
357 bgp_unlock_node (rn);
fb018d25
DS
358 return;
359 }
360
361 bnc = rn->info;
7898cb4f 362 bgp_unlock_node (rn);
fb018d25
DS
363 bnc->last_update = bgp_clock();
364 bnc->change_flags = 0;
365 metric = stream_getl (s);
366 nexthop_num = stream_getc (s);
367
368 /* debug print the input */
369 if (BGP_DEBUG(nht, NHT))
370 {
4690c7d7
DS
371 char buf[PREFIX2STR_BUFFER];
372 prefix2str(&p, buf, sizeof (buf));
fb018d25
DS
373 zlog_debug("parse nexthop update(%s): metric=%d, #nexthop=%d", buf,
374 metric, nexthop_num);
375 }
376
377 if (metric != bnc->metric)
378 bnc->change_flags |= BGP_NEXTHOP_METRIC_CHANGED;
379
380 if(nexthop_num != bnc->nexthop_num)
381 bnc->change_flags |= BGP_NEXTHOP_CHANGED;
382
383 if (nexthop_num)
384 {
9ff31ad5
DS
385 /* notify bgp fsm if nbr ip goes from invalid->valid */
386 if (!bnc->nexthop_num)
387 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
388
fb018d25
DS
389 bnc->flags |= BGP_NEXTHOP_VALID;
390 bnc->metric = metric;
391 bnc->nexthop_num = nexthop_num;
392
393 for (i = 0; i < nexthop_num; i++)
394 {
395 nexthop = nexthop_new();
396 nexthop->type = stream_getc (s);
397 switch (nexthop->type)
398 {
399 case ZEBRA_NEXTHOP_IPV4:
400 nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
401 break;
402 case ZEBRA_NEXTHOP_IFINDEX:
fb018d25
DS
403 nexthop->ifindex = stream_getl (s);
404 break;
405 case ZEBRA_NEXTHOP_IPV4_IFINDEX:
fb018d25
DS
406 nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
407 nexthop->ifindex = stream_getl (s);
408 break;
409#ifdef HAVE_IPV6
410 case ZEBRA_NEXTHOP_IPV6:
411 stream_get (&nexthop->gate.ipv6, s, 16);
412 break;
413 case ZEBRA_NEXTHOP_IPV6_IFINDEX:
fb018d25
DS
414 stream_get (&nexthop->gate.ipv6, s, 16);
415 nexthop->ifindex = stream_getl (s);
416 break;
417#endif
418 default:
419 /* do nothing */
420 break;
421 }
422
423 if (nhlist_tail)
424 {
425 nhlist_tail->next = nexthop;
426 nhlist_tail = nexthop;
427 }
428 else
429 {
430 nhlist_tail = nexthop;
431 nhlist_head = nexthop;
432 }
433
434 /* No need to evaluate the nexthop if we have already determined
435 * that there has been a change.
436 */
437 if (bnc->change_flags & BGP_NEXTHOP_CHANGED)
438 continue;
439
440 for (oldnh = bnc->nexthop; oldnh; oldnh = oldnh->next)
441 if (nexthop_same_no_recurse(oldnh, nexthop))
442 break;
443
444 if (!oldnh)
9ff31ad5 445 bnc->change_flags |= BGP_NEXTHOP_CHANGED;
fb018d25
DS
446 }
447 bnc_nexthop_free(bnc);
448 bnc->nexthop = nhlist_head;
449 }
450 else
451 {
452 bnc->flags &= ~BGP_NEXTHOP_VALID;
9ff31ad5
DS
453 bnc->nexthop_num = nexthop_num;
454
455 /* notify bgp fsm if nbr ip goes from valid->invalid */
fc9a856f 456 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
9ff31ad5 457
fb018d25
DS
458 bnc_nexthop_free(bnc);
459 bnc->nexthop = NULL;
460 }
461
462 evaluate_paths(bnc);
463}
464
465/**
466 * make_prefix - make a prefix structure from the path (essentially
467 * path's node.
468 */
469static int
470make_prefix (int afi, struct bgp_info *ri, struct prefix *p)
471{
078430f6
DS
472
473 int is_bgp_static = ((ri->type == ZEBRA_ROUTE_BGP) &&
474 (ri->sub_type == BGP_ROUTE_STATIC)) ? 1 : 0;
475
fb018d25
DS
476 memset (p, 0, sizeof (struct prefix));
477 switch (afi)
478 {
479 case AFI_IP:
480 p->family = AF_INET;
078430f6
DS
481 if (is_bgp_static)
482 {
483 p->u.prefix4 = ri->net->p.u.prefix4;
484 p->prefixlen = ri->net->p.prefixlen;
485 }
486 else
487 {
488 p->u.prefix4 = ri->attr->nexthop;
489 p->prefixlen = IPV4_MAX_BITLEN;
490 }
fb018d25
DS
491 break;
492#ifdef HAVE_IPV6
493 case AFI_IP6:
65740e1b 494 /* We don't register link local NH */
801a9bcc 495 if (ri->attr->extra->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL
fb018d25
DS
496 || IN6_IS_ADDR_LINKLOCAL (&ri->attr->extra->mp_nexthop_global))
497 return -1;
498
499 p->family = AF_INET6;
078430f6
DS
500
501 if (is_bgp_static)
502 {
503 p->u.prefix6 = ri->net->p.u.prefix6;
504 p->prefixlen = ri->net->p.prefixlen;
505 }
506 else
507 {
508 p->u.prefix6 = ri->attr->extra->mp_nexthop_global;
509 p->prefixlen = IPV6_MAX_BITLEN;
510 }
fb018d25
DS
511 break;
512#endif
513 default:
65740e1b
DS
514 if (BGP_DEBUG(nht, NHT))
515 {
516 zlog_debug("%s: Attempting to make prefix with unknown AFI %d (not %d or %d)",
517 __FUNCTION__, afi, AFI_IP, AFI_IP6);
518 }
fb018d25
DS
519 break;
520 }
521 return 0;
522}
523
524/**
078430f6 525 * sendmsg_zebra_rnh -- Format and send a nexthop register/Unregister
fb018d25
DS
526 * command to Zebra.
527 * ARGUMENTS:
528 * struct bgp_nexthop_cache *bnc -- the nexthop structure.
078430f6 529 * int command -- command to send to zebra
fb018d25
DS
530 * RETURNS:
531 * void.
532 */
533static void
078430f6 534sendmsg_zebra_rnh (struct bgp_nexthop_cache *bnc, int command)
fb018d25
DS
535{
536 struct stream *s;
537 struct prefix *p;
538 int ret;
539
540 /* Check socket. */
541 if (!zclient || zclient->sock < 0)
ad4cbda1 542 return;
543
544 /* Don't try to register if Zebra doesn't know of this instance. */
545 if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bnc->bgp))
546 return;
fb018d25
DS
547
548 p = &(bnc->node->p);
549 s = zclient->obuf;
550 stream_reset (s);
6aeb9e78 551 zclient_create_header (s, command, bnc->bgp->vrf_id);
078430f6
DS
552 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED) ||
553 CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH))
fc9a856f
DS
554 stream_putc(s, 1);
555 else
556 stream_putc(s, 0);
557
fb018d25
DS
558 stream_putw(s, PREFIX_FAMILY(p));
559 stream_putc(s, p->prefixlen);
560 switch (PREFIX_FAMILY(p))
561 {
562 case AF_INET:
563 stream_put_in_addr (s, &p->u.prefix4);
564 break;
565#ifdef HAVE_IPV6
566 case AF_INET6:
567 stream_put(s, &(p->u.prefix6), 16);
568 break;
569#endif
570 default:
571 break;
572 }
573 stream_putw_at (s, 0, stream_get_endp (s));
574
575 ret = zclient_send_message(zclient);
576 /* TBD: handle the failure */
577 if (ret < 0)
578 zlog_warn("sendmsg_nexthop: zclient_send_message() failed");
fc9a856f 579
078430f6
DS
580 if ((command == ZEBRA_NEXTHOP_REGISTER) ||
581 (command == ZEBRA_IMPORT_ROUTE_REGISTER))
fc9a856f 582 SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
078430f6
DS
583 else if ((command == ZEBRA_NEXTHOP_UNREGISTER) ||
584 (command == ZEBRA_IMPORT_ROUTE_UNREGISTER))
fc9a856f 585 UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
fb018d25
DS
586 return;
587}
588
589/**
078430f6
DS
590 * register_zebra_rnh - register a NH/route with Zebra for notification
591 * when the route or the route to the nexthop changes.
fb018d25 592 * ARGUMENTS:
078430f6 593 * struct bgp_nexthop_cache *bnc
fb018d25
DS
594 * RETURNS:
595 * void.
596 */
597static void
078430f6 598register_zebra_rnh (struct bgp_nexthop_cache *bnc, int is_bgp_import_route)
fb018d25
DS
599{
600 /* Check if we have already registered */
601 if (bnc->flags & BGP_NEXTHOP_REGISTERED)
602 return;
078430f6
DS
603 if (is_bgp_import_route)
604 sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_REGISTER);
605 else
606 sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_REGISTER);
fb018d25
DS
607}
608
609/**
078430f6 610 * unregister_zebra_rnh -- Unregister the route/nexthop from Zebra.
fb018d25 611 * ARGUMENTS:
078430f6 612 * struct bgp_nexthop_cache *bnc
fb018d25
DS
613 * RETURNS:
614 * void.
615 */
616static void
078430f6 617unregister_zebra_rnh (struct bgp_nexthop_cache *bnc, int is_bgp_import_route)
fb018d25
DS
618{
619 /* Check if we have already registered */
620 if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
621 return;
622
078430f6
DS
623 if (is_bgp_import_route)
624 sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_UNREGISTER);
625 else
626 sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_UNREGISTER);
fb018d25
DS
627}
628
629/**
630 * evaluate_paths - Evaluate the paths/nets associated with a nexthop.
631 * ARGUMENTS:
632 * struct bgp_nexthop_cache *bnc -- the nexthop structure.
633 * RETURNS:
634 * void.
635 */
636static void
637evaluate_paths (struct bgp_nexthop_cache *bnc)
638{
639 struct bgp_node *rn;
640 struct bgp_info *path;
75aead62 641 struct bgp *bgp = bnc->bgp;
fb018d25 642 int afi;
fc9a856f 643 struct peer *peer = (struct peer *)bnc->nht_info;
fb018d25
DS
644
645 LIST_FOREACH(path, &(bnc->paths), nh_thread)
646 {
647 if (!(path->type == ZEBRA_ROUTE_BGP &&
ffd0c037
DS
648 ((path->sub_type == BGP_ROUTE_NORMAL) ||
649 (path->sub_type == BGP_ROUTE_STATIC))))
fb018d25
DS
650 continue;
651
652 rn = path->net;
653 afi = family2afi(rn->p.family);
654
655 /* Path becomes valid/invalid depending on whether the nexthop
656 * reachable/unreachable.
657 */
658 if ((CHECK_FLAG(path->flags, BGP_INFO_VALID) ? 1 : 0) !=
659 (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) ? 1 : 0))
660 {
661 if (CHECK_FLAG (path->flags, BGP_INFO_VALID))
662 {
663 bgp_aggregate_decrement (bgp, &rn->p, path,
664 afi, SAFI_UNICAST);
665 bgp_info_unset_flag (rn, path, BGP_INFO_VALID);
666 }
667 else
668 {
669 bgp_info_set_flag (rn, path, BGP_INFO_VALID);
670 bgp_aggregate_increment (bgp, &rn->p, path,
671 afi, SAFI_UNICAST);
672 }
673 }
674
675 /* Copy the metric to the path. Will be used for bestpath computation */
676 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric)
677 (bgp_info_extra_get(path))->igpmetric = bnc->metric;
678 else if (path->extra)
679 path->extra->igpmetric = 0;
680
c52d6050 681 if (CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED) ||
682 CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED))
fb018d25
DS
683 SET_FLAG(path->flags, BGP_INFO_IGP_CHANGED);
684
685 bgp_process(bgp, rn, afi, SAFI_UNICAST);
686 }
fc9a856f
DS
687
688 if (peer && !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED))
689 {
690 if (BGP_DEBUG(nht, NHT))
691 zlog_debug("%s: Updating peer (%s) status with NHT", __FUNCTION__, peer->host);
692 bgp_fsm_nht_update(peer, CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID));
693 SET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
694 }
695
fb018d25
DS
696 RESET_FLAG(bnc->change_flags);
697}
698
699/**
700 * path_nh_map - make or break path-to-nexthop association.
701 * ARGUMENTS:
702 * path - pointer to the path structure
703 * bnc - pointer to the nexthop structure
704 * make - if set, make the association. if unset, just break the existing
705 * association.
706 */
707static void
708path_nh_map (struct bgp_info *path, struct bgp_nexthop_cache *bnc, int make)
709{
710 if (path->nexthop)
711 {
712 LIST_REMOVE(path, nh_thread);
713 path->nexthop->path_count--;
714 path->nexthop = NULL;
715 }
716 if (make)
717 {
718 LIST_INSERT_HEAD(&(bnc->paths), path, nh_thread);
719 path->nexthop = bnc;
720 path->nexthop->path_count++;
721 }
722}