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