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