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