]> git.proxmox.com Git - mirror_frr.git/blame - isisd/isis_redist.c
Merge pull request #3370 from pguibert6WIND/default_vrf_initialization
[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);
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);
347 }
f3ccedaa
CF
348}
349
d62a17ae 350static void isis_redist_update_zebra_subscriptions(struct isis *isis)
f3ccedaa 351{
d62a17ae 352 struct listnode *node;
353 struct isis_area *area;
354 int type;
355 int level;
356 int protocol;
357
358 char do_subscribe[REDIST_PROTOCOL_COUNT][ZEBRA_ROUTE_MAX + 1];
359
360 memset(do_subscribe, 0, sizeof(do_subscribe));
361
362 for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
363 for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++)
364 for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++)
365 for (level = 0; level < ISIS_LEVELS; level++)
9d303b37
DL
366 if (area->redist_settings[protocol]
367 [type]
368 [level].redist)
d62a17ae 369 do_subscribe[protocol][type] =
370 1;
371
372 for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++)
373 for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) {
374 /* This field is actually controlling transmission of
375 * the IS-IS
376 * routes to Zebra and has nothing to do with
377 * redistribution,
378 * so skip it. */
7c0cbd0e 379 if (type == PROTO_TYPE)
d62a17ae 380 continue;
381
382 afi_t afi = afi_for_redist_protocol(protocol);
383
384 if (do_subscribe[protocol][type])
385 isis_zebra_redistribute_set(afi, type);
386 else
387 isis_zebra_redistribute_unset(afi, type);
388 }
f3ccedaa
CF
389}
390
d62a17ae 391static void isis_redist_set(struct isis_area *area, int level, int family,
392 int type, uint32_t metric, const char *routemap,
393 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
d62a17ae 448static void isis_redist_unset(struct isis_area *area, int level, int family,
449 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;
507 if (redist->map_name)
508 XFREE(MTYPE_ISIS, redist->map_name);
509 }
510 route_table_finish(area->ext_reach[protocol][level]);
511 }
512
513 isis_redist_update_zebra_subscriptions(area->isis);
f3ccedaa
CF
514}
515
49d41a26
DS
516DEFUN (isis_redistribute,
517 isis_redistribute_cmd,
ef020087
CF
518 "redistribute <ipv4|ipv6> " PROTO_REDIST_STR
519#ifndef FABRICD
520 " <level-1|level-2>"
521#endif
522 " [<metric (0-16777215)|route-map WORD>]",
49d41a26
DS
523 REDIST_STR
524 "Redistribute IPv4 routes\n"
525 "Redistribute IPv6 routes\n"
7c0cbd0e 526 PROTO_REDIST_HELP
ef020087 527#ifndef FABRICD
49d41a26
DS
528 "Redistribute into level-1\n"
529 "Redistribute into level-2\n"
ef020087 530#endif
49d41a26
DS
531 "Metric for redistributed routes\n"
532 "ISIS default metric\n"
533 "Route map reference\n"
534 "Pointer to route-map entries\n")
f3ccedaa 535{
d62a17ae 536 int idx_afi = 1;
537 int idx_protocol = 2;
538 int idx_level = 3;
ef020087 539 int idx_metric_rmap = fabricd ? 3 : 4;
d62a17ae 540 VTY_DECLVAR_CONTEXT(isis_area, area);
541 int family;
542 int afi;
543 int type;
544 int level;
8cfc8c5c 545 unsigned long metric = 0;
d62a17ae 546 const char *routemap = NULL;
547
548 family = str2family(argv[idx_afi]->text);
549 if (family < 0)
550 return CMD_WARNING_CONFIG_FAILED;
551
552 afi = family2afi(family);
553 if (!afi)
554 return CMD_WARNING_CONFIG_FAILED;
555
556 type = proto_redistnum(afi, argv[idx_protocol]->text);
557 if (type < 0)
558 return CMD_WARNING_CONFIG_FAILED;
559
ef020087
CF
560 if (fabricd)
561 level = 2;
562 else if (!strcmp("level-1", argv[idx_level]->arg))
d62a17ae 563 level = 1;
564 else if (!strcmp("level-2", argv[idx_level]->arg))
565 level = 2;
566 else
567 return CMD_WARNING_CONFIG_FAILED;
568
569 if ((area->is_type & level) != level) {
570 vty_out(vty, "Node is not a level-%d IS\n", level);
571 return CMD_WARNING_CONFIG_FAILED;
572 }
573
d62a17ae 574 if (argc > idx_metric_rmap + 1) {
575 if (argv[idx_metric_rmap + 1]->arg[0] == '\0')
576 return CMD_WARNING_CONFIG_FAILED;
577
578 if (strmatch(argv[idx_metric_rmap]->text, "metric")) {
579 char *endp;
580 metric = strtoul(argv[idx_metric_rmap + 1]->arg, &endp,
581 10);
582
583 if (*endp != '\0')
584 return CMD_WARNING_CONFIG_FAILED;
585 } else {
586 routemap = argv[idx_metric_rmap + 1]->arg;
587 }
588 }
589
590 isis_redist_set(area, level, family, type, metric, routemap, 0);
591 return 0;
f3ccedaa
CF
592}
593
49d41a26
DS
594DEFUN (no_isis_redistribute,
595 no_isis_redistribute_cmd,
ef020087
CF
596 "no redistribute <ipv4|ipv6> " PROTO_REDIST_STR
597#ifndef FABRICD
598 " <level-1|level-2>"
599#endif
600 , NO_STR
49d41a26
DS
601 REDIST_STR
602 "Redistribute IPv4 routes\n"
603 "Redistribute IPv6 routes\n"
7c0cbd0e 604 PROTO_REDIST_HELP
ef020087 605#ifndef FABRICD
49d41a26 606 "Redistribute into level-1\n"
ef020087
CF
607 "Redistribute into level-2\n"
608#endif
609 )
f3ccedaa 610{
d62a17ae 611 int idx_afi = 2;
612 int idx_protocol = 3;
613 int idx_level = 4;
614 VTY_DECLVAR_CONTEXT(isis_area, area);
615 int type;
616 int level;
617 int family;
618 int afi;
619
620 family = str2family(argv[idx_afi]->arg);
621 if (family < 0)
622 return CMD_WARNING_CONFIG_FAILED;
623
624 afi = family2afi(family);
625 if (!afi)
626 return CMD_WARNING_CONFIG_FAILED;
627
628 type = proto_redistnum(afi, argv[idx_protocol]->text);
629 if (type < 0)
630 return CMD_WARNING_CONFIG_FAILED;
631
ef020087
CF
632 if (fabricd)
633 level = 2;
634 else
635 level = strmatch("level-1", argv[idx_level]->text) ? 1 : 2;
d62a17ae 636
637 isis_redist_unset(area, level, family, type);
638 return 0;
f3ccedaa
CF
639}
640
49d41a26
DS
641DEFUN (isis_default_originate,
642 isis_default_originate_cmd,
ef020087
CF
643 "default-information originate <ipv4|ipv6>"
644#ifndef FABRICD
645 " <level-1|level-2>"
646#endif
647 " [always] [<metric (0-16777215)|route-map WORD>]",
49d41a26
DS
648 "Control distribution of default information\n"
649 "Distribute a default route\n"
650 "Distribute default route for IPv4\n"
651 "Distribute default route for IPv6\n"
ef020087 652#ifndef FABRICD
49d41a26
DS
653 "Distribute default route into level-1\n"
654 "Distribute default route into level-2\n"
ef020087 655#endif
49d41a26
DS
656 "Always advertise default route\n"
657 "Metric for default route\n"
658 "ISIS default metric\n"
659 "Route map reference\n"
660 "Pointer to route-map entries\n")
f3ccedaa 661{
d62a17ae 662 int idx_afi = 2;
663 int idx_level = 3;
ef020087
CF
664 int idx_always = fabricd ? 3 : 4;
665 int idx_metric_rmap = fabricd ? 3 : 4;
d62a17ae 666 VTY_DECLVAR_CONTEXT(isis_area, area);
667 int family;
668 int originate_type = DEFAULT_ORIGINATE;
669 int level;
8cfc8c5c 670 unsigned long metric = 0;
d62a17ae 671 const char *routemap = NULL;
672
673 family = str2family(argv[idx_afi]->text);
674 if (family < 0)
675 return CMD_WARNING_CONFIG_FAILED;
676
ef020087
CF
677 if (fabricd)
678 level = 2;
679 else
680 level = strmatch("level-1", argv[idx_level]->text) ? 1 : 2;
d62a17ae 681
682 if ((area->is_type & level) != level) {
683 vty_out(vty, "Node is not a level-%d IS\n", level);
684 return CMD_WARNING_CONFIG_FAILED;
685 }
686
687 if (argc > idx_always && strmatch(argv[idx_always]->text, "always")) {
688 originate_type = DEFAULT_ORIGINATE_ALWAYS;
689 idx_metric_rmap++;
690 }
691
692 if (argc > idx_metric_rmap) {
693 if (strmatch(argv[idx_metric_rmap]->text, "metric"))
694 metric = strtoul(argv[idx_metric_rmap + 1]->arg, NULL,
695 10);
696 else
697 routemap = argv[idx_metric_rmap + 1]->arg;
698 }
699
700 if (family == AF_INET6 && originate_type != DEFAULT_ORIGINATE_ALWAYS) {
701 vty_out(vty,
702 "Zebra doesn't implement default-originate for IPv6 yet\n");
703 vty_out(vty,
704 "so use with care or use default-originate always.\n");
705 }
706
707 isis_redist_set(area, level, family, DEFAULT_ROUTE, metric, routemap,
708 originate_type);
709 return 0;
f3ccedaa
CF
710}
711
49d41a26
DS
712DEFUN (no_isis_default_originate,
713 no_isis_default_originate_cmd,
ef020087
CF
714 "no default-information originate <ipv4|ipv6>"
715#ifndef FABRICD
716 " <level-1|level-2>"
717#endif
718 , NO_STR
49d41a26
DS
719 "Control distribution of default information\n"
720 "Distribute a default route\n"
721 "Distribute default route for IPv4\n"
722 "Distribute default route for IPv6\n"
ef020087 723#ifndef FABRICD
49d41a26 724 "Distribute default route into level-1\n"
ef020087
CF
725 "Distribute default route into level-2\n"
726#endif
727 )
f3ccedaa 728{
d62a17ae 729 int idx_afi = 3;
730 int idx_level = 4;
731 VTY_DECLVAR_CONTEXT(isis_area, area);
732 int family;
733 int level;
734
735 family = str2family(argv[idx_afi]->text);
736 if (family < 0)
737 return CMD_WARNING_CONFIG_FAILED;
738
ef020087
CF
739 if (fabricd)
740 level = 2;
741 else if (strmatch("level-1", argv[idx_level]->text))
d62a17ae 742 level = 1;
743 else if (strmatch("level-2", argv[idx_level]->text))
744 level = 2;
745 else
746 return CMD_WARNING_CONFIG_FAILED;
747
748 isis_redist_unset(area, level, family, DEFAULT_ROUTE);
749 return 0;
f3ccedaa
CF
750}
751
d62a17ae 752int isis_redist_config_write(struct vty *vty, struct isis_area *area,
753 int family)
f3ccedaa 754{
d62a17ae 755 int type;
756 int level;
757 int write = 0;
758 struct isis_redist *redist;
759 const char *family_str;
760
761 if (family == AF_INET)
762 family_str = "ipv4";
763 else if (family == AF_INET6)
764 family_str = "ipv6";
765 else
766 return 0;
767
768 for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
7c0cbd0e 769 if (type == PROTO_TYPE)
d62a17ae 770 continue;
771
772 for (level = 1; level <= ISIS_LEVELS; level++) {
773 redist = get_redist_settings(area, family, type, level);
774 if (!redist->redist)
775 continue;
ef020087
CF
776 vty_out(vty, " redistribute %s %s", family_str,
777 zebra_route_string(type));
778 if (!fabricd)
779 vty_out(vty, " level-%d", level);
8cfc8c5c 780 if (redist->metric)
d62a17ae 781 vty_out(vty, " metric %u", redist->metric);
782 if (redist->map_name)
783 vty_out(vty, " route-map %s", redist->map_name);
784 vty_out(vty, "\n");
785 write++;
786 }
787 }
788
789 for (level = 1; level <= ISIS_LEVELS; level++) {
790 redist =
791 get_redist_settings(area, family, DEFAULT_ROUTE, level);
792 if (!redist->redist)
793 continue;
ef020087
CF
794 vty_out(vty, " default-information originate %s",
795 family_str);
796 if (!fabricd)
797 vty_out(vty, " level-%d", level);
d62a17ae 798 if (redist->redist == DEFAULT_ORIGINATE_ALWAYS)
799 vty_out(vty, " always");
8cfc8c5c 800 if (redist->metric)
d62a17ae 801 vty_out(vty, " metric %u", redist->metric);
802 if (redist->map_name)
803 vty_out(vty, " route-map %s", redist->map_name);
804 vty_out(vty, "\n");
805 write++;
806 }
807
808 return write;
f3ccedaa
CF
809}
810
d62a17ae 811void isis_redist_init(void)
f3ccedaa 812{
7c0cbd0e
CF
813 install_element(ROUTER_NODE, &isis_redistribute_cmd);
814 install_element(ROUTER_NODE, &no_isis_redistribute_cmd);
815 install_element(ROUTER_NODE, &isis_default_originate_cmd);
816 install_element(ROUTER_NODE, &no_isis_default_originate_cmd);
f3ccedaa 817}