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