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