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