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