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