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