Annotation of embedaddon/quagga/isisd/isis_redist.c, revision 1.1.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>