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