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