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