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