Annotation of embedaddon/quagga/isisd/isis_redist.c, revision 1.1.1.1
1.1 misho 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; 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:
46: static int
47: redist_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:
57: static int
58: is_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:
69: static struct route_table*
70: get_ext_info(struct isis *i, int family)
71: {
72: int protocol = redist_protocol(family);
73:
74: return i->ext_info[protocol];
75: }
76:
77: static struct isis_redist*
78: get_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:
85: struct route_table*
86: get_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:
93: static struct route_node *
94: isis_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:
102: static void
103: isis_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:
112: static 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 */
120: static void
121: isis_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. */
156: static void
157: isis_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. */
185: static void
186: isis_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:
215: static void
216: isis_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 */
254: void
255: isis_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:
304: void
305: isis_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:
364: static void
365: isis_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:
378: static void
379: isis_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:
413: static void
414: isis_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:
469: static void
470: isis_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:
512: void
513: isis_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:
537: DEFUN(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:
606: DEFUN(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:
650: DEFUN(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:
722: DEFUN(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:
756: int
757: isis_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:
814: void
815: isis_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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>