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