]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_rnh.c
Merge remote-tracking branch 'origin/cmaster' into cmaster-next
[mirror_frr.git] / zebra / zebra_rnh.c
1 /* Zebra next hop tracking code
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 "prefix.h"
25 #include "table.h"
26 #include "memory.h"
27 #include "str.h"
28 #include "command.h"
29 #include "if.h"
30 #include "log.h"
31 #include "sockunion.h"
32 #include "linklist.h"
33 #include "thread.h"
34 #include "workqueue.h"
35 #include "prefix.h"
36 #include "routemap.h"
37 #include "stream.h"
38 #include "nexthop.h"
39 #include "vrf.h"
40
41 #include "zebra/rib.h"
42 #include "zebra/rt.h"
43 #include "zebra/zserv.h"
44 #include "zebra/zebra_ns.h"
45 #include "zebra/zebra_vrf.h"
46 #include "zebra/redistribute.h"
47 #include "zebra/debug.h"
48 #include "zebra/zebra_rnh.h"
49 #include "zebra/zebra_routemap.h"
50 #include "zebra/interface.h"
51 #include "zebra/zebra_memory.h"
52
53 static void free_state(vrf_id_t vrf_id, struct rib *rib, struct route_node *rn);
54 static void copy_state(struct rnh *rnh, struct rib *rib,
55 struct route_node *rn);
56 #define lookup_rnh_table(v, f) \
57 ({ \
58 struct zebra_vrf *zvrf; \
59 struct route_table *t = NULL; \
60 zvrf = zebra_vrf_lookup(v); \
61 if (zvrf) \
62 t = zvrf->rnh_table[family2afi(f)]; \
63 t; \
64 })
65
66 static int compare_state(struct rib *r1, struct rib *r2);
67 static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
68 vrf_id_t vrf_id);
69 static void print_rnh(struct route_node *rn, struct vty *vty);
70
71 int zebra_rnh_ip_default_route = 0;
72 int zebra_rnh_ipv6_default_route = 0;
73
74 static inline struct route_table *get_rnh_table(vrf_id_t vrfid, int family,
75 rnh_type_t type)
76 {
77 struct zebra_vrf *zvrf;
78 struct route_table *t = NULL;
79
80 zvrf = zebra_vrf_lookup(vrfid);
81 if (zvrf)
82 switch (type)
83 {
84 case RNH_NEXTHOP_TYPE:
85 t = zvrf->rnh_table[family2afi(family)];
86 break;
87 case RNH_IMPORT_CHECK_TYPE:
88 t = zvrf->import_check_table[family2afi(family)];
89 break;
90 }
91
92 return t;
93 }
94
95 char *rnh_str (struct rnh *rnh, char *buf, int size)
96 {
97 prefix2str(&(rnh->node->p), buf, size);
98 return buf;
99 }
100
101 struct rnh *
102 zebra_add_rnh (struct prefix *p, vrf_id_t vrfid, rnh_type_t type)
103 {
104 struct route_table *table;
105 struct route_node *rn;
106 struct rnh *rnh = NULL;
107 char buf[PREFIX2STR_BUFFER];
108
109 if (IS_ZEBRA_DEBUG_NHT)
110 {
111 prefix2str(p, buf, sizeof (buf));
112 zlog_debug("%u: Add RNH %s type %d", vrfid, buf, type);
113 }
114 table = get_rnh_table(vrfid, PREFIX_FAMILY(p), type);
115 if (!table)
116 {
117 prefix2str(p, buf, sizeof (buf));
118 zlog_warn("%u: Add RNH %s type %d - table not found",
119 vrfid, buf, type);
120 return NULL;
121 }
122
123 /* Make it sure prefixlen is applied to the prefix. */
124 apply_mask (p);
125
126 /* Lookup (or add) route node.*/
127 rn = route_node_get (table, p);
128
129 if (!rn->info)
130 {
131 rnh = XCALLOC(MTYPE_RNH, sizeof(struct rnh));
132 rnh->client_list = list_new();
133 rnh->vrf_id = vrfid;
134 rnh->zebra_static_route_list = list_new();
135 route_lock_node (rn);
136 rn->info = rnh;
137 rnh->node = rn;
138 }
139
140 route_unlock_node (rn);
141 return (rn->info);
142 }
143
144 struct rnh *
145 zebra_lookup_rnh (struct prefix *p, vrf_id_t vrfid, rnh_type_t type)
146 {
147 struct route_table *table;
148 struct route_node *rn;
149
150 table = get_rnh_table(vrfid, PREFIX_FAMILY(p), type);
151 if (!table)
152 return NULL;
153
154 /* Make it sure prefixlen is applied to the prefix. */
155 apply_mask (p);
156
157 /* Lookup route node.*/
158 rn = route_node_lookup (table, p);
159 if (!rn)
160 return NULL;
161
162 route_unlock_node (rn);
163 return (rn->info);
164 }
165
166 void
167 zebra_delete_rnh (struct rnh *rnh, rnh_type_t type)
168 {
169 struct route_node *rn;
170
171 if (!rnh || (rnh->flags & ZEBRA_NHT_DELETED) || !(rn = rnh->node))
172 return;
173
174 if (IS_ZEBRA_DEBUG_NHT)
175 {
176 char buf[PREFIX2STR_BUFFER];
177 zlog_debug("%u: Del RNH %s type %d",
178 rnh->vrf_id, rnh_str(rnh, buf, sizeof (buf)), type);
179 }
180
181 rnh->flags |= ZEBRA_NHT_DELETED;
182 list_free(rnh->client_list);
183 list_free(rnh->zebra_static_route_list);
184 free_state(rnh->vrf_id, rnh->state, rn);
185 XFREE(MTYPE_RNH, rn->info);
186 rn->info = NULL;
187 route_unlock_node (rn);
188 return;
189 }
190
191 void
192 zebra_add_rnh_client (struct rnh *rnh, struct zserv *client, rnh_type_t type,
193 vrf_id_t vrf_id)
194 {
195 if (IS_ZEBRA_DEBUG_NHT)
196 {
197 char buf[PREFIX2STR_BUFFER];
198 zlog_debug("%u: Client %s registers for RNH %s type %d",
199 vrf_id, zebra_route_string(client->proto),
200 rnh_str(rnh, buf, sizeof (buf)), type);
201 }
202 if (!listnode_lookup(rnh->client_list, client))
203 {
204 listnode_add(rnh->client_list, client);
205 send_client(rnh, client, type, vrf_id); // Pending: check if its needed
206 }
207 }
208
209 void
210 zebra_remove_rnh_client (struct rnh *rnh, struct zserv *client, rnh_type_t type)
211 {
212 if (IS_ZEBRA_DEBUG_NHT)
213 {
214 char buf[PREFIX2STR_BUFFER];
215 zlog_debug("Client %s unregisters for RNH %s type %d",
216 zebra_route_string(client->proto),
217 rnh_str(rnh, buf, sizeof (buf)), type);
218 }
219 listnode_delete(rnh->client_list, client);
220 if (list_isempty(rnh->client_list) &&
221 list_isempty(rnh->zebra_static_route_list))
222 zebra_delete_rnh(rnh, type);
223 }
224
225 void
226 zebra_register_rnh_static_nh(vrf_id_t vrf_id, struct prefix *nh,
227 struct route_node *static_rn)
228 {
229 struct rnh *rnh;
230
231 rnh = zebra_add_rnh(nh, vrf_id, RNH_NEXTHOP_TYPE);
232 if (rnh && !listnode_lookup(rnh->zebra_static_route_list, static_rn))
233 {
234 listnode_add(rnh->zebra_static_route_list, static_rn);
235 }
236 }
237
238 void
239 zebra_deregister_rnh_static_nh(vrf_id_t vrf_id, struct prefix *nh,
240 struct route_node *static_rn)
241 {
242 struct rnh *rnh;
243
244 rnh = zebra_lookup_rnh(nh, vrf_id, RNH_NEXTHOP_TYPE);
245 if (!rnh || (rnh->flags & ZEBRA_NHT_DELETED))
246 return;
247
248 listnode_delete(rnh->zebra_static_route_list, static_rn);
249
250 if (list_isempty(rnh->client_list) &&
251 list_isempty(rnh->zebra_static_route_list))
252 zebra_delete_rnh(rnh, RNH_NEXTHOP_TYPE);
253 }
254
255 void
256 zebra_deregister_rnh_static_nexthops (vrf_id_t vrf_id, struct nexthop *nexthop,
257 struct route_node *rn)
258 {
259 struct nexthop *nh;
260 struct prefix nh_p;
261
262 for (nh = nexthop; nh ; nh = nh->next)
263 {
264 switch (nh->type)
265 {
266 case NEXTHOP_TYPE_IPV4:
267 case NEXTHOP_TYPE_IPV4_IFINDEX:
268 nh_p.family = AF_INET;
269 nh_p.prefixlen = IPV4_MAX_BITLEN;
270 nh_p.u.prefix4 = nh->gate.ipv4;
271 break;
272 case NEXTHOP_TYPE_IPV6:
273 case NEXTHOP_TYPE_IPV6_IFINDEX:
274 nh_p.family = AF_INET6;
275 nh_p.prefixlen = IPV6_MAX_BITLEN;
276 nh_p.u.prefix6 = nh->gate.ipv6;
277 break;
278 /*
279 * Not sure what really to do here, we are not
280 * supposed to have either of these for NHT
281 * and the code has no way to know what prefix
282 * to use. So I'm going to just continue
283 * for the moment, which is preferable to
284 * what is currently happening which is a
285 * CRASH and BURN.
286 * Some simple testing shows that we
287 * are not leaving slag around for these
288 * skipped static routes. Since
289 * they don't appear to be installed
290 */
291 case NEXTHOP_TYPE_IFINDEX:
292 case NEXTHOP_TYPE_BLACKHOLE:
293 continue;
294 break;
295 }
296 zebra_deregister_rnh_static_nh(vrf_id, &nh_p, rn);
297 }
298 }
299
300 /* Apply the NHT route-map for a client to the route (and nexthops)
301 * resolving a NH.
302 */
303 static int
304 zebra_rnh_apply_nht_rmap(int family, struct route_node *prn,
305 struct rib *rib, int proto)
306 {
307 int at_least_one = 0;
308 int rmap_family; /* Route map has diff AF family enum */
309 struct nexthop *nexthop;
310 int ret;
311
312 rmap_family = (family == AF_INET) ? AFI_IP : AFI_IP6;
313
314 if (prn && rib)
315 {
316 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
317 {
318 ret = zebra_nht_route_map_check(rmap_family, proto, &prn->p, rib,
319 nexthop);
320 if (ret != RMAP_DENYMATCH)
321 {
322 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
323 at_least_one++; /* at least one valid NH */
324 }
325 else
326 {
327 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
328 }
329 }
330 }
331 return (at_least_one);
332 }
333
334 /*
335 * Determine appropriate route (RIB entry) resolving a tracked entry
336 * (nexthop or BGP route for import).
337 */
338 static struct rib *
339 zebra_rnh_resolve_entry (vrf_id_t vrfid, int family, rnh_type_t type,
340 struct route_node *nrn, struct rnh *rnh,
341 struct route_node **prn)
342 {
343 struct route_table *route_table;
344 struct route_node *rn;
345 struct rib *rib;
346
347 *prn = NULL;
348
349 route_table = zebra_vrf_table(family2afi(family), SAFI_UNICAST, vrfid);
350 if (!route_table) // unexpected
351 return NULL;
352
353 rn = route_node_match(route_table, &nrn->p);
354 if (!rn)
355 return NULL;
356
357 /* When resolving nexthops, do not resolve via the default route unless
358 * 'ip nht resolve-via-default' is configured.
359 */
360 if ((type == RNH_NEXTHOP_TYPE) &&
361 (is_default_prefix (&rn->p) &&
362 !nh_resolve_via_default(rn->p.family)))
363 rib = NULL;
364 else if ((type == RNH_IMPORT_CHECK_TYPE) &&
365 CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH) &&
366 !prefix_same(&nrn->p, &rn->p))
367 rib = NULL;
368 else
369 {
370 /* Identify appropriate route entry. */
371 RNODE_FOREACH_RIB(rn, rib)
372 {
373 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
374 continue;
375 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
376 {
377 if (CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
378 {
379 if (rib->type == ZEBRA_ROUTE_CONNECT)
380 break;
381 }
382 else if ((type == RNH_IMPORT_CHECK_TYPE) &&
383 (rib->type == ZEBRA_ROUTE_BGP))
384 continue;
385 else
386 break;
387 }
388 }
389 }
390
391 /* Need to unlock route node */
392 route_unlock_node(rn);
393 if (rib)
394 *prn = rn;
395 return rib;
396 }
397
398 /*
399 * See if a tracked route entry for import (by BGP) has undergone any
400 * change, and if so, notify the client.
401 */
402 static void
403 zebra_rnh_eval_import_check_entry (vrf_id_t vrfid, int family, int force,
404 struct route_node *nrn, struct rnh *rnh,
405 struct rib *rib)
406 {
407 int state_changed = 0;
408 struct zserv *client;
409 char bufn[INET6_ADDRSTRLEN];
410 struct listnode *node;
411 struct nexthop *nexthop, *tnexthop;
412 int recursing;
413
414 if (rib && (rnh->state == NULL))
415 {
416 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
417 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
418 {
419 state_changed = 1;
420 break;
421 }
422 }
423 else if (!rib && (rnh->state != NULL))
424 state_changed = 1;
425
426 if (compare_state(rib, rnh->state))
427 copy_state(rnh, rib, nrn);
428
429 if (state_changed || force)
430 {
431 if (IS_ZEBRA_DEBUG_NHT)
432 {
433 prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN);
434 zlog_debug("%u:%s: Route import check %s %s\n",
435 vrfid, bufn, rnh->state ? "passed" : "failed",
436 state_changed ? "(state changed)" : "");
437 }
438 /* state changed, notify clients */
439 for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client))
440 {
441 send_client(rnh, client, RNH_IMPORT_CHECK_TYPE, vrfid);
442 }
443 }
444 }
445
446 /*
447 * Notify clients registered for this nexthop about a change.
448 */
449 static void
450 zebra_rnh_notify_protocol_clients (vrf_id_t vrfid, int family,
451 struct route_node *nrn, struct rnh *rnh,
452 struct route_node *prn, struct rib *rib)
453 {
454 struct listnode *node;
455 struct zserv *client;
456 char bufn[INET6_ADDRSTRLEN];
457 char bufp[INET6_ADDRSTRLEN];
458 int num_resolving_nh;
459
460 if (IS_ZEBRA_DEBUG_NHT)
461 {
462 prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN);
463 if (prn && rib)
464 {
465 prefix2str(&prn->p, bufp, INET6_ADDRSTRLEN);
466 zlog_debug("%u:%s: NH resolved over route %s", vrfid, bufn, bufp);
467 }
468 else
469 zlog_debug("%u:%s: NH has become unresolved", vrfid, bufn);
470 }
471
472 for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client))
473 {
474 if (prn && rib)
475 {
476 /* Apply route-map for this client to route resolving this
477 * nexthop to see if it is filtered or not.
478 */
479 num_resolving_nh = zebra_rnh_apply_nht_rmap(family, prn, rib,
480 client->proto);
481 if (num_resolving_nh)
482 rnh->filtered[client->proto] = 0;
483 else
484 rnh->filtered[client->proto] = 1;
485
486 if (IS_ZEBRA_DEBUG_NHT)
487 zlog_debug("%u:%s: Notifying client %s about NH %s",
488 vrfid, bufn, zebra_route_string(client->proto),
489 num_resolving_nh ? "" : "(filtered by route-map)");
490 }
491 else
492 {
493 rnh->filtered[client->proto] = 0;
494 if (IS_ZEBRA_DEBUG_NHT)
495 zlog_debug("%u:%s: Notifying client %s about NH (unreachable)",
496 vrfid, bufn, zebra_route_string(client->proto));
497 }
498
499 send_client(rnh, client, RNH_NEXTHOP_TYPE, vrfid);
500 }
501 }
502
503 static void
504 zebra_rnh_process_static_routes (vrf_id_t vrfid, int family,
505 struct route_node *nrn, struct rnh *rnh,
506 struct route_node *prn, struct rib *rib)
507 {
508 struct listnode *node;
509 int num_resolving_nh = 0;
510 struct route_node *static_rn;
511 struct rib *srib;
512 struct nexthop *nexthop;
513 char bufn[INET6_ADDRSTRLEN];
514 char bufp[INET6_ADDRSTRLEN];
515 char bufs[INET6_ADDRSTRLEN];
516
517 if (IS_ZEBRA_DEBUG_NHT)
518 {
519 prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN);
520 if (prn)
521 prefix2str(&prn->p, bufp, INET6_ADDRSTRLEN);
522 }
523
524 if (prn && rib)
525 {
526 /* Apply route-map for "static" to route resolving this
527 * nexthop to see if it is filtered or not.
528 */
529 num_resolving_nh = zebra_rnh_apply_nht_rmap(family, prn, rib,
530 ZEBRA_ROUTE_STATIC);
531 if (num_resolving_nh)
532 rnh->filtered[ZEBRA_ROUTE_STATIC] = 0;
533 else
534 rnh->filtered[ZEBRA_ROUTE_STATIC] = 1;
535 }
536 else
537 rnh->filtered[ZEBRA_ROUTE_STATIC] = 0;
538
539 /* Evaluate each static route associated with this nexthop. */
540 for (ALL_LIST_ELEMENTS_RO(rnh->zebra_static_route_list, node,
541 static_rn))
542 {
543 RNODE_FOREACH_RIB(static_rn, srib)
544 {
545 if (srib->type == ZEBRA_ROUTE_STATIC)
546 continue;
547
548 /* Set the filter flag for the correct nexthop - static route may
549 * be having multiple. We care here only about registered nexthops.
550 */
551 for (nexthop = srib->nexthop; nexthop; nexthop = nexthop->next)
552 {
553 switch (nexthop->type)
554 {
555 case NEXTHOP_TYPE_IPV4:
556 case NEXTHOP_TYPE_IPV4_IFINDEX:
557 if (nexthop->gate.ipv4.s_addr == nrn->p.u.prefix4.s_addr)
558 {
559 if (num_resolving_nh)
560 UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED);
561 else
562 SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED);
563 }
564 break;
565 case NEXTHOP_TYPE_IPV6:
566 case NEXTHOP_TYPE_IPV6_IFINDEX:
567
568 if (memcmp(&nexthop->gate.ipv6,&nrn->p.u.prefix6, 16) == 0)
569 {
570 if (num_resolving_nh)
571 UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED);
572 else
573 SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED);
574 }
575 break;
576 default:
577 break;
578 }
579 }
580
581 if (IS_ZEBRA_DEBUG_NHT)
582 {
583 prefix2str(&static_rn->p, bufs, INET6_ADDRSTRLEN);
584 if (prn && rib)
585 zlog_debug("%u:%s: NH change %s, scheduling static route %s",
586 vrfid, bufn, num_resolving_nh ?
587 "" : "(filtered by route-map)", bufs);
588 else
589 zlog_debug("%u:%s: NH unreachable, scheduling static route %s",
590 vrfid, bufn, bufs);
591 }
592
593 SET_FLAG(srib->status, RIB_ENTRY_CHANGED);
594 SET_FLAG(srib->status, RIB_ENTRY_NEXTHOPS_CHANGED);
595 }
596
597 rib_queue_add(static_rn);
598 }
599 }
600
601 /*
602 * See if a tracked nexthop entry has undergone any change, and if so,
603 * take appropriate action; this involves notifying any clients and/or
604 * scheduling dependent static routes for processing.
605 */
606 static void
607 zebra_rnh_eval_nexthop_entry (vrf_id_t vrfid, int family, int force,
608 struct route_node *nrn, struct rnh *rnh,
609 struct route_node *prn, struct rib *rib)
610 {
611 int state_changed = 0;
612
613 /* If we're resolving over a different route, resolution has changed or
614 * the resolving route has some change (e.g., metric), there is a state
615 * change.
616 */
617 if (!prefix_same(&rnh->resolved_route, &prn->p))
618 {
619 if (rib)
620 UNSET_FLAG(rib->status, RIB_ENTRY_NEXTHOPS_CHANGED);
621
622 if (prn)
623 prefix_copy(&rnh->resolved_route, &prn->p);
624 else
625 memset(&rnh->resolved_route, 0, sizeof(struct prefix));
626
627 copy_state(rnh, rib, nrn);
628 state_changed = 1;
629 }
630 else if (compare_state(rib, rnh->state))
631 {
632 if (rib)
633 UNSET_FLAG(rib->status, RIB_ENTRY_NEXTHOPS_CHANGED);
634
635 copy_state(rnh, rib, nrn);
636 state_changed = 1;
637 }
638
639 if (state_changed || force)
640 {
641 /* NOTE: Use the "copy" of resolving route stored in 'rnh' i.e.,
642 * rnh->state.
643 */
644 /* Notify registered protocol clients. */
645 zebra_rnh_notify_protocol_clients (vrfid, family, nrn, rnh,
646 prn, rnh->state);
647
648 /* Process static routes attached to this nexthop */
649 zebra_rnh_process_static_routes (vrfid, family, nrn, rnh,
650 prn, rnh->state);
651 }
652 }
653
654 /* Evaluate one tracked entry */
655 static void
656 zebra_rnh_evaluate_entry (vrf_id_t vrfid, int family, int force, rnh_type_t type,
657 struct route_node *nrn)
658 {
659 struct rnh *rnh;
660 struct rib *rib;
661 struct route_node *prn;
662 char bufn[INET6_ADDRSTRLEN];
663
664 if (IS_ZEBRA_DEBUG_NHT)
665 {
666 prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN);
667 zlog_debug("%u:%s: Evaluate RNH, type %d %s",
668 vrfid, bufn, type, force ? "(force)" : "");
669 }
670
671 rnh = nrn->info;
672
673 /* Identify route entry (RIB) resolving this tracked entry. */
674 rib = zebra_rnh_resolve_entry (vrfid, family, type, nrn, rnh, &prn);
675
676 /* If the entry cannot be resolved and that is also the existing state,
677 * there is nothing further to do.
678 */
679 if (!rib && rnh->state == NULL && !force)
680 return;
681
682 /* Process based on type of entry. */
683 if (type == RNH_IMPORT_CHECK_TYPE)
684 zebra_rnh_eval_import_check_entry (vrfid, family, force,
685 nrn, rnh, rib);
686 else
687 zebra_rnh_eval_nexthop_entry (vrfid, family, force,
688 nrn, rnh, prn, rib);
689 }
690
691
692 /* Evaluate all tracked entries (nexthops or routes for import into BGP)
693 * of a particular VRF and address-family or a specific prefix.
694 */
695 void
696 zebra_evaluate_rnh (vrf_id_t vrfid, int family, int force, rnh_type_t type,
697 struct prefix *p)
698 {
699 struct route_table *rnh_table;
700 struct route_node *nrn;
701
702 rnh_table = get_rnh_table(vrfid, family, type);
703 if (!rnh_table) // unexpected
704 return;
705
706 if (p)
707 {
708 /* Evaluating a specific entry, make sure it exists. */
709 nrn = route_node_lookup (rnh_table, p);
710 if (nrn && nrn->info)
711 zebra_rnh_evaluate_entry (vrfid, family, force, type, nrn);
712 if (nrn)
713 route_unlock_node (nrn);
714 }
715 else
716 {
717 /* Evaluate entire table. */
718 nrn = route_top (rnh_table);
719 while (nrn)
720 {
721 if (nrn->info)
722 zebra_rnh_evaluate_entry (vrfid, family, force, type, nrn);
723 nrn = route_next(nrn); /* this will also unlock nrn */
724 }
725 }
726 }
727
728 void
729 zebra_print_rnh_table (vrf_id_t vrfid, int af, struct vty *vty, rnh_type_t type)
730 {
731 struct route_table *table;
732 struct route_node *rn;
733
734 table = get_rnh_table(vrfid, af, type);
735 if (!table)
736 {
737 zlog_debug("print_rnhs: rnh table not found\n");
738 return;
739 }
740
741 for (rn = route_top(table); rn; rn = route_next(rn))
742 if (rn->info)
743 print_rnh(rn, vty);
744 }
745
746 int
747 zebra_cleanup_rnh_client (vrf_id_t vrf_id, int family, struct zserv *client,
748 rnh_type_t type)
749 {
750 struct route_table *ntable;
751 struct route_node *nrn;
752 struct rnh *rnh;
753
754 if (IS_ZEBRA_DEBUG_NHT)
755 zlog_debug("%u: Client %s RNH cleanup for family %d type %d",
756 vrf_id, zebra_route_string(client->proto), family, type);
757
758 ntable = get_rnh_table(vrf_id, family, type);
759 if (!ntable)
760 {
761 zlog_debug("cleanup_rnh_client: rnh table not found\n");
762 return -1;
763 }
764
765 for (nrn = route_top (ntable); nrn; nrn = route_next (nrn))
766 {
767 if (!nrn->info)
768 continue;
769
770 rnh = nrn->info;
771 zebra_remove_rnh_client(rnh, client, type);
772 }
773 return 1;
774 }
775
776 /**
777 * free_state - free up the rib structure associated with the rnh.
778 */
779 static void
780 free_state (vrf_id_t vrf_id, struct rib *rib, struct route_node *rn)
781 {
782
783 if (!rib)
784 return;
785
786 /* free RIB and nexthops */
787 zebra_deregister_rnh_static_nexthops (vrf_id, rib->nexthop, rn);
788 nexthops_free(rib->nexthop);
789 XFREE (MTYPE_RIB, rib);
790 }
791
792 static void
793 copy_state (struct rnh *rnh, struct rib *rib, struct route_node *rn)
794 {
795 struct rib *state;
796 struct nexthop *nh;
797
798 if (rnh->state)
799 {
800 free_state(rnh->vrf_id, rnh->state, rn);
801 rnh->state = NULL;
802 }
803
804 if (!rib)
805 return;
806
807 state = XCALLOC (MTYPE_RIB, sizeof (struct rib));
808 state->type = rib->type;
809 state->metric = rib->metric;
810
811 for (nh = rib->nexthop; nh; nh = nh->next)
812 rib_copy_nexthops(state, nh);
813 rnh->state = state;
814 }
815
816 static int
817 compare_state (struct rib *r1, struct rib *r2)
818 {
819
820 if (!r1 && !r2)
821 return 0;
822
823 if ((!r1 && r2) || (r1 && !r2))
824 return 1;
825
826 if (r1->metric != r2->metric)
827 return 1;
828
829 if (r1->nexthop_num != r2->nexthop_num)
830 return 1;
831
832 if (CHECK_FLAG(r1->status, RIB_ENTRY_NEXTHOPS_CHANGED))
833 return 1;
834
835 return 0;
836 }
837
838 static int
839 send_client (struct rnh *rnh, struct zserv *client, rnh_type_t type, vrf_id_t vrf_id)
840 {
841 struct stream *s;
842 struct rib *rib;
843 unsigned long nump;
844 u_char num;
845 struct nexthop *nexthop;
846 struct route_node *rn;
847 int cmd = (type == RNH_IMPORT_CHECK_TYPE)
848 ? ZEBRA_IMPORT_CHECK_UPDATE : ZEBRA_NEXTHOP_UPDATE;
849
850 rn = rnh->node;
851 rib = rnh->state;
852
853 /* Get output stream. */
854 s = client->obuf;
855 stream_reset (s);
856
857 zserv_create_header (s, cmd, vrf_id);
858
859 stream_putw(s, rn->p.family);
860 switch (rn->p.family)
861 {
862 case AF_INET:
863 stream_putc(s, rn->p.prefixlen);
864 stream_put_in_addr(s, &rn->p.u.prefix4);
865 break;
866 case AF_INET6:
867 stream_putc(s, rn->p.prefixlen);
868 stream_put(s, &rn->p.u.prefix6, IPV6_MAX_BYTELEN);
869 break;
870 default:
871 zlog_err("%s: Unknown family (%d) notification attempted\n",
872 __FUNCTION__, rn->p.family);
873 break;
874 }
875 if (rib)
876 {
877 stream_putl (s, rib->metric);
878 num = 0;
879 nump = stream_get_endp(s);
880 stream_putc (s, 0);
881 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
882 if ((CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ||
883 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) &&
884 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
885 {
886 stream_putc (s, nexthop->type);
887 switch (nexthop->type)
888 {
889 case NEXTHOP_TYPE_IPV4:
890 stream_put_in_addr (s, &nexthop->gate.ipv4);
891 break;
892 case NEXTHOP_TYPE_IFINDEX:
893 stream_putl (s, nexthop->ifindex);
894 break;
895 case NEXTHOP_TYPE_IPV4_IFINDEX:
896 stream_put_in_addr (s, &nexthop->gate.ipv4);
897 stream_putl (s, nexthop->ifindex);
898 break;
899 #ifdef HAVE_IPV6
900 case NEXTHOP_TYPE_IPV6:
901 stream_put (s, &nexthop->gate.ipv6, 16);
902 break;
903 case NEXTHOP_TYPE_IPV6_IFINDEX:
904 stream_put (s, &nexthop->gate.ipv6, 16);
905 stream_putl (s, nexthop->ifindex);
906 break;
907 #endif /* HAVE_IPV6 */
908 default:
909 /* do nothing */
910 break;
911 }
912 num++;
913 }
914 stream_putc_at (s, nump, num);
915 }
916 else
917 {
918 stream_putl (s, 0);
919 stream_putc (s, 0);
920 }
921 stream_putw_at (s, 0, stream_get_endp (s));
922
923 client->nh_last_upd_time = quagga_monotime();
924 client->last_write_cmd = cmd;
925 return zebra_server_send_message(client);
926 }
927
928 static void
929 print_nh (struct nexthop *nexthop, struct vty *vty)
930 {
931 char buf[BUFSIZ];
932 struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT);
933
934 switch (nexthop->type)
935 {
936 case NEXTHOP_TYPE_IPV4:
937 case NEXTHOP_TYPE_IPV4_IFINDEX:
938 vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4));
939 if (nexthop->ifindex)
940 vty_out (vty, ", %s", ifindex2ifname_per_ns (zns, nexthop->ifindex));
941 break;
942 case NEXTHOP_TYPE_IPV6:
943 case NEXTHOP_TYPE_IPV6_IFINDEX:
944 vty_out (vty, " %s",
945 inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ));
946 if (nexthop->ifindex)
947 vty_out (vty, ", via %s", ifindex2ifname_per_ns (zns, nexthop->ifindex));
948 break;
949 case NEXTHOP_TYPE_IFINDEX:
950 vty_out (vty, " is directly connected, %s",
951 ifindex2ifname_per_ns (zns, nexthop->ifindex));
952 break;
953 case NEXTHOP_TYPE_BLACKHOLE:
954 vty_out (vty, " is directly connected, Null0");
955 break;
956 default:
957 break;
958 }
959 vty_out(vty, "%s", VTY_NEWLINE);
960 }
961
962 static void
963 print_rnh (struct route_node *rn, struct vty *vty)
964 {
965 struct rnh *rnh;
966 struct nexthop *nexthop;
967 struct listnode *node;
968 struct zserv *client;
969 char buf[BUFSIZ];
970
971 rnh = rn->info;
972 vty_out(vty, "%s%s%s", inet_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ),
973 CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED) ? "(Connected)" : "",
974 VTY_NEWLINE);
975 if (rnh->state)
976 {
977 vty_out(vty, " resolved via %s%s",
978 zebra_route_string(rnh->state->type), VTY_NEWLINE);
979 for (nexthop = rnh->state->nexthop; nexthop; nexthop = nexthop->next)
980 print_nh(nexthop, vty);
981 }
982 else
983 vty_out(vty, " unresolved%s%s",
984 CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED) ? "(Connected)" : "",
985 VTY_NEWLINE);
986
987 vty_out(vty, " Client list:");
988 for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client))
989 vty_out(vty, " %s(fd %d)%s", zebra_route_string(client->proto),
990 client->sock, rnh->filtered[client->proto] ? "(filtered)" : "");
991 if (!list_isempty(rnh->zebra_static_route_list))
992 vty_out(vty, " zebra%s", rnh->filtered[ZEBRA_ROUTE_STATIC] ? "(filtered)" : "");
993 vty_out(vty, "%s", VTY_NEWLINE);
994 }