]> git.proxmox.com Git - mirror_frr.git/blob - isisd/isis_redist.c
71540e9e0bd93ac66f139943c01d90798331fdd7
[mirror_frr.git] / isisd / isis_redist.c
1 /*
2 * IS-IS Rout(e)ing protocol - isis_redist.c
3 *
4 * Copyright (C) 2013-2015 Christian Franke <chris@opensourcerouting.org>
5 *
6 * This program 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 Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <zebra.h>
22
23 #include "command.h"
24 #include "if.h"
25 #include "linklist.h"
26 #include "memory.h"
27 #include "isis_memory.h"
28 #include "prefix.h"
29 #include "routemap.h"
30 #include "stream.h"
31 #include "table.h"
32 #include "vty.h"
33 #include "srcdest_table.h"
34
35 #include "isisd/dict.h"
36 #include "isisd/isis_constants.h"
37 #include "isisd/isis_common.h"
38 #include "isisd/isis_flags.h"
39 #include "isisd/isis_misc.h"
40 #include "isisd/isis_circuit.h"
41 #include "isisd/isisd.h"
42 #include "isisd/isis_lsp.h"
43 #include "isisd/isis_route.h"
44 #include "isisd/isis_zebra.h"
45
46 static int redist_protocol(int family)
47 {
48 if (family == AF_INET)
49 return 0;
50 if (family == AF_INET6)
51 return 1;
52
53 assert(!"Unsupported address family!");
54 return 0;
55 }
56
57 static afi_t afi_for_redist_protocol(int protocol)
58 {
59 if (protocol == 0)
60 return AFI_IP;
61 if (protocol == 1)
62 return AFI_IP6;
63
64 assert(!"Unknown redist protocol!");
65 return AFI_IP;
66 }
67
68 static struct route_table *get_ext_info(struct isis *i, int family)
69 {
70 int protocol = redist_protocol(family);
71
72 return i->ext_info[protocol];
73 }
74
75 static struct isis_redist *get_redist_settings(struct isis_area *area,
76 int family, int type, int level)
77 {
78 int protocol = redist_protocol(family);
79
80 return &area->redist_settings[protocol][type][level - 1];
81 }
82
83 struct route_table *get_ext_reach(struct isis_area *area, int family, int level)
84 {
85 int protocol = redist_protocol(family);
86
87 return area->ext_reach[protocol][level - 1];
88 }
89
90 /* Install external reachability information into a
91 * specific area for a specific level.
92 * Schedule an lsp regenerate if necessary */
93 static void isis_redist_install(struct isis_area *area, int level,
94 const struct prefix *p,
95 const struct prefix_ipv6 *src_p,
96 struct isis_ext_info *info)
97 {
98 int family = p->family;
99 struct route_table *er_table = get_ext_reach(area, family, level);
100 struct route_node *er_node;
101
102 if (!er_table) {
103 zlog_warn(
104 "%s: External reachability table of area %s"
105 " is not initialized.",
106 __func__, area->area_tag);
107 return;
108 }
109
110 er_node = srcdest_rnode_get(er_table, p, src_p);
111 if (er_node->info) {
112 route_unlock_node(er_node);
113
114 /* Don't update/reschedule lsp generation if nothing changed. */
115 if (!memcmp(er_node->info, info, sizeof(*info)))
116 return;
117 } else {
118 er_node->info = XMALLOC(MTYPE_ISIS_EXT_INFO, sizeof(*info));
119 }
120
121 memcpy(er_node->info, info, sizeof(*info));
122 lsp_regenerate_schedule(area, level, 0);
123 }
124
125 /* Remove external reachability information from a
126 * specific area for a specific level.
127 * Schedule an lsp regenerate if necessary. */
128 static void isis_redist_uninstall(struct isis_area *area, int level,
129 const struct prefix *p,
130 const struct prefix_ipv6 *src_p)
131 {
132 int family = p->family;
133 struct route_table *er_table = get_ext_reach(area, family, level);
134 struct route_node *er_node;
135
136 if (!er_table) {
137 zlog_warn(
138 "%s: External reachability table of area %s"
139 " is not initialized.",
140 __func__, area->area_tag);
141 return;
142 }
143
144 er_node = srcdest_rnode_lookup(er_table, p, src_p);
145 if (!er_node)
146 return;
147 else
148 route_unlock_node(er_node);
149
150 if (!er_node->info)
151 return;
152
153 XFREE(MTYPE_ISIS_EXT_INFO, er_node->info);
154 route_unlock_node(er_node);
155 lsp_regenerate_schedule(area, level, 0);
156 }
157
158 /* Update external reachability info of area for a given level
159 * and prefix, using the given redistribution settings. */
160 static void isis_redist_update_ext_reach(struct isis_area *area, int level,
161 struct isis_redist *redist,
162 const struct prefix *p,
163 const struct prefix_ipv6 *src_p,
164 struct isis_ext_info *info)
165 {
166 struct isis_ext_info area_info;
167 route_map_result_t map_ret;
168
169 memcpy(&area_info, info, sizeof(area_info));
170 area_info.metric = redist->metric;
171
172 if (redist->map_name) {
173 map_ret =
174 route_map_apply(redist->map, p, RMAP_ISIS, &area_info);
175 if (map_ret == RMAP_DENYMATCH)
176 area_info.distance = 255;
177 }
178
179 /* Allow synthesized default routes only on always orignate */
180 if (area_info.origin == DEFAULT_ROUTE
181 && redist->redist != DEFAULT_ORIGINATE_ALWAYS)
182 area_info.distance = 255;
183
184 if (area_info.distance < 255)
185 isis_redist_install(area, level, p, src_p, &area_info);
186 else
187 isis_redist_uninstall(area, level, p, src_p);
188 }
189
190 static void isis_redist_ensure_default(struct isis *isis, int family)
191 {
192 struct prefix p;
193 struct route_table *ei_table = get_ext_info(isis, family);
194 struct route_node *ei_node;
195 struct isis_ext_info *info;
196
197 if (family == AF_INET) {
198 p.family = AF_INET;
199 p.prefixlen = 0;
200 memset(&p.u.prefix4, 0, sizeof(p.u.prefix4));
201 } else if (family == AF_INET6) {
202 p.family = AF_INET6;
203 p.prefixlen = 0;
204 memset(&p.u.prefix6, 0, sizeof(p.u.prefix6));
205 } else
206 assert(!"Unknown family!");
207
208 ei_node = srcdest_rnode_get(ei_table, &p, NULL);
209 if (ei_node->info) {
210 route_unlock_node(ei_node);
211 return;
212 }
213
214 ei_node->info =
215 XCALLOC(MTYPE_ISIS_EXT_INFO, sizeof(struct isis_ext_info));
216
217 info = ei_node->info;
218 info->origin = DEFAULT_ROUTE;
219 info->distance = 254;
220 info->metric = MAX_WIDE_PATH_METRIC;
221 }
222
223 /* Handle notification about route being added */
224 void isis_redist_add(int type, struct prefix *p, struct prefix_ipv6 *src_p,
225 uint8_t distance, uint32_t metric)
226 {
227 int family = p->family;
228 struct route_table *ei_table = get_ext_info(isis, family);
229 struct route_node *ei_node;
230 struct isis_ext_info *info;
231 struct listnode *node;
232 struct isis_area *area;
233 int level;
234 struct isis_redist *redist;
235
236 char debug_buf[BUFSIZ];
237 prefix2str(p, debug_buf, sizeof(debug_buf));
238
239 zlog_debug("%s: New route %s from %s: distance %d.", __func__,
240 debug_buf, zebra_route_string(type), distance);
241
242 if (!ei_table) {
243 zlog_warn("%s: External information table not initialized.",
244 __func__);
245 return;
246 }
247
248 ei_node = srcdest_rnode_get(ei_table, p, src_p);
249 if (ei_node->info)
250 route_unlock_node(ei_node);
251 else
252 ei_node->info = XCALLOC(MTYPE_ISIS_EXT_INFO,
253 sizeof(struct isis_ext_info));
254
255 info = ei_node->info;
256 info->origin = type;
257 info->distance = distance;
258 info->metric = metric;
259
260 if (is_default_prefix(p)
261 && (!src_p || !src_p->prefixlen)) {
262 type = DEFAULT_ROUTE;
263 }
264
265 for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
266 for (level = 1; level <= ISIS_LEVELS; level++) {
267 redist = get_redist_settings(area, family, type, level);
268 if (!redist->redist)
269 continue;
270
271 isis_redist_update_ext_reach(area, level, redist, p,
272 src_p, info);
273 }
274 }
275
276 void isis_redist_delete(int type, struct prefix *p, struct prefix_ipv6 *src_p)
277 {
278 int family = p->family;
279 struct route_table *ei_table = get_ext_info(isis, family);
280 struct route_node *ei_node;
281 struct listnode *node;
282 struct isis_area *area;
283 int level;
284 struct isis_redist *redist;
285
286 char debug_buf[BUFSIZ];
287 prefix2str(p, debug_buf, sizeof(debug_buf));
288
289 zlog_debug("%s: Removing route %s from %s.", __func__, debug_buf,
290 zebra_route_string(type));
291
292 if (is_default_prefix(p)
293 && (!src_p || !src_p->prefixlen)) {
294 /* Don't remove default route but add synthetic route for use
295 * by "default-information originate always". Areas without the
296 * "always" setting will ignore routes with origin
297 * DEFAULT_ROUTE. */
298 isis_redist_add(DEFAULT_ROUTE, p, NULL,
299 254, MAX_WIDE_PATH_METRIC);
300 return;
301 }
302
303 if (!ei_table) {
304 zlog_warn("%s: External information table not initialized.",
305 __func__);
306 return;
307 }
308
309 ei_node = srcdest_rnode_lookup(ei_table, p, src_p);
310 if (!ei_node || !ei_node->info) {
311 char buf[BUFSIZ];
312 prefix2str(p, buf, sizeof(buf));
313 zlog_warn(
314 "%s: Got a delete for %s route %s, but that route"
315 " was never added.",
316 __func__, zebra_route_string(type), buf);
317 if (ei_node)
318 route_unlock_node(ei_node);
319 return;
320 }
321 route_unlock_node(ei_node);
322
323 for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
324 for (level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
325 redist = get_redist_settings(area, family, type, level);
326 if (!redist->redist)
327 continue;
328
329 isis_redist_uninstall(area, level, p, src_p);
330 }
331
332 XFREE(MTYPE_ISIS_EXT_INFO, ei_node->info);
333 route_unlock_node(ei_node);
334 }
335
336 static void isis_redist_routemap_set(struct isis_redist *redist,
337 const char *routemap)
338 {
339 if (redist->map_name) {
340 XFREE(MTYPE_ISIS, redist->map_name);
341 redist->map = NULL;
342 }
343
344 if (routemap && strlen(routemap)) {
345 redist->map_name = XSTRDUP(MTYPE_ISIS, routemap);
346 redist->map = route_map_lookup_by_name(routemap);
347 }
348 }
349
350 static void isis_redist_update_zebra_subscriptions(struct isis *isis)
351 {
352 struct listnode *node;
353 struct isis_area *area;
354 int type;
355 int level;
356 int protocol;
357
358 char do_subscribe[REDIST_PROTOCOL_COUNT][ZEBRA_ROUTE_MAX + 1];
359
360 memset(do_subscribe, 0, sizeof(do_subscribe));
361
362 for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
363 for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++)
364 for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++)
365 for (level = 0; level < ISIS_LEVELS; level++)
366 if (area->redist_settings[protocol]
367 [type]
368 [level].redist)
369 do_subscribe[protocol][type] =
370 1;
371
372 for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++)
373 for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) {
374 /* This field is actually controlling transmission of
375 * the IS-IS
376 * routes to Zebra and has nothing to do with
377 * redistribution,
378 * so skip it. */
379 if (type == PROTO_TYPE)
380 continue;
381
382 afi_t afi = afi_for_redist_protocol(protocol);
383
384 if (do_subscribe[protocol][type])
385 isis_zebra_redistribute_set(afi, type);
386 else
387 isis_zebra_redistribute_unset(afi, type);
388 }
389 }
390
391 void isis_redist_set(struct isis_area *area, int level, int family, int type,
392 uint32_t metric, const char *routemap, int originate_type)
393 {
394 int protocol = redist_protocol(family);
395 struct isis_redist *redist =
396 get_redist_settings(area, family, type, level);
397 int i;
398 struct route_table *ei_table;
399 struct route_node *rn;
400 struct isis_ext_info *info;
401
402 redist->redist = (type == DEFAULT_ROUTE) ? originate_type : 1;
403 redist->metric = metric;
404 isis_redist_routemap_set(redist, routemap);
405
406 if (!area->ext_reach[protocol][level - 1]) {
407 area->ext_reach[protocol][level - 1] = srcdest_table_init();
408 }
409
410 for (i = 0; i < REDIST_PROTOCOL_COUNT; i++) {
411 if (!area->isis->ext_info[i]) {
412 area->isis->ext_info[i] = srcdest_table_init();
413 }
414 }
415
416 isis_redist_update_zebra_subscriptions(area->isis);
417
418 if (type == DEFAULT_ROUTE && originate_type == DEFAULT_ORIGINATE_ALWAYS)
419 isis_redist_ensure_default(area->isis, family);
420
421 ei_table = get_ext_info(area->isis, family);
422 for (rn = route_top(ei_table); rn; rn = srcdest_route_next(rn)) {
423 if (!rn->info)
424 continue;
425 info = rn->info;
426
427 const struct prefix *p, *src_p;
428
429 srcdest_rnode_prefixes(rn, &p, &src_p);
430
431 if (type == DEFAULT_ROUTE) {
432 if (!is_default_prefix(p)
433 || (src_p && src_p->prefixlen)) {
434 continue;
435 }
436 } else {
437 if (info->origin != type)
438 continue;
439 }
440
441 isis_redist_update_ext_reach(area, level, redist, p,
442 (const struct prefix_ipv6 *)src_p,
443 info);
444 }
445 }
446
447 void isis_redist_unset(struct isis_area *area, int level, int family, int type)
448 {
449 struct isis_redist *redist =
450 get_redist_settings(area, family, type, level);
451 struct route_table *er_table = get_ext_reach(area, family, level);
452 struct route_node *rn;
453 struct isis_ext_info *info;
454
455 if (!redist->redist)
456 return;
457
458 redist->redist = 0;
459 if (!er_table) {
460 zlog_warn("%s: External reachability table uninitialized.",
461 __func__);
462 return;
463 }
464
465 for (rn = route_top(er_table); rn; rn = srcdest_route_next(rn)) {
466 if (!rn->info)
467 continue;
468 info = rn->info;
469
470 const struct prefix *p, *src_p;
471 srcdest_rnode_prefixes(rn, &p, &src_p);
472
473 if (type == DEFAULT_ROUTE) {
474 if (!is_default_prefix(p)
475 || (src_p && src_p->prefixlen)) {
476 continue;
477 }
478 } else {
479 if (info->origin != type)
480 continue;
481 }
482
483 XFREE(MTYPE_ISIS_EXT_INFO, rn->info);
484 route_unlock_node(rn);
485 }
486
487 lsp_regenerate_schedule(area, level, 0);
488 isis_redist_update_zebra_subscriptions(area->isis);
489 }
490
491 void isis_redist_area_finish(struct isis_area *area)
492 {
493 int protocol;
494 int level;
495 int type;
496
497 for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++)
498 for (level = 0; level < ISIS_LEVELS; level++) {
499 for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) {
500 struct isis_redist *redist;
501
502 redist = &area->redist_settings[protocol][type]
503 [level];
504 redist->redist = 0;
505 if (redist->map_name)
506 XFREE(MTYPE_ISIS, redist->map_name);
507 }
508 route_table_finish(area->ext_reach[protocol][level]);
509 }
510
511 isis_redist_update_zebra_subscriptions(area->isis);
512 }
513
514 DEFUN (isis_redistribute,
515 isis_redistribute_cmd,
516 "redistribute <ipv4|ipv6> " PROTO_REDIST_STR
517 #ifndef FABRICD
518 " <level-1|level-2>"
519 #endif
520 " [<metric (0-16777215)|route-map WORD>]",
521 REDIST_STR
522 "Redistribute IPv4 routes\n"
523 "Redistribute IPv6 routes\n"
524 PROTO_REDIST_HELP
525 #ifndef FABRICD
526 "Redistribute into level-1\n"
527 "Redistribute into level-2\n"
528 #endif
529 "Metric for redistributed routes\n"
530 "ISIS default metric\n"
531 "Route map reference\n"
532 "Pointer to route-map entries\n")
533 {
534 int idx_afi = 1;
535 int idx_protocol = 2;
536 int idx_level = 3;
537 int idx_metric_rmap = fabricd ? 3 : 4;
538 VTY_DECLVAR_CONTEXT(isis_area, area);
539 int family;
540 int afi;
541 int type;
542 int level;
543 unsigned long metric = 0;
544 const char *routemap = NULL;
545
546 family = str2family(argv[idx_afi]->text);
547 if (family < 0)
548 return CMD_WARNING_CONFIG_FAILED;
549
550 afi = family2afi(family);
551 if (!afi)
552 return CMD_WARNING_CONFIG_FAILED;
553
554 type = proto_redistnum(afi, argv[idx_protocol]->text);
555 if (type < 0)
556 return CMD_WARNING_CONFIG_FAILED;
557
558 if (fabricd)
559 level = 2;
560 else if (!strcmp("level-1", argv[idx_level]->arg))
561 level = 1;
562 else if (!strcmp("level-2", argv[idx_level]->arg))
563 level = 2;
564 else
565 return CMD_WARNING_CONFIG_FAILED;
566
567 if ((area->is_type & level) != level) {
568 vty_out(vty, "Node is not a level-%d IS\n", level);
569 return CMD_WARNING_CONFIG_FAILED;
570 }
571
572 if (argc > idx_metric_rmap + 1) {
573 if (argv[idx_metric_rmap + 1]->arg[0] == '\0')
574 return CMD_WARNING_CONFIG_FAILED;
575
576 if (strmatch(argv[idx_metric_rmap]->text, "metric")) {
577 char *endp;
578 metric = strtoul(argv[idx_metric_rmap + 1]->arg, &endp,
579 10);
580
581 if (*endp != '\0')
582 return CMD_WARNING_CONFIG_FAILED;
583 } else {
584 routemap = argv[idx_metric_rmap + 1]->arg;
585 }
586 }
587
588 isis_redist_set(area, level, family, type, metric, routemap, 0);
589 return 0;
590 }
591
592 DEFUN (no_isis_redistribute,
593 no_isis_redistribute_cmd,
594 "no redistribute <ipv4|ipv6> " PROTO_REDIST_STR
595 #ifndef FABRICD
596 " <level-1|level-2>"
597 #endif
598 , NO_STR
599 REDIST_STR
600 "Redistribute IPv4 routes\n"
601 "Redistribute IPv6 routes\n"
602 PROTO_REDIST_HELP
603 #ifndef FABRICD
604 "Redistribute into level-1\n"
605 "Redistribute into level-2\n"
606 #endif
607 )
608 {
609 int idx_afi = 2;
610 int idx_protocol = 3;
611 int idx_level = 4;
612 VTY_DECLVAR_CONTEXT(isis_area, area);
613 int type;
614 int level;
615 int family;
616 int afi;
617
618 family = str2family(argv[idx_afi]->arg);
619 if (family < 0)
620 return CMD_WARNING_CONFIG_FAILED;
621
622 afi = family2afi(family);
623 if (!afi)
624 return CMD_WARNING_CONFIG_FAILED;
625
626 type = proto_redistnum(afi, argv[idx_protocol]->text);
627 if (type < 0)
628 return CMD_WARNING_CONFIG_FAILED;
629
630 if (fabricd)
631 level = 2;
632 else
633 level = strmatch("level-1", argv[idx_level]->text) ? 1 : 2;
634
635 isis_redist_unset(area, level, family, type);
636 return 0;
637 }
638
639 #ifdef FABRICD
640 DEFUN (isis_default_originate,
641 isis_default_originate_cmd,
642 "default-information originate <ipv4|ipv6>"
643 " [always] [<metric (0-16777215)|route-map WORD>]",
644 "Control distribution of default information\n"
645 "Distribute a default route\n"
646 "Distribute default route for IPv4\n"
647 "Distribute default route for IPv6\n"
648 "Always advertise default route\n"
649 "Metric for default route\n"
650 "ISIS default metric\n"
651 "Route map reference\n"
652 "Pointer to route-map entries\n")
653 {
654 int idx_afi = 2;
655 int idx_always = fabricd ? 3 : 4;
656 int idx_metric_rmap = fabricd ? 3 : 4;
657 VTY_DECLVAR_CONTEXT(isis_area, area);
658 int family;
659 int originate_type = DEFAULT_ORIGINATE;
660 int level;
661 unsigned long metric = 0;
662 const char *routemap = NULL;
663
664 family = str2family(argv[idx_afi]->text);
665 if (family < 0)
666 return CMD_WARNING_CONFIG_FAILED;
667
668 level = 2;
669
670 if ((area->is_type & level) != level) {
671 vty_out(vty, "Node is not a level-%d IS\n", level);
672 return CMD_WARNING_CONFIG_FAILED;
673 }
674
675 if (argc > idx_always && strmatch(argv[idx_always]->text, "always")) {
676 originate_type = DEFAULT_ORIGINATE_ALWAYS;
677 idx_metric_rmap++;
678 }
679
680 if (argc > idx_metric_rmap) {
681 if (strmatch(argv[idx_metric_rmap]->text, "metric"))
682 metric = strtoul(argv[idx_metric_rmap + 1]->arg, NULL,
683 10);
684 else
685 routemap = argv[idx_metric_rmap + 1]->arg;
686 }
687
688 if (family == AF_INET6 && originate_type != DEFAULT_ORIGINATE_ALWAYS) {
689 vty_out(vty,
690 "Zebra doesn't implement default-originate for IPv6 yet\n");
691 vty_out(vty,
692 "so use with care or use default-originate always.\n");
693 }
694
695 isis_redist_set(area, level, family, DEFAULT_ROUTE, metric, routemap,
696 originate_type);
697 return 0;
698 }
699
700 DEFUN (no_isis_default_originate,
701 no_isis_default_originate_cmd,
702 "no default-information originate <ipv4|ipv6>",
703 NO_STR
704 "Control distribution of default information\n"
705 "Distribute a default route\n"
706 "Distribute default route for IPv4\n"
707 "Distribute default route for IPv6\n")
708 {
709 int idx_afi = 3;
710 VTY_DECLVAR_CONTEXT(isis_area, area);
711 int family;
712 int level;
713
714 family = str2family(argv[idx_afi]->text);
715 if (family < 0)
716 return CMD_WARNING_CONFIG_FAILED;
717
718 level = 2;
719
720 isis_redist_unset(area, level, family, DEFAULT_ROUTE);
721 return 0;
722 }
723 #endif /* ifdef FABRICD */
724
725 int isis_redist_config_write(struct vty *vty, struct isis_area *area,
726 int family)
727 {
728 int type;
729 int level;
730 int write = 0;
731 struct isis_redist *redist;
732 const char *family_str;
733
734 if (family == AF_INET)
735 family_str = "ipv4";
736 else if (family == AF_INET6)
737 family_str = "ipv6";
738 else
739 return 0;
740
741 for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
742 if (type == PROTO_TYPE)
743 continue;
744
745 for (level = 1; level <= ISIS_LEVELS; level++) {
746 redist = get_redist_settings(area, family, type, level);
747 if (!redist->redist)
748 continue;
749 vty_out(vty, " redistribute %s %s", family_str,
750 zebra_route_string(type));
751 if (!fabricd)
752 vty_out(vty, " level-%d", level);
753 if (redist->metric)
754 vty_out(vty, " metric %u", redist->metric);
755 if (redist->map_name)
756 vty_out(vty, " route-map %s", redist->map_name);
757 vty_out(vty, "\n");
758 write++;
759 }
760 }
761
762 for (level = 1; level <= ISIS_LEVELS; level++) {
763 redist =
764 get_redist_settings(area, family, DEFAULT_ROUTE, level);
765 if (!redist->redist)
766 continue;
767 vty_out(vty, " default-information originate %s",
768 family_str);
769 if (!fabricd)
770 vty_out(vty, " level-%d", level);
771 if (redist->redist == DEFAULT_ORIGINATE_ALWAYS)
772 vty_out(vty, " always");
773 if (redist->metric)
774 vty_out(vty, " metric %u", redist->metric);
775 if (redist->map_name)
776 vty_out(vty, " route-map %s", redist->map_name);
777 vty_out(vty, "\n");
778 write++;
779 }
780
781 return write;
782 }
783
784 void isis_redist_init(void)
785 {
786 install_element(ROUTER_NODE, &isis_redistribute_cmd);
787 install_element(ROUTER_NODE, &no_isis_redistribute_cmd);
788 #ifdef FABRICD
789 install_element(ROUTER_NODE, &isis_default_originate_cmd);
790 install_element(ROUTER_NODE, &no_isis_default_originate_cmd);
791 #endif /* ifdef FABRICD */
792 }