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