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