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