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>