]> git.proxmox.com Git - mirror_frr.git/blob - isisd/isis_redist.c
Merge pull request #2764 from opensourcerouting/isis-srcdest
[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, (struct prefix *)p,
175 RMAP_ISIS, &area_info);
176 if (map_ret == RMAP_DENYMATCH)
177 area_info.distance = 255;
178 }
179
180 /* Allow synthesized default routes only on always orignate */
181 if (area_info.origin == DEFAULT_ROUTE
182 && redist->redist != DEFAULT_ORIGINATE_ALWAYS)
183 area_info.distance = 255;
184
185 if (area_info.distance < 255)
186 isis_redist_install(area, level, p, src_p, &area_info);
187 else
188 isis_redist_uninstall(area, level, p, src_p);
189 }
190
191 static void isis_redist_ensure_default(struct isis *isis, int family)
192 {
193 struct prefix p;
194 struct route_table *ei_table = get_ext_info(isis, family);
195 struct route_node *ei_node;
196 struct isis_ext_info *info;
197
198 if (family == AF_INET) {
199 p.family = AF_INET;
200 p.prefixlen = 0;
201 memset(&p.u.prefix4, 0, sizeof(p.u.prefix4));
202 } else if (family == AF_INET6) {
203 p.family = AF_INET6;
204 p.prefixlen = 0;
205 memset(&p.u.prefix6, 0, sizeof(p.u.prefix6));
206 } else
207 assert(!"Unknown family!");
208
209 ei_node = srcdest_rnode_get(ei_table, &p, NULL);
210 if (ei_node->info) {
211 route_unlock_node(ei_node);
212 return;
213 }
214
215 ei_node->info =
216 XCALLOC(MTYPE_ISIS_EXT_INFO, sizeof(struct isis_ext_info));
217
218 info = ei_node->info;
219 info->origin = DEFAULT_ROUTE;
220 info->distance = 254;
221 info->metric = MAX_WIDE_PATH_METRIC;
222 }
223
224 /* Handle notification about route being added */
225 void isis_redist_add(int type, struct prefix *p, struct prefix_ipv6 *src_p,
226 uint8_t distance, uint32_t metric)
227 {
228 int family = p->family;
229 struct route_table *ei_table = get_ext_info(isis, family);
230 struct route_node *ei_node;
231 struct isis_ext_info *info;
232 struct listnode *node;
233 struct isis_area *area;
234 int level;
235 struct isis_redist *redist;
236
237 char debug_buf[BUFSIZ];
238 prefix2str(p, debug_buf, sizeof(debug_buf));
239
240 zlog_debug("%s: New route %s from %s: distance %d.", __func__,
241 debug_buf, zebra_route_string(type), distance);
242
243 if (!ei_table) {
244 zlog_warn("%s: External information table not initialized.",
245 __func__);
246 return;
247 }
248
249 ei_node = srcdest_rnode_get(ei_table, p, src_p);
250 if (ei_node->info)
251 route_unlock_node(ei_node);
252 else
253 ei_node->info = XCALLOC(MTYPE_ISIS_EXT_INFO,
254 sizeof(struct isis_ext_info));
255
256 info = ei_node->info;
257 info->origin = type;
258 info->distance = distance;
259 info->metric = metric;
260
261 if (is_default_prefix(p)
262 && (!src_p || !src_p->prefixlen)) {
263 type = DEFAULT_ROUTE;
264 }
265
266 for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
267 for (level = 1; level <= ISIS_LEVELS; level++) {
268 redist = get_redist_settings(area, family, type, level);
269 if (!redist->redist)
270 continue;
271
272 isis_redist_update_ext_reach(area, level, redist, p,
273 src_p, info);
274 }
275 }
276
277 void isis_redist_delete(int type, struct prefix *p, struct prefix_ipv6 *src_p)
278 {
279 int family = p->family;
280 struct route_table *ei_table = get_ext_info(isis, family);
281 struct route_node *ei_node;
282 struct listnode *node;
283 struct isis_area *area;
284 int level;
285 struct isis_redist *redist;
286
287 char debug_buf[BUFSIZ];
288 prefix2str(p, debug_buf, sizeof(debug_buf));
289
290 zlog_debug("%s: Removing route %s from %s.", __func__, debug_buf,
291 zebra_route_string(type));
292
293 if (is_default_prefix(p)
294 && (!src_p || !src_p->prefixlen)) {
295 /* Don't remove default route but add synthetic route for use
296 * by "default-information originate always". Areas without the
297 * "always" setting will ignore routes with origin
298 * DEFAULT_ROUTE. */
299 isis_redist_add(DEFAULT_ROUTE, p, NULL,
300 254, MAX_WIDE_PATH_METRIC);
301 return;
302 }
303
304 if (!ei_table) {
305 zlog_warn("%s: External information table not initialized.",
306 __func__);
307 return;
308 }
309
310 ei_node = srcdest_rnode_lookup(ei_table, p, src_p);
311 if (!ei_node || !ei_node->info) {
312 char buf[BUFSIZ];
313 prefix2str(p, buf, sizeof(buf));
314 zlog_warn(
315 "%s: Got a delete for %s route %s, but that route"
316 " was never added.",
317 __func__, zebra_route_string(type), buf);
318 if (ei_node)
319 route_unlock_node(ei_node);
320 return;
321 }
322 route_unlock_node(ei_node);
323
324 for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
325 for (level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
326 redist = get_redist_settings(area, family, type, level);
327 if (!redist->redist)
328 continue;
329
330 isis_redist_uninstall(area, level, p, src_p);
331 }
332
333 XFREE(MTYPE_ISIS_EXT_INFO, ei_node->info);
334 route_unlock_node(ei_node);
335 }
336
337 static void isis_redist_routemap_set(struct isis_redist *redist,
338 const char *routemap)
339 {
340 if (redist->map_name) {
341 XFREE(MTYPE_ISIS, redist->map_name);
342 redist->map = NULL;
343 }
344
345 if (routemap && strlen(routemap)) {
346 redist->map_name = XSTRDUP(MTYPE_ISIS, routemap);
347 redist->map = route_map_lookup_by_name(routemap);
348 }
349 }
350
351 static void isis_redist_update_zebra_subscriptions(struct isis *isis)
352 {
353 struct listnode *node;
354 struct isis_area *area;
355 int type;
356 int level;
357 int protocol;
358
359 char do_subscribe[REDIST_PROTOCOL_COUNT][ZEBRA_ROUTE_MAX + 1];
360
361 memset(do_subscribe, 0, sizeof(do_subscribe));
362
363 for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
364 for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++)
365 for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++)
366 for (level = 0; level < ISIS_LEVELS; level++)
367 if (area->redist_settings[protocol]
368 [type]
369 [level].redist)
370 do_subscribe[protocol][type] =
371 1;
372
373 for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++)
374 for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) {
375 /* This field is actually controlling transmission of
376 * the IS-IS
377 * routes to Zebra and has nothing to do with
378 * redistribution,
379 * so skip it. */
380 if (type == ZEBRA_ROUTE_ISIS)
381 continue;
382
383 afi_t afi = afi_for_redist_protocol(protocol);
384
385 if (do_subscribe[protocol][type])
386 isis_zebra_redistribute_set(afi, type);
387 else
388 isis_zebra_redistribute_unset(afi, type);
389 }
390 }
391
392 static void isis_redist_set(struct isis_area *area, int level, int family,
393 int type, uint32_t metric, const char *routemap,
394 int originate_type)
395 {
396 int protocol = redist_protocol(family);
397 struct isis_redist *redist =
398 get_redist_settings(area, family, type, level);
399 int i;
400 struct route_table *ei_table;
401 struct route_node *rn;
402 struct isis_ext_info *info;
403
404 redist->redist = (type == DEFAULT_ROUTE) ? originate_type : 1;
405 redist->metric = metric;
406 isis_redist_routemap_set(redist, routemap);
407
408 if (!area->ext_reach[protocol][level - 1]) {
409 area->ext_reach[protocol][level - 1] = srcdest_table_init();
410 }
411
412 for (i = 0; i < REDIST_PROTOCOL_COUNT; i++) {
413 if (!area->isis->ext_info[i]) {
414 area->isis->ext_info[i] = srcdest_table_init();
415 }
416 }
417
418 isis_redist_update_zebra_subscriptions(area->isis);
419
420 if (type == DEFAULT_ROUTE && originate_type == DEFAULT_ORIGINATE_ALWAYS)
421 isis_redist_ensure_default(area->isis, family);
422
423 ei_table = get_ext_info(area->isis, family);
424 for (rn = route_top(ei_table); rn; rn = srcdest_route_next(rn)) {
425 if (!rn->info)
426 continue;
427 info = rn->info;
428
429 const struct prefix *p, *src_p;
430
431 srcdest_rnode_prefixes(rn, &p, &src_p);
432
433 if (type == DEFAULT_ROUTE) {
434 if (!is_default_prefix(p)
435 || (src_p && src_p->prefixlen)) {
436 continue;
437 }
438 } else {
439 if (info->origin != type)
440 continue;
441 }
442
443 isis_redist_update_ext_reach(area, level, redist, p,
444 (struct prefix_ipv6 *)src_p, info);
445 }
446 }
447
448 static void isis_redist_unset(struct isis_area *area, int level, int family,
449 int type)
450 {
451 struct isis_redist *redist =
452 get_redist_settings(area, family, type, level);
453 struct route_table *er_table = get_ext_reach(area, family, level);
454 struct route_node *rn;
455 struct isis_ext_info *info;
456
457 if (!redist->redist)
458 return;
459
460 redist->redist = 0;
461 if (!er_table) {
462 zlog_warn("%s: External reachability table uninitialized.",
463 __func__);
464 return;
465 }
466
467 for (rn = route_top(er_table); rn; rn = srcdest_route_next(rn)) {
468 if (!rn->info)
469 continue;
470 info = rn->info;
471
472 const struct prefix *p, *src_p;
473 srcdest_rnode_prefixes(rn, &p, &src_p);
474
475 if (type == DEFAULT_ROUTE) {
476 if (!is_default_prefix(p)
477 || (src_p && src_p->prefixlen)) {
478 continue;
479 }
480 } else {
481 if (info->origin != type)
482 continue;
483 }
484
485 XFREE(MTYPE_ISIS_EXT_INFO, rn->info);
486 route_unlock_node(rn);
487 }
488
489 lsp_regenerate_schedule(area, level, 0);
490 isis_redist_update_zebra_subscriptions(area->isis);
491 }
492
493 void isis_redist_area_finish(struct isis_area *area)
494 {
495 int protocol;
496 int level;
497 int type;
498
499 for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++)
500 for (level = 0; level < ISIS_LEVELS; level++) {
501 for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) {
502 struct isis_redist *redist;
503
504 redist = &area->redist_settings[protocol][type]
505 [level];
506 redist->redist = 0;
507 if (redist->map_name)
508 XFREE(MTYPE_ISIS, redist->map_name);
509 }
510 route_table_finish(area->ext_reach[protocol][level]);
511 }
512
513 isis_redist_update_zebra_subscriptions(area->isis);
514 }
515
516 DEFUN (isis_redistribute,
517 isis_redistribute_cmd,
518 "redistribute <ipv4|ipv6> " FRR_REDIST_STR_ISISD " <level-1|level-2> [<metric (0-16777215)|route-map WORD>]",
519 REDIST_STR
520 "Redistribute IPv4 routes\n"
521 "Redistribute IPv6 routes\n"
522 FRR_REDIST_HELP_STR_ISISD
523 "Redistribute into level-1\n"
524 "Redistribute into level-2\n"
525 "Metric for redistributed routes\n"
526 "ISIS default metric\n"
527 "Route map reference\n"
528 "Pointer to route-map entries\n")
529 {
530 int idx_afi = 1;
531 int idx_protocol = 2;
532 int idx_level = 3;
533 int idx_metric_rmap = 4;
534 VTY_DECLVAR_CONTEXT(isis_area, area);
535 int family;
536 int afi;
537 int type;
538 int level;
539 unsigned long metric = 0;
540 const char *routemap = NULL;
541
542 family = str2family(argv[idx_afi]->text);
543 if (family < 0)
544 return CMD_WARNING_CONFIG_FAILED;
545
546 afi = family2afi(family);
547 if (!afi)
548 return CMD_WARNING_CONFIG_FAILED;
549
550 type = proto_redistnum(afi, argv[idx_protocol]->text);
551 if (type < 0)
552 return CMD_WARNING_CONFIG_FAILED;
553
554 if (!strcmp("level-1", argv[idx_level]->arg))
555 level = 1;
556 else if (!strcmp("level-2", argv[idx_level]->arg))
557 level = 2;
558 else
559 return CMD_WARNING_CONFIG_FAILED;
560
561 if ((area->is_type & level) != level) {
562 vty_out(vty, "Node is not a level-%d IS\n", level);
563 return CMD_WARNING_CONFIG_FAILED;
564 }
565
566 if (argc > idx_metric_rmap + 1) {
567 if (argv[idx_metric_rmap + 1]->arg[0] == '\0')
568 return CMD_WARNING_CONFIG_FAILED;
569
570 if (strmatch(argv[idx_metric_rmap]->text, "metric")) {
571 char *endp;
572 metric = strtoul(argv[idx_metric_rmap + 1]->arg, &endp,
573 10);
574
575 if (*endp != '\0')
576 return CMD_WARNING_CONFIG_FAILED;
577 } else {
578 routemap = argv[idx_metric_rmap + 1]->arg;
579 }
580 }
581
582 isis_redist_set(area, level, family, type, metric, routemap, 0);
583 return 0;
584 }
585
586 DEFUN (no_isis_redistribute,
587 no_isis_redistribute_cmd,
588 "no redistribute <ipv4|ipv6> " FRR_REDIST_STR_ISISD " <level-1|level-2>",
589 NO_STR
590 REDIST_STR
591 "Redistribute IPv4 routes\n"
592 "Redistribute IPv6 routes\n"
593 FRR_REDIST_HELP_STR_ISISD
594 "Redistribute into level-1\n"
595 "Redistribute into level-2\n")
596 {
597 int idx_afi = 2;
598 int idx_protocol = 3;
599 int idx_level = 4;
600 VTY_DECLVAR_CONTEXT(isis_area, area);
601 int type;
602 int level;
603 int family;
604 int afi;
605
606 family = str2family(argv[idx_afi]->arg);
607 if (family < 0)
608 return CMD_WARNING_CONFIG_FAILED;
609
610 afi = family2afi(family);
611 if (!afi)
612 return CMD_WARNING_CONFIG_FAILED;
613
614 type = proto_redistnum(afi, argv[idx_protocol]->text);
615 if (type < 0)
616 return CMD_WARNING_CONFIG_FAILED;
617
618 level = strmatch("level-1", argv[idx_level]->text) ? 1 : 2;
619
620 isis_redist_unset(area, level, family, type);
621 return 0;
622 }
623
624 DEFUN (isis_default_originate,
625 isis_default_originate_cmd,
626 "default-information originate <ipv4|ipv6> <level-1|level-2> [always] [<metric (0-16777215)|route-map WORD>]",
627 "Control distribution of default information\n"
628 "Distribute a default route\n"
629 "Distribute default route for IPv4\n"
630 "Distribute default route for IPv6\n"
631 "Distribute default route into level-1\n"
632 "Distribute default route into level-2\n"
633 "Always advertise default route\n"
634 "Metric for default route\n"
635 "ISIS default metric\n"
636 "Route map reference\n"
637 "Pointer to route-map entries\n")
638 {
639 int idx_afi = 2;
640 int idx_level = 3;
641 int idx_always = 4;
642 int idx_metric_rmap = 4;
643 VTY_DECLVAR_CONTEXT(isis_area, area);
644 int family;
645 int originate_type = DEFAULT_ORIGINATE;
646 int level;
647 unsigned long metric = 0;
648 const char *routemap = NULL;
649
650 family = str2family(argv[idx_afi]->text);
651 if (family < 0)
652 return CMD_WARNING_CONFIG_FAILED;
653
654 level = strmatch("level-1", argv[idx_level]->text) ? 1 : 2;
655
656 if ((area->is_type & level) != level) {
657 vty_out(vty, "Node is not a level-%d IS\n", level);
658 return CMD_WARNING_CONFIG_FAILED;
659 }
660
661 if (argc > idx_always && strmatch(argv[idx_always]->text, "always")) {
662 originate_type = DEFAULT_ORIGINATE_ALWAYS;
663 idx_metric_rmap++;
664 }
665
666 if (argc > idx_metric_rmap) {
667 if (strmatch(argv[idx_metric_rmap]->text, "metric"))
668 metric = strtoul(argv[idx_metric_rmap + 1]->arg, NULL,
669 10);
670 else
671 routemap = argv[idx_metric_rmap + 1]->arg;
672 }
673
674 if (family == AF_INET6 && originate_type != DEFAULT_ORIGINATE_ALWAYS) {
675 vty_out(vty,
676 "Zebra doesn't implement default-originate for IPv6 yet\n");
677 vty_out(vty,
678 "so use with care or use default-originate always.\n");
679 }
680
681 isis_redist_set(area, level, family, DEFAULT_ROUTE, metric, routemap,
682 originate_type);
683 return 0;
684 }
685
686 DEFUN (no_isis_default_originate,
687 no_isis_default_originate_cmd,
688 "no default-information originate <ipv4|ipv6> <level-1|level-2>",
689 NO_STR
690 "Control distribution of default information\n"
691 "Distribute a default route\n"
692 "Distribute default route for IPv4\n"
693 "Distribute default route for IPv6\n"
694 "Distribute default route into level-1\n"
695 "Distribute default route into level-2\n")
696 {
697 int idx_afi = 3;
698 int idx_level = 4;
699 VTY_DECLVAR_CONTEXT(isis_area, area);
700 int family;
701 int level;
702
703 family = str2family(argv[idx_afi]->text);
704 if (family < 0)
705 return CMD_WARNING_CONFIG_FAILED;
706
707 if (strmatch("level-1", argv[idx_level]->text))
708 level = 1;
709 else if (strmatch("level-2", argv[idx_level]->text))
710 level = 2;
711 else
712 return CMD_WARNING_CONFIG_FAILED;
713
714 isis_redist_unset(area, level, family, DEFAULT_ROUTE);
715 return 0;
716 }
717
718 int isis_redist_config_write(struct vty *vty, struct isis_area *area,
719 int family)
720 {
721 int type;
722 int level;
723 int write = 0;
724 struct isis_redist *redist;
725 const char *family_str;
726
727 if (family == AF_INET)
728 family_str = "ipv4";
729 else if (family == AF_INET6)
730 family_str = "ipv6";
731 else
732 return 0;
733
734 for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
735 if (type == ZEBRA_ROUTE_ISIS)
736 continue;
737
738 for (level = 1; level <= ISIS_LEVELS; level++) {
739 redist = get_redist_settings(area, family, type, level);
740 if (!redist->redist)
741 continue;
742 vty_out(vty, " redistribute %s %s level-%d", family_str,
743 zebra_route_string(type), level);
744 if (redist->metric)
745 vty_out(vty, " metric %u", redist->metric);
746 if (redist->map_name)
747 vty_out(vty, " route-map %s", redist->map_name);
748 vty_out(vty, "\n");
749 write++;
750 }
751 }
752
753 for (level = 1; level <= ISIS_LEVELS; level++) {
754 redist =
755 get_redist_settings(area, family, DEFAULT_ROUTE, level);
756 if (!redist->redist)
757 continue;
758 vty_out(vty, " default-information originate %s level-%d",
759 family_str, level);
760 if (redist->redist == DEFAULT_ORIGINATE_ALWAYS)
761 vty_out(vty, " always");
762 if (redist->metric)
763 vty_out(vty, " metric %u", redist->metric);
764 if (redist->map_name)
765 vty_out(vty, " route-map %s", redist->map_name);
766 vty_out(vty, "\n");
767 write++;
768 }
769
770 return write;
771 }
772
773 void isis_redist_init(void)
774 {
775 install_element(ISIS_NODE, &isis_redistribute_cmd);
776 install_element(ISIS_NODE, &no_isis_redistribute_cmd);
777 install_element(ISIS_NODE, &isis_default_originate_cmd);
778 install_element(ISIS_NODE, &no_isis_default_originate_cmd);
779 }