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