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