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