File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / ospf6d / ospf6_interface.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jul 21 23:54:39 2013 UTC (11 years ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, HEAD
0.99.22

    1: /*
    2:  * Copyright (C) 2003 Yasuhiro Ohara
    3:  *
    4:  * This file is part of GNU Zebra.
    5:  *
    6:  * GNU Zebra 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
    8:  * Free Software Foundation; either version 2, or (at your option) any
    9:  * later version.
   10:  *
   11:  * GNU Zebra is distributed in the hope that it will be useful, but
   12:  * WITHOUT ANY WARRANTY; without even the implied warranty of
   13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14:  * General Public License for more details.
   15:  *
   16:  * You should have received a copy of the GNU General Public License
   17:  * along with GNU Zebra; see the file COPYING.  If not, write to the 
   18:  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
   19:  * Boston, MA 02111-1307, USA.  
   20:  */
   21: 
   22: #include <zebra.h>
   23: 
   24: #include "memory.h"
   25: #include "if.h"
   26: #include "log.h"
   27: #include "command.h"
   28: #include "thread.h"
   29: #include "prefix.h"
   30: #include "plist.h"
   31: 
   32: #include "ospf6_lsa.h"
   33: #include "ospf6_lsdb.h"
   34: #include "ospf6_network.h"
   35: #include "ospf6_message.h"
   36: #include "ospf6_route.h"
   37: #include "ospf6_top.h"
   38: #include "ospf6_area.h"
   39: #include "ospf6_interface.h"
   40: #include "ospf6_neighbor.h"
   41: #include "ospf6_intra.h"
   42: #include "ospf6_spf.h"
   43: #include "ospf6d.h"
   44: 
   45: unsigned char conf_debug_ospf6_interface = 0;
   46: 
   47: const char *ospf6_interface_state_str[] =
   48: {
   49:   "None",
   50:   "Down",
   51:   "Loopback",
   52:   "Waiting",
   53:   "PointToPoint",
   54:   "DROther",
   55:   "BDR",
   56:   "DR",
   57:   NULL
   58: };
   59: 
   60: struct ospf6_interface *
   61: ospf6_interface_lookup_by_ifindex (int ifindex)
   62: {
   63:   struct ospf6_interface *oi;
   64:   struct interface *ifp;
   65: 
   66:   ifp = if_lookup_by_index (ifindex);
   67:   if (ifp == NULL)
   68:     return (struct ospf6_interface *) NULL;
   69: 
   70:   oi = (struct ospf6_interface *) ifp->info;
   71:   return oi;
   72: }
   73: 
   74: /* schedule routing table recalculation */
   75: static void
   76: ospf6_interface_lsdb_hook (struct ospf6_lsa *lsa)
   77: {
   78:   switch (ntohs (lsa->header->type))
   79:     {
   80:       case OSPF6_LSTYPE_LINK:
   81:         if (OSPF6_INTERFACE (lsa->lsdb->data)->state == OSPF6_INTERFACE_DR)
   82:           OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (OSPF6_INTERFACE (lsa->lsdb->data));
   83:         ospf6_spf_schedule (OSPF6_INTERFACE (lsa->lsdb->data)->area);
   84:         break;
   85: 
   86:       default:
   87:         break;
   88:     }
   89: }
   90: 
   91: /* Create new ospf6 interface structure */
   92: struct ospf6_interface *
   93: ospf6_interface_create (struct interface *ifp)
   94: {
   95:   struct ospf6_interface *oi;
   96:   unsigned int iobuflen;
   97: 
   98:   oi = (struct ospf6_interface *)
   99:     XCALLOC (MTYPE_OSPF6_IF, sizeof (struct ospf6_interface));
  100: 
  101:   if (!oi)
  102:     {
  103:       zlog_err ("Can't malloc ospf6_interface for ifindex %d", ifp->ifindex);
  104:       return (struct ospf6_interface *) NULL;
  105:     }
  106: 
  107:   oi->area = (struct ospf6_area *) NULL;
  108:   oi->neighbor_list = list_new ();
  109:   oi->neighbor_list->cmp = ospf6_neighbor_cmp;
  110:   oi->linklocal_addr = (struct in6_addr *) NULL;
  111:   oi->instance_id = OSPF6_INTERFACE_INSTANCE_ID;
  112:   oi->transdelay = OSPF6_INTERFACE_TRANSDELAY;
  113:   oi->priority = OSPF6_INTERFACE_PRIORITY;
  114: 
  115:   oi->hello_interval = OSPF6_INTERFACE_HELLO_INTERVAL;
  116:   oi->dead_interval = OSPF6_INTERFACE_DEAD_INTERVAL;
  117:   oi->rxmt_interval = OSPF6_INTERFACE_RXMT_INTERVAL;
  118:   oi->cost = OSPF6_INTERFACE_COST;
  119:   oi->state = OSPF6_INTERFACE_DOWN;
  120:   oi->flag = 0;
  121:   oi->mtu_ignore = 0;
  122: 
  123:   /* Try to adjust I/O buffer size with IfMtu */
  124:   oi->ifmtu = ifp->mtu6;
  125:   iobuflen = ospf6_iobuf_size (ifp->mtu6);
  126:   if (oi->ifmtu > iobuflen)
  127:     {
  128:       if (IS_OSPF6_DEBUG_INTERFACE)
  129:         zlog_debug ("Interface %s: IfMtu is adjusted to I/O buffer size: %d.",
  130: 		    ifp->name, iobuflen);
  131:       oi->ifmtu = iobuflen;
  132:     }
  133: 
  134:   oi->lsupdate_list = ospf6_lsdb_create (oi);
  135:   oi->lsack_list = ospf6_lsdb_create (oi);
  136:   oi->lsdb = ospf6_lsdb_create (oi);
  137:   oi->lsdb->hook_add = ospf6_interface_lsdb_hook;
  138:   oi->lsdb->hook_remove = ospf6_interface_lsdb_hook;
  139:   oi->lsdb_self = ospf6_lsdb_create (oi);
  140: 
  141:   oi->route_connected = OSPF6_ROUTE_TABLE_CREATE (INTERFACE, CONNECTED_ROUTES);
  142:   oi->route_connected->scope = oi;
  143: 
  144:   /* link both */
  145:   oi->interface = ifp;
  146:   ifp->info = oi;
  147: 
  148:   return oi;
  149: }
  150: 
  151: void
  152: ospf6_interface_delete (struct ospf6_interface *oi)
  153: {
  154:   struct listnode *node, *nnode;
  155:   struct ospf6_neighbor *on;
  156: 
  157:   for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
  158:       ospf6_neighbor_delete (on);
  159:   
  160:   list_delete (oi->neighbor_list);
  161: 
  162:   THREAD_OFF (oi->thread_send_hello);
  163:   THREAD_OFF (oi->thread_send_lsupdate);
  164:   THREAD_OFF (oi->thread_send_lsack);
  165: 
  166:   ospf6_lsdb_remove_all (oi->lsdb);
  167:   ospf6_lsdb_remove_all (oi->lsupdate_list);
  168:   ospf6_lsdb_remove_all (oi->lsack_list);
  169: 
  170:   ospf6_lsdb_delete (oi->lsdb);
  171:   ospf6_lsdb_delete (oi->lsdb_self);
  172: 
  173:   ospf6_lsdb_delete (oi->lsupdate_list);
  174:   ospf6_lsdb_delete (oi->lsack_list);
  175: 
  176:   ospf6_route_table_delete (oi->route_connected);
  177: 
  178:   /* cut link */
  179:   oi->interface->info = NULL;
  180: 
  181:   /* plist_name */
  182:   if (oi->plist_name)
  183:     XFREE (MTYPE_PREFIX_LIST_STR, oi->plist_name);
  184: 
  185:   XFREE (MTYPE_OSPF6_IF, oi);
  186: }
  187: 
  188: void
  189: ospf6_interface_enable (struct ospf6_interface *oi)
  190: {
  191:   UNSET_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE);
  192: 
  193:   oi->thread_send_hello =
  194:     thread_add_event (master, ospf6_hello_send, oi, 0);
  195: }
  196: 
  197: void
  198: ospf6_interface_disable (struct ospf6_interface *oi)
  199: {
  200:   struct listnode *node, *nnode;
  201:   struct ospf6_neighbor *on;
  202: 
  203:   SET_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE);
  204: 
  205:   for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
  206:       ospf6_neighbor_delete (on);
  207: 
  208:   list_delete_all_node (oi->neighbor_list);
  209: 
  210:   ospf6_lsdb_remove_all (oi->lsdb);
  211:   ospf6_lsdb_remove_all (oi->lsupdate_list);
  212:   ospf6_lsdb_remove_all (oi->lsack_list);
  213: 
  214:   THREAD_OFF (oi->thread_send_hello);
  215:   THREAD_OFF (oi->thread_send_lsupdate);
  216:   THREAD_OFF (oi->thread_send_lsack);
  217: }
  218: 
  219: static struct in6_addr *
  220: ospf6_interface_get_linklocal_address (struct interface *ifp)
  221: {
  222:   struct listnode *n;
  223:   struct connected *c;
  224:   struct in6_addr *l = (struct in6_addr *) NULL;
  225: 
  226:   /* for each connected address */
  227:   for (ALL_LIST_ELEMENTS_RO (ifp->connected, n, c))
  228:     {
  229:       /* if family not AF_INET6, ignore */
  230:       if (c->address->family != AF_INET6)
  231:         continue;
  232: 
  233:       /* linklocal scope check */
  234:       if (IN6_IS_ADDR_LINKLOCAL (&c->address->u.prefix6))
  235:         l = &c->address->u.prefix6;
  236:     }
  237:   return l;
  238: }
  239: 
  240: void
  241: ospf6_interface_if_add (struct interface *ifp)
  242: {
  243:   struct ospf6_interface *oi;
  244:   unsigned int iobuflen;
  245: 
  246:   oi = (struct ospf6_interface *) ifp->info;
  247:   if (oi == NULL)
  248:     return;
  249: 
  250:   /* Try to adjust I/O buffer size with IfMtu */
  251:   if (oi->ifmtu == 0)
  252:     oi->ifmtu = ifp->mtu6;
  253:   iobuflen = ospf6_iobuf_size (ifp->mtu6);
  254:   if (oi->ifmtu > iobuflen)
  255:     {
  256:       if (IS_OSPF6_DEBUG_INTERFACE)
  257:         zlog_debug ("Interface %s: IfMtu is adjusted to I/O buffer size: %d.",
  258: 		    ifp->name, iobuflen);
  259:       oi->ifmtu = iobuflen;
  260:     }
  261: 
  262:   /* interface start */
  263:   if (oi->area)
  264:     thread_add_event (master, interface_up, oi, 0);
  265: }
  266: 
  267: void
  268: ospf6_interface_if_del (struct interface *ifp)
  269: {
  270:   struct ospf6_interface *oi;
  271: 
  272:   oi = (struct ospf6_interface *) ifp->info;
  273:   if (oi == NULL)
  274:     return;
  275: 
  276:   /* interface stop */
  277:   if (oi->area)
  278:     thread_execute (master, interface_down, oi, 0);
  279: 
  280:   listnode_delete (oi->area->if_list, oi);
  281:   oi->area = (struct ospf6_area *) NULL;
  282: 
  283:   /* cut link */
  284:   oi->interface = NULL;
  285:   ifp->info = NULL;
  286: 
  287:   ospf6_interface_delete (oi);
  288: }
  289: 
  290: void
  291: ospf6_interface_state_update (struct interface *ifp)
  292: {
  293:   struct ospf6_interface *oi;
  294: 
  295:   oi = (struct ospf6_interface *) ifp->info;
  296:   if (oi == NULL)
  297:     return;
  298:   if (oi->area == NULL)
  299:     return;
  300: 
  301:   if (if_is_up (ifp))
  302:     thread_add_event (master, interface_up, oi, 0);
  303:   else
  304:     thread_add_event (master, interface_down, oi, 0);
  305: 
  306:   return;
  307: }
  308: 
  309: void
  310: ospf6_interface_connected_route_update (struct interface *ifp)
  311: {
  312:   struct ospf6_interface *oi;
  313:   struct ospf6_route *route;
  314:   struct connected *c;
  315:   struct listnode *node, *nnode;
  316: 
  317:   oi = (struct ospf6_interface *) ifp->info;
  318:   if (oi == NULL)
  319:     return;
  320: 
  321:   /* reset linklocal pointer */
  322:   oi->linklocal_addr = ospf6_interface_get_linklocal_address (ifp);
  323: 
  324:   /* if area is null, do not make connected-route list */
  325:   if (oi->area == NULL)
  326:     return;
  327: 
  328:   /* update "route to advertise" interface route table */
  329:   ospf6_route_remove_all (oi->route_connected);
  330: 
  331:   for (ALL_LIST_ELEMENTS (oi->interface->connected, node, nnode, c))
  332:     {
  333:       if (c->address->family != AF_INET6)
  334:         continue;
  335: 
  336:       CONTINUE_IF_ADDRESS_LINKLOCAL (IS_OSPF6_DEBUG_INTERFACE, c->address);
  337:       CONTINUE_IF_ADDRESS_UNSPECIFIED (IS_OSPF6_DEBUG_INTERFACE, c->address);
  338:       CONTINUE_IF_ADDRESS_LOOPBACK (IS_OSPF6_DEBUG_INTERFACE, c->address);
  339:       CONTINUE_IF_ADDRESS_V4COMPAT (IS_OSPF6_DEBUG_INTERFACE, c->address);
  340:       CONTINUE_IF_ADDRESS_V4MAPPED (IS_OSPF6_DEBUG_INTERFACE, c->address);
  341: 
  342:       /* apply filter */
  343:       if (oi->plist_name)
  344:         {
  345:           struct prefix_list *plist;
  346:           enum prefix_list_type ret;
  347:           char buf[128];
  348: 
  349:           prefix2str (c->address, buf, sizeof (buf));
  350:           plist = prefix_list_lookup (AFI_IP6, oi->plist_name);
  351:           ret = prefix_list_apply (plist, (void *) c->address);
  352:           if (ret == PREFIX_DENY)
  353:             {
  354:               if (IS_OSPF6_DEBUG_INTERFACE)
  355:                 zlog_debug ("%s on %s filtered by prefix-list %s ",
  356: 			    buf, oi->interface->name, oi->plist_name);
  357:               continue;
  358:             }
  359:         }
  360: 
  361:       route = ospf6_route_create ();
  362:       memcpy (&route->prefix, c->address, sizeof (struct prefix));
  363:       apply_mask (&route->prefix);
  364:       route->type = OSPF6_DEST_TYPE_NETWORK;
  365:       route->path.area_id = oi->area->area_id;
  366:       route->path.type = OSPF6_PATH_TYPE_INTRA;
  367:       route->path.cost = oi->cost;
  368:       route->nexthop[0].ifindex = oi->interface->ifindex;
  369:       inet_pton (AF_INET6, "::1", &route->nexthop[0].address);
  370:       ospf6_route_add (route, oi->route_connected);
  371:     }
  372: 
  373:   /* create new Link-LSA */
  374:   OSPF6_LINK_LSA_SCHEDULE (oi);
  375:   OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);
  376:   OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area);
  377: }
  378: 
  379: static void
  380: ospf6_interface_state_change (u_char next_state, struct ospf6_interface *oi)
  381: {
  382:   u_char prev_state;
  383: 
  384:   prev_state = oi->state;
  385:   oi->state = next_state;
  386: 
  387:   if (prev_state == next_state)
  388:     return;
  389: 
  390:   /* log */
  391:   if (IS_OSPF6_DEBUG_INTERFACE)
  392:     {
  393:       zlog_debug ("Interface state change %s: %s -> %s", oi->interface->name,
  394: 		  ospf6_interface_state_str[prev_state],
  395: 		  ospf6_interface_state_str[next_state]);
  396:     }
  397:   oi->state_change++;
  398: 
  399:   if ((prev_state == OSPF6_INTERFACE_DR ||
  400:        prev_state == OSPF6_INTERFACE_BDR) &&
  401:       (next_state != OSPF6_INTERFACE_DR &&
  402:        next_state != OSPF6_INTERFACE_BDR))
  403:     ospf6_sso (oi->interface->ifindex, &alldrouters6, IPV6_LEAVE_GROUP);
  404:   if ((prev_state != OSPF6_INTERFACE_DR &&
  405:        prev_state != OSPF6_INTERFACE_BDR) &&
  406:       (next_state == OSPF6_INTERFACE_DR ||
  407:        next_state == OSPF6_INTERFACE_BDR))
  408:     ospf6_sso (oi->interface->ifindex, &alldrouters6, IPV6_JOIN_GROUP);
  409: 
  410:   OSPF6_ROUTER_LSA_SCHEDULE (oi->area);
  411:   if (next_state == OSPF6_INTERFACE_DOWN)
  412:     {
  413:       OSPF6_NETWORK_LSA_EXECUTE (oi);
  414:       OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT (oi);
  415:       OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area);
  416:     }
  417:   else if (prev_state == OSPF6_INTERFACE_DR ||
  418:            next_state == OSPF6_INTERFACE_DR)
  419:     {
  420:       OSPF6_NETWORK_LSA_SCHEDULE (oi);
  421:       OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);
  422:       OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area);
  423:     }
  424: 
  425: #ifdef HAVE_SNMP
  426:   /* Terminal state or regression */ 
  427:   if ((next_state == OSPF6_INTERFACE_POINTTOPOINT) ||
  428:       (next_state == OSPF6_INTERFACE_DROTHER) ||
  429:       (next_state == OSPF6_INTERFACE_BDR) ||
  430:       (next_state == OSPF6_INTERFACE_DR) ||
  431:       (next_state < prev_state))
  432:     ospf6TrapIfStateChange (oi);
  433: #endif
  434: 
  435: }
  436: 
  437: 
  438: /* DR Election, RFC2328 section 9.4 */
  439: 
  440: #define IS_ELIGIBLE(n) \
  441:   ((n)->state >= OSPF6_NEIGHBOR_TWOWAY && (n)->priority != 0)
  442: 
  443: static struct ospf6_neighbor *
  444: better_bdrouter (struct ospf6_neighbor *a, struct ospf6_neighbor *b)
  445: {
  446:   if ((a == NULL || ! IS_ELIGIBLE (a) || a->drouter == a->router_id) &&
  447:       (b == NULL || ! IS_ELIGIBLE (b) || b->drouter == b->router_id))
  448:     return NULL;
  449:   else if (a == NULL || ! IS_ELIGIBLE (a) || a->drouter == a->router_id)
  450:     return b;
  451:   else if (b == NULL || ! IS_ELIGIBLE (b) || b->drouter == b->router_id)
  452:     return a;
  453: 
  454:   if (a->bdrouter == a->router_id && b->bdrouter != b->router_id)
  455:     return a;
  456:   if (a->bdrouter != a->router_id && b->bdrouter == b->router_id)
  457:     return b;
  458: 
  459:   if (a->priority > b->priority)
  460:     return a;
  461:   if (a->priority < b->priority)
  462:     return b;
  463: 
  464:   if (ntohl (a->router_id) > ntohl (b->router_id))
  465:     return a;
  466:   if (ntohl (a->router_id) < ntohl (b->router_id))
  467:     return b;
  468: 
  469:   zlog_warn ("Router-ID duplicate ?");
  470:   return a;
  471: }
  472: 
  473: static struct ospf6_neighbor *
  474: better_drouter (struct ospf6_neighbor *a, struct ospf6_neighbor *b)
  475: {
  476:   if ((a == NULL || ! IS_ELIGIBLE (a) || a->drouter != a->router_id) &&
  477:       (b == NULL || ! IS_ELIGIBLE (b) || b->drouter != b->router_id))
  478:     return NULL;
  479:   else if (a == NULL || ! IS_ELIGIBLE (a) || a->drouter != a->router_id)
  480:     return b;
  481:   else if (b == NULL || ! IS_ELIGIBLE (b) || b->drouter != b->router_id)
  482:     return a;
  483: 
  484:   if (a->drouter == a->router_id && b->drouter != b->router_id)
  485:     return a;
  486:   if (a->drouter != a->router_id && b->drouter == b->router_id)
  487:     return b;
  488: 
  489:   if (a->priority > b->priority)
  490:     return a;
  491:   if (a->priority < b->priority)
  492:     return b;
  493: 
  494:   if (ntohl (a->router_id) > ntohl (b->router_id))
  495:     return a;
  496:   if (ntohl (a->router_id) < ntohl (b->router_id))
  497:     return b;
  498: 
  499:   zlog_warn ("Router-ID duplicate ?");
  500:   return a;
  501: }
  502: 
  503: static u_char
  504: dr_election (struct ospf6_interface *oi)
  505: {
  506:   struct listnode *node, *nnode;
  507:   struct ospf6_neighbor *on, *drouter, *bdrouter, myself;
  508:   struct ospf6_neighbor *best_drouter, *best_bdrouter;
  509:   u_char next_state = 0;
  510: 
  511:   drouter = bdrouter = NULL;
  512:   best_drouter = best_bdrouter = NULL;
  513: 
  514:   /* pseudo neighbor myself, including noting current DR/BDR (1) */
  515:   memset (&myself, 0, sizeof (myself));
  516:   inet_ntop (AF_INET, &oi->area->ospf6->router_id, myself.name,
  517:              sizeof (myself.name));
  518:   myself.state = OSPF6_NEIGHBOR_TWOWAY;
  519:   myself.drouter = oi->drouter;
  520:   myself.bdrouter = oi->bdrouter;
  521:   myself.priority = oi->priority;
  522:   myself.router_id = oi->area->ospf6->router_id;
  523: 
  524:   /* Electing BDR (2) */
  525:   for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
  526:     bdrouter = better_bdrouter (bdrouter, on);
  527:   
  528:   best_bdrouter = bdrouter;
  529:   bdrouter = better_bdrouter (best_bdrouter, &myself);
  530: 
  531:   /* Electing DR (3) */
  532:   for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
  533:     drouter = better_drouter (drouter, on);
  534: 
  535:   best_drouter = drouter;
  536:   drouter = better_drouter (best_drouter, &myself);
  537:   if (drouter == NULL)
  538:     drouter = bdrouter;
  539: 
  540:   /* the router itself is newly/no longer DR/BDR (4) */
  541:   if ((drouter == &myself && myself.drouter != myself.router_id) ||
  542:       (drouter != &myself && myself.drouter == myself.router_id) ||
  543:       (bdrouter == &myself && myself.bdrouter != myself.router_id) ||
  544:       (bdrouter != &myself && myself.bdrouter == myself.router_id))
  545:     {
  546:       myself.drouter = (drouter ? drouter->router_id : htonl (0));
  547:       myself.bdrouter = (bdrouter ? bdrouter->router_id : htonl (0));
  548: 
  549:       /* compatible to Electing BDR (2) */
  550:       bdrouter = better_bdrouter (best_bdrouter, &myself);
  551: 
  552:       /* compatible to Electing DR (3) */
  553:       drouter = better_drouter (best_drouter, &myself);
  554:       if (drouter == NULL)
  555:         drouter = bdrouter;
  556:     }
  557: 
  558:   /* Set interface state accordingly (5) */
  559:   if (drouter && drouter == &myself)
  560:     next_state = OSPF6_INTERFACE_DR;
  561:   else if (bdrouter && bdrouter == &myself)
  562:     next_state = OSPF6_INTERFACE_BDR;
  563:   else
  564:     next_state = OSPF6_INTERFACE_DROTHER;
  565: 
  566:   /* If NBMA, schedule Start for each neighbor having priority of 0 (6) */
  567:   /* XXX */
  568: 
  569:   /* If DR or BDR change, invoke AdjOK? for each neighbor (7) */
  570:   /* RFC 2328 section 12.4. Originating LSAs (3) will be handled
  571:      accordingly after AdjOK */
  572:   if (oi->drouter != (drouter ? drouter->router_id : htonl (0)) ||
  573:       oi->bdrouter != (bdrouter ? bdrouter->router_id : htonl (0)))
  574:     {
  575:       if (IS_OSPF6_DEBUG_INTERFACE)
  576:         zlog_debug ("DR Election on %s: DR: %s BDR: %s", oi->interface->name,
  577: 		    (drouter ? drouter->name : "0.0.0.0"),
  578: 		    (bdrouter ? bdrouter->name : "0.0.0.0"));
  579: 
  580:       for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, node, on))
  581:         {
  582:           if (on->state < OSPF6_NEIGHBOR_TWOWAY)
  583:             continue;
  584:           /* Schedule AdjOK. */
  585:           thread_add_event (master, adj_ok, on, 0);
  586:         }
  587:     }
  588: 
  589:   oi->drouter = (drouter ? drouter->router_id : htonl (0));
  590:   oi->bdrouter = (bdrouter ? bdrouter->router_id : htonl (0));
  591:   return next_state;
  592: }
  593: 
  594: 
  595: /* Interface State Machine */
  596: int
  597: interface_up (struct thread *thread)
  598: {
  599:   struct ospf6_interface *oi;
  600: 
  601:   oi = (struct ospf6_interface *) THREAD_ARG (thread);
  602:   assert (oi && oi->interface);
  603: 
  604:   if (IS_OSPF6_DEBUG_INTERFACE)
  605:     zlog_debug ("Interface Event %s: [InterfaceUp]",
  606: 		oi->interface->name);
  607: 
  608:   /* check physical interface is up */
  609:   if (! if_is_up (oi->interface))
  610:     {
  611:       if (IS_OSPF6_DEBUG_INTERFACE)
  612:         zlog_debug ("Interface %s is down, can't execute [InterfaceUp]",
  613: 		    oi->interface->name);
  614:       return 0;
  615:     }
  616: 
  617:   /* if already enabled, do nothing */
  618:   if (oi->state > OSPF6_INTERFACE_DOWN)
  619:     {
  620:       if (IS_OSPF6_DEBUG_INTERFACE)
  621:         zlog_debug ("Interface %s already enabled",
  622: 		    oi->interface->name);
  623:       return 0;
  624:     }
  625: 
  626:   /* Join AllSPFRouters */
  627:   ospf6_sso (oi->interface->ifindex, &allspfrouters6, IPV6_JOIN_GROUP);
  628: 
  629:   /* Update interface route */
  630:   ospf6_interface_connected_route_update (oi->interface);
  631: 
  632:   /* Schedule Hello */
  633:   if (! CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
  634:     thread_add_event (master, ospf6_hello_send, oi, 0);
  635: 
  636:   /* decide next interface state */
  637:   if (if_is_pointopoint (oi->interface))
  638:     ospf6_interface_state_change (OSPF6_INTERFACE_POINTTOPOINT, oi);
  639:   else if (oi->priority == 0)
  640:     ospf6_interface_state_change (OSPF6_INTERFACE_DROTHER, oi);
  641:   else
  642:     {
  643:       ospf6_interface_state_change (OSPF6_INTERFACE_WAITING, oi);
  644:       thread_add_timer (master, wait_timer, oi, oi->dead_interval);
  645:     }
  646: 
  647:   return 0;
  648: }
  649: 
  650: int
  651: wait_timer (struct thread *thread)
  652: {
  653:   struct ospf6_interface *oi;
  654: 
  655:   oi = (struct ospf6_interface *) THREAD_ARG (thread);
  656:   assert (oi && oi->interface);
  657: 
  658:   if (IS_OSPF6_DEBUG_INTERFACE)
  659:     zlog_debug ("Interface Event %s: [WaitTimer]",
  660: 		oi->interface->name);
  661: 
  662:   if (oi->state == OSPF6_INTERFACE_WAITING)
  663:     ospf6_interface_state_change (dr_election (oi), oi);
  664: 
  665:   return 0;
  666: }
  667: 
  668: int
  669: backup_seen (struct thread *thread)
  670: {
  671:   struct ospf6_interface *oi;
  672: 
  673:   oi = (struct ospf6_interface *) THREAD_ARG (thread);
  674:   assert (oi && oi->interface);
  675: 
  676:   if (IS_OSPF6_DEBUG_INTERFACE)
  677:     zlog_debug ("Interface Event %s: [BackupSeen]",
  678: 		oi->interface->name);
  679: 
  680:   if (oi->state == OSPF6_INTERFACE_WAITING)
  681:     ospf6_interface_state_change (dr_election (oi), oi);
  682: 
  683:   return 0;
  684: }
  685: 
  686: int
  687: neighbor_change (struct thread *thread)
  688: {
  689:   struct ospf6_interface *oi;
  690: 
  691:   oi = (struct ospf6_interface *) THREAD_ARG (thread);
  692:   assert (oi && oi->interface);
  693: 
  694:   if (IS_OSPF6_DEBUG_INTERFACE)
  695:     zlog_debug ("Interface Event %s: [NeighborChange]",
  696: 		oi->interface->name);
  697: 
  698:   if (oi->state == OSPF6_INTERFACE_DROTHER ||
  699:       oi->state == OSPF6_INTERFACE_BDR ||
  700:       oi->state == OSPF6_INTERFACE_DR)
  701:     ospf6_interface_state_change (dr_election (oi), oi);
  702: 
  703:   return 0;
  704: }
  705: 
  706: int
  707: interface_down (struct thread *thread)
  708: {
  709:   struct ospf6_interface *oi;
  710:   struct listnode *node, *nnode;
  711:   struct ospf6_neighbor *on;
  712: 
  713:   oi = (struct ospf6_interface *) THREAD_ARG (thread);
  714:   assert (oi && oi->interface);
  715: 
  716:   if (IS_OSPF6_DEBUG_INTERFACE)
  717:     zlog_debug ("Interface Event %s: [InterfaceDown]",
  718: 		oi->interface->name);
  719: 
  720:   /* Leave AllSPFRouters */
  721:   if (oi->state > OSPF6_INTERFACE_DOWN)
  722:     ospf6_sso (oi->interface->ifindex, &allspfrouters6, IPV6_LEAVE_GROUP);
  723: 
  724:   ospf6_interface_state_change (OSPF6_INTERFACE_DOWN, oi);
  725: 
  726:   for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
  727:     ospf6_neighbor_delete (on);
  728:   
  729:   list_delete_all_node (oi->neighbor_list);
  730: 
  731:   return 0;
  732: }
  733: 
  734: 
  735: /* show specified interface structure */
  736: static int
  737: ospf6_interface_show (struct vty *vty, struct interface *ifp)
  738: {
  739:   struct ospf6_interface *oi;
  740:   struct connected *c;
  741:   struct prefix *p;
  742:   struct listnode *i;
  743:   char strbuf[64], drouter[32], bdrouter[32];
  744:   const char *updown[3] = {"down", "up", NULL};
  745:   const char *type;
  746:   struct timeval res, now;
  747:   char duration[32];
  748:   struct ospf6_lsa *lsa;
  749: 
  750:   /* check physical interface type */
  751:   if (if_is_loopback (ifp))
  752:     type = "LOOPBACK";
  753:   else if (if_is_broadcast (ifp))
  754:     type = "BROADCAST";
  755:   else if (if_is_pointopoint (ifp))
  756:     type = "POINTOPOINT";
  757:   else
  758:     type = "UNKNOWN";
  759: 
  760:   vty_out (vty, "%s is %s, type %s%s",
  761:            ifp->name, updown[if_is_up (ifp)], type,
  762: 	   VNL);
  763:   vty_out (vty, "  Interface ID: %d%s", ifp->ifindex, VNL);
  764: 
  765:   if (ifp->info == NULL)
  766:     {
  767:       vty_out (vty, "   OSPF not enabled on this interface%s", VNL);
  768:       return 0;
  769:     }
  770:   else
  771:     oi = (struct ospf6_interface *) ifp->info;
  772: 
  773:   vty_out (vty, "  Internet Address:%s", VNL);
  774: 
  775:   for (ALL_LIST_ELEMENTS_RO (ifp->connected, i, c))
  776:     {
  777:       p = c->address;
  778:       prefix2str (p, strbuf, sizeof (strbuf));
  779:       switch (p->family)
  780:         {
  781:         case AF_INET:
  782:           vty_out (vty, "    inet : %s%s", strbuf,
  783: 		   VNL);
  784:           break;
  785:         case AF_INET6:
  786:           vty_out (vty, "    inet6: %s%s", strbuf,
  787: 		   VNL);
  788:           break;
  789:         default:
  790:           vty_out (vty, "    ???  : %s%s", strbuf,
  791: 		   VNL);
  792:           break;
  793:         }
  794:     }
  795: 
  796:   if (oi->area)
  797:     {
  798:       vty_out (vty, "  Instance ID %d, Interface MTU %d (autodetect: %d)%s",
  799: 	       oi->instance_id, oi->ifmtu, ifp->mtu6, VNL);
  800:       vty_out (vty, "  MTU mismatch detection: %s%s", oi->mtu_ignore ?
  801: 	       "disabled" : "enabled", VNL);
  802:       inet_ntop (AF_INET, &oi->area->area_id,
  803:                  strbuf, sizeof (strbuf));
  804:       vty_out (vty, "  Area ID %s, Cost %hu%s", strbuf, oi->cost,
  805: 	       VNL);
  806:     }
  807:   else
  808:     vty_out (vty, "  Not Attached to Area%s", VNL);
  809: 
  810:   vty_out (vty, "  State %s, Transmit Delay %d sec, Priority %d%s",
  811:            ospf6_interface_state_str[oi->state],
  812:            oi->transdelay, oi->priority,
  813: 	   VNL);
  814:   vty_out (vty, "  Timer intervals configured:%s", VNL);
  815:   vty_out (vty, "   Hello %d, Dead %d, Retransmit %d%s",
  816:            oi->hello_interval, oi->dead_interval, oi->rxmt_interval,
  817: 	   VNL);
  818: 
  819:   inet_ntop (AF_INET, &oi->drouter, drouter, sizeof (drouter));
  820:   inet_ntop (AF_INET, &oi->bdrouter, bdrouter, sizeof (bdrouter));
  821:   vty_out (vty, "  DR: %s BDR: %s%s", drouter, bdrouter, VNL);
  822: 
  823:   vty_out (vty, "  Number of I/F scoped LSAs is %u%s",
  824:            oi->lsdb->count, VNL);
  825: 
  826:   quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
  827: 
  828:   timerclear (&res);
  829:   if (oi->thread_send_lsupdate)
  830:     timersub (&oi->thread_send_lsupdate->u.sands, &now, &res);
  831:   timerstring (&res, duration, sizeof (duration));
  832:   vty_out (vty, "    %d Pending LSAs for LSUpdate in Time %s [thread %s]%s",
  833:            oi->lsupdate_list->count, duration,
  834:            (oi->thread_send_lsupdate ? "on" : "off"),
  835:            VNL);
  836:   for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
  837:        lsa = ospf6_lsdb_next (lsa))
  838:     vty_out (vty, "      %s%s", lsa->name, VNL);
  839: 
  840:   timerclear (&res);
  841:   if (oi->thread_send_lsack)
  842:     timersub (&oi->thread_send_lsack->u.sands, &now, &res);
  843:   timerstring (&res, duration, sizeof (duration));
  844:   vty_out (vty, "    %d Pending LSAs for LSAck in Time %s [thread %s]%s",
  845:            oi->lsack_list->count, duration,
  846:            (oi->thread_send_lsack ? "on" : "off"),
  847:            VNL);
  848:   for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
  849:        lsa = ospf6_lsdb_next (lsa))
  850:     vty_out (vty, "      %s%s", lsa->name, VNL);
  851: 
  852:   return 0;
  853: }
  854: 
  855: /* show interface */
  856: DEFUN (show_ipv6_ospf6_interface,
  857:        show_ipv6_ospf6_interface_ifname_cmd,
  858:        "show ipv6 ospf6 interface IFNAME",
  859:        SHOW_STR
  860:        IP6_STR
  861:        OSPF6_STR
  862:        INTERFACE_STR
  863:        IFNAME_STR
  864:        )
  865: {
  866:   struct interface *ifp;
  867:   struct listnode *i;
  868: 
  869:   if (argc)
  870:     {
  871:       ifp = if_lookup_by_name (argv[0]);
  872:       if (ifp == NULL)
  873:         {
  874:           vty_out (vty, "No such Interface: %s%s", argv[0],
  875:                    VNL);
  876:           return CMD_WARNING;
  877:         }
  878:       ospf6_interface_show (vty, ifp);
  879:     }
  880:   else
  881:     {
  882:       for (ALL_LIST_ELEMENTS_RO (iflist, i, ifp))
  883:         ospf6_interface_show (vty, ifp);
  884:     }
  885: 
  886:   return CMD_SUCCESS;
  887: }
  888: 
  889: ALIAS (show_ipv6_ospf6_interface,
  890:        show_ipv6_ospf6_interface_cmd,
  891:        "show ipv6 ospf6 interface",
  892:        SHOW_STR
  893:        IP6_STR
  894:        OSPF6_STR
  895:        INTERFACE_STR
  896:        )
  897: 
  898: DEFUN (show_ipv6_ospf6_interface_ifname_prefix,
  899:        show_ipv6_ospf6_interface_ifname_prefix_cmd,
  900:        "show ipv6 ospf6 interface IFNAME prefix",
  901:        SHOW_STR
  902:        IP6_STR
  903:        OSPF6_STR
  904:        INTERFACE_STR
  905:        IFNAME_STR
  906:        "Display connected prefixes to advertise\n"
  907:        )
  908: {
  909:   struct interface *ifp;
  910:   struct ospf6_interface *oi;
  911: 
  912:   ifp = if_lookup_by_name (argv[0]);
  913:   if (ifp == NULL)
  914:     {
  915:       vty_out (vty, "No such Interface: %s%s", argv[0], VNL);
  916:       return CMD_WARNING;
  917:     }
  918: 
  919:   oi = ifp->info;
  920:   if (oi == NULL)
  921:     {
  922:       vty_out (vty, "OSPFv3 is not enabled on %s%s", argv[0], VNL);
  923:       return CMD_WARNING;
  924:     }
  925: 
  926:   argc--;
  927:   argv++;
  928:   ospf6_route_table_show (vty, argc, argv, oi->route_connected);
  929: 
  930:   return CMD_SUCCESS;
  931: }
  932: 
  933: ALIAS (show_ipv6_ospf6_interface_ifname_prefix,
  934:        show_ipv6_ospf6_interface_ifname_prefix_detail_cmd,
  935:        "show ipv6 ospf6 interface IFNAME prefix (X:X::X:X|X:X::X:X/M|detail)",
  936:        SHOW_STR
  937:        IP6_STR
  938:        OSPF6_STR
  939:        INTERFACE_STR
  940:        IFNAME_STR
  941:        "Display connected prefixes to advertise\n"
  942:        OSPF6_ROUTE_ADDRESS_STR
  943:        OSPF6_ROUTE_PREFIX_STR
  944:        "Display details of the prefixes\n"
  945:        )
  946: 
  947: ALIAS (show_ipv6_ospf6_interface_ifname_prefix,
  948:        show_ipv6_ospf6_interface_ifname_prefix_match_cmd,
  949:        "show ipv6 ospf6 interface IFNAME prefix X:X::X:X/M (match|detail)",
  950:        SHOW_STR
  951:        IP6_STR
  952:        OSPF6_STR
  953:        INTERFACE_STR
  954:        IFNAME_STR
  955:        "Display connected prefixes to advertise\n"
  956:        OSPF6_ROUTE_PREFIX_STR
  957:        OSPF6_ROUTE_MATCH_STR
  958:        "Display details of the prefixes\n"
  959:        )
  960: 
  961: DEFUN (show_ipv6_ospf6_interface_prefix,
  962:        show_ipv6_ospf6_interface_prefix_cmd,
  963:        "show ipv6 ospf6 interface prefix",
  964:        SHOW_STR
  965:        IP6_STR
  966:        OSPF6_STR
  967:        INTERFACE_STR
  968:        "Display connected prefixes to advertise\n"
  969:        )
  970: {
  971:   struct listnode *i;
  972:   struct ospf6_interface *oi;
  973:   struct interface *ifp;
  974: 
  975:   for (ALL_LIST_ELEMENTS_RO (iflist, i, ifp))
  976:     {
  977:       oi = (struct ospf6_interface *) ifp->info;
  978:       if (oi == NULL)
  979:         continue;
  980: 
  981:       ospf6_route_table_show (vty, argc, argv, oi->route_connected);
  982:     }
  983: 
  984:   return CMD_SUCCESS;
  985: }
  986: 
  987: ALIAS (show_ipv6_ospf6_interface_prefix,
  988:        show_ipv6_ospf6_interface_prefix_detail_cmd,
  989:        "show ipv6 ospf6 interface prefix (X:X::X:X|X:X::X:X/M|detail)",
  990:        SHOW_STR
  991:        IP6_STR
  992:        OSPF6_STR
  993:        INTERFACE_STR
  994:        "Display connected prefixes to advertise\n"
  995:        OSPF6_ROUTE_ADDRESS_STR
  996:        OSPF6_ROUTE_PREFIX_STR
  997:        "Display details of the prefixes\n"
  998:        )
  999: 
 1000: ALIAS (show_ipv6_ospf6_interface_prefix,
 1001:        show_ipv6_ospf6_interface_prefix_match_cmd,
 1002:        "show ipv6 ospf6 interface prefix X:X::X:X/M (match|detail)",
 1003:        SHOW_STR
 1004:        IP6_STR
 1005:        OSPF6_STR
 1006:        INTERFACE_STR
 1007:        "Display connected prefixes to advertise\n"
 1008:        OSPF6_ROUTE_PREFIX_STR
 1009:        OSPF6_ROUTE_MATCH_STR
 1010:        "Display details of the prefixes\n"
 1011:        )
 1012: 
 1013: 
 1014: /* interface variable set command */
 1015: DEFUN (ipv6_ospf6_ifmtu,
 1016:        ipv6_ospf6_ifmtu_cmd,
 1017:        "ipv6 ospf6 ifmtu <1-65535>",
 1018:        IP6_STR
 1019:        OSPF6_STR
 1020:        "Interface MTU\n"
 1021:        "OSPFv3 Interface MTU\n"
 1022:        )
 1023: {
 1024:   struct ospf6_interface *oi;
 1025:   struct interface *ifp;
 1026:   unsigned int ifmtu, iobuflen;
 1027:   struct listnode *node, *nnode;
 1028:   struct ospf6_neighbor *on;
 1029: 
 1030:   ifp = (struct interface *) vty->index;
 1031:   assert (ifp);
 1032: 
 1033:   oi = (struct ospf6_interface *) ifp->info;
 1034:   if (oi == NULL)
 1035:     oi = ospf6_interface_create (ifp);
 1036:   assert (oi);
 1037: 
 1038:   ifmtu = strtol (argv[0], NULL, 10);
 1039: 
 1040:   if (oi->ifmtu == ifmtu)
 1041:     return CMD_SUCCESS;
 1042: 
 1043:   if (ifp->mtu6 != 0 && ifp->mtu6 < ifmtu)
 1044:     {
 1045:       vty_out (vty, "%s's ospf6 ifmtu cannot go beyond physical mtu (%d)%s",
 1046:                ifp->name, ifp->mtu6, VNL);
 1047:       return CMD_WARNING;
 1048:     }
 1049: 
 1050:   if (oi->ifmtu < ifmtu)
 1051:     {
 1052:       iobuflen = ospf6_iobuf_size (ifmtu);
 1053:       if (iobuflen < ifmtu)
 1054:         {
 1055:           vty_out (vty, "%s's ifmtu is adjusted to I/O buffer size (%d).%s",
 1056:                    ifp->name, iobuflen, VNL);
 1057:           oi->ifmtu = iobuflen;
 1058:         }
 1059:       else
 1060:         oi->ifmtu = ifmtu;
 1061:     }
 1062:   else
 1063:     oi->ifmtu = ifmtu;
 1064: 
 1065:   /* re-establish adjacencies */
 1066:   for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
 1067:     {
 1068:       THREAD_OFF (on->inactivity_timer);
 1069:       thread_add_event (master, inactivity_timer, on, 0);
 1070:     }
 1071: 
 1072:   return CMD_SUCCESS;
 1073: }
 1074: 
 1075: DEFUN (no_ipv6_ospf6_ifmtu,
 1076:        no_ipv6_ospf6_ifmtu_cmd,
 1077:        "no ipv6 ospf6 ifmtu",
 1078:        NO_STR
 1079:        IP6_STR
 1080:        OSPF6_STR
 1081:        "Interface MTU\n"
 1082:        )
 1083: {
 1084:   struct ospf6_interface *oi;
 1085:   struct interface *ifp;
 1086:   unsigned int iobuflen;
 1087:   struct listnode *node, *nnode;
 1088:   struct ospf6_neighbor *on;
 1089: 
 1090:   ifp = (struct interface *) vty->index;
 1091:   assert (ifp);
 1092: 
 1093:   oi = (struct ospf6_interface *) ifp->info;
 1094:   if (oi == NULL)
 1095:     oi = ospf6_interface_create (ifp);
 1096:   assert (oi);
 1097: 
 1098:   if (oi->ifmtu < ifp->mtu)
 1099:     {
 1100:       iobuflen = ospf6_iobuf_size (ifp->mtu);
 1101:       if (iobuflen < ifp->mtu)
 1102:         {
 1103:           vty_out (vty, "%s's ifmtu is adjusted to I/O buffer size (%d).%s",
 1104:                    ifp->name, iobuflen, VNL);
 1105:           oi->ifmtu = iobuflen;
 1106:         }
 1107:       else
 1108:         oi->ifmtu = ifp->mtu;
 1109:     }
 1110:   else
 1111:     oi->ifmtu = ifp->mtu;
 1112: 
 1113:   /* re-establish adjacencies */
 1114:   for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
 1115:     {
 1116:       THREAD_OFF (on->inactivity_timer);
 1117:       thread_add_event (master, inactivity_timer, on, 0);
 1118:     }
 1119: 
 1120:   return CMD_SUCCESS;
 1121: }
 1122: 
 1123: DEFUN (ipv6_ospf6_cost,
 1124:        ipv6_ospf6_cost_cmd,
 1125:        "ipv6 ospf6 cost <1-65535>",
 1126:        IP6_STR
 1127:        OSPF6_STR
 1128:        "Interface cost\n"
 1129:        "Outgoing metric of this interface\n"
 1130:        )
 1131: {
 1132:   struct ospf6_interface *oi;
 1133:   struct interface *ifp;
 1134:   unsigned long int lcost;
 1135: 
 1136:   ifp = (struct interface *) vty->index;
 1137:   assert (ifp);
 1138: 
 1139:   oi = (struct ospf6_interface *) ifp->info;
 1140:   if (oi == NULL)
 1141:     oi = ospf6_interface_create (ifp);
 1142:   assert (oi);
 1143: 
 1144:   lcost = strtol (argv[0], NULL, 10);
 1145: 
 1146:   if (lcost > UINT32_MAX)
 1147:     {
 1148:       vty_out (vty, "Cost %ld is out of range%s", lcost, VNL);
 1149:       return CMD_WARNING;
 1150:     }
 1151:   
 1152:   if (oi->cost == lcost)
 1153:     return CMD_SUCCESS;
 1154:   
 1155:   oi->cost = lcost;
 1156:   
 1157:   /* update cost held in route_connected list in ospf6_interface */
 1158:   ospf6_interface_connected_route_update (oi->interface);
 1159: 
 1160:   /* execute LSA hooks */
 1161:   if (oi->area)
 1162:     {
 1163:       OSPF6_LINK_LSA_SCHEDULE (oi);
 1164:       OSPF6_ROUTER_LSA_SCHEDULE (oi->area);
 1165:       OSPF6_NETWORK_LSA_SCHEDULE (oi);
 1166:       OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);
 1167:       OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area);
 1168:     }
 1169: 
 1170:   return CMD_SUCCESS;
 1171: }
 1172: 
 1173: DEFUN (ipv6_ospf6_hellointerval,
 1174:        ipv6_ospf6_hellointerval_cmd,
 1175:        "ipv6 ospf6 hello-interval <1-65535>",
 1176:        IP6_STR
 1177:        OSPF6_STR
 1178:        "Interval time of Hello packets\n"
 1179:        SECONDS_STR
 1180:        )
 1181: {
 1182:   struct ospf6_interface *oi;
 1183:   struct interface *ifp;
 1184: 
 1185:   ifp = (struct interface *) vty->index;
 1186:   assert (ifp);
 1187: 
 1188:   oi = (struct ospf6_interface *) ifp->info;
 1189:   if (oi == NULL)
 1190:     oi = ospf6_interface_create (ifp);
 1191:   assert (oi);
 1192: 
 1193:   oi->hello_interval = strtol (argv[0], NULL, 10);
 1194:   return CMD_SUCCESS;
 1195: }
 1196: 
 1197: /* interface variable set command */
 1198: DEFUN (ipv6_ospf6_deadinterval,
 1199:        ipv6_ospf6_deadinterval_cmd,
 1200:        "ipv6 ospf6 dead-interval <1-65535>",
 1201:        IP6_STR
 1202:        OSPF6_STR
 1203:        "Interval time after which a neighbor is declared down\n"
 1204:        SECONDS_STR
 1205:        )
 1206: {
 1207:   struct ospf6_interface *oi;
 1208:   struct interface *ifp;
 1209: 
 1210:   ifp = (struct interface *) vty->index;
 1211:   assert (ifp);
 1212: 
 1213:   oi = (struct ospf6_interface *) ifp->info;
 1214:   if (oi == NULL)
 1215:     oi = ospf6_interface_create (ifp);
 1216:   assert (oi);
 1217: 
 1218:   oi->dead_interval = strtol (argv[0], NULL, 10);
 1219:   return CMD_SUCCESS;
 1220: }
 1221: 
 1222: /* interface variable set command */
 1223: DEFUN (ipv6_ospf6_transmitdelay,
 1224:        ipv6_ospf6_transmitdelay_cmd,
 1225:        "ipv6 ospf6 transmit-delay <1-3600>",
 1226:        IP6_STR
 1227:        OSPF6_STR
 1228:        "Transmit delay of this interface\n"
 1229:        SECONDS_STR
 1230:        )
 1231: {
 1232:   struct ospf6_interface *oi;
 1233:   struct interface *ifp;
 1234: 
 1235:   ifp = (struct interface *) vty->index;
 1236:   assert (ifp);
 1237: 
 1238:   oi = (struct ospf6_interface *) ifp->info;
 1239:   if (oi == NULL)
 1240:     oi = ospf6_interface_create (ifp);
 1241:   assert (oi);
 1242: 
 1243:   oi->transdelay = strtol (argv[0], NULL, 10);
 1244:   return CMD_SUCCESS;
 1245: }
 1246: 
 1247: /* interface variable set command */
 1248: DEFUN (ipv6_ospf6_retransmitinterval,
 1249:        ipv6_ospf6_retransmitinterval_cmd,
 1250:        "ipv6 ospf6 retransmit-interval <1-65535>",
 1251:        IP6_STR
 1252:        OSPF6_STR
 1253:        "Time between retransmitting lost link state advertisements\n"
 1254:        SECONDS_STR
 1255:        )
 1256: {
 1257:   struct ospf6_interface *oi;
 1258:   struct interface *ifp;
 1259: 
 1260:   ifp = (struct interface *) vty->index;
 1261:   assert (ifp);
 1262: 
 1263:   oi = (struct ospf6_interface *) ifp->info;
 1264:   if (oi == NULL)
 1265:     oi = ospf6_interface_create (ifp);
 1266:   assert (oi);
 1267: 
 1268:   oi->rxmt_interval = strtol (argv[0], NULL, 10);
 1269:   return CMD_SUCCESS;
 1270: }
 1271: 
 1272: /* interface variable set command */
 1273: DEFUN (ipv6_ospf6_priority,
 1274:        ipv6_ospf6_priority_cmd,
 1275:        "ipv6 ospf6 priority <0-255>",
 1276:        IP6_STR
 1277:        OSPF6_STR
 1278:        "Router priority\n"
 1279:        "Priority value\n"
 1280:        )
 1281: {
 1282:   struct ospf6_interface *oi;
 1283:   struct interface *ifp;
 1284: 
 1285:   ifp = (struct interface *) vty->index;
 1286:   assert (ifp);
 1287: 
 1288:   oi = (struct ospf6_interface *) ifp->info;
 1289:   if (oi == NULL)
 1290:     oi = ospf6_interface_create (ifp);
 1291:   assert (oi);
 1292: 
 1293:   oi->priority = strtol (argv[0], NULL, 10);
 1294: 
 1295:   if (oi->area)
 1296:     ospf6_interface_state_change (dr_election (oi), oi);
 1297: 
 1298:   return CMD_SUCCESS;
 1299: }
 1300: 
 1301: DEFUN (ipv6_ospf6_instance,
 1302:        ipv6_ospf6_instance_cmd,
 1303:        "ipv6 ospf6 instance-id <0-255>",
 1304:        IP6_STR
 1305:        OSPF6_STR
 1306:        "Instance ID for this interface\n"
 1307:        "Instance ID value\n"
 1308:        )
 1309: {
 1310:   struct ospf6_interface *oi;
 1311:   struct interface *ifp;
 1312: 
 1313:   ifp = (struct interface *)vty->index;
 1314:   assert (ifp);
 1315: 
 1316:   oi = (struct ospf6_interface *)ifp->info;
 1317:   if (oi == NULL)
 1318:     oi = ospf6_interface_create (ifp);
 1319:   assert (oi);
 1320: 
 1321:   oi->instance_id = strtol (argv[0], NULL, 10);
 1322:   return CMD_SUCCESS;
 1323: }
 1324: 
 1325: DEFUN (ipv6_ospf6_passive,
 1326:        ipv6_ospf6_passive_cmd,
 1327:        "ipv6 ospf6 passive",
 1328:        IP6_STR
 1329:        OSPF6_STR
 1330:        "passive interface, No adjacency will be formed on this interface\n"
 1331:        )
 1332: {
 1333:   struct ospf6_interface *oi;
 1334:   struct interface *ifp;
 1335:   struct listnode *node, *nnode;
 1336:   struct ospf6_neighbor *on;
 1337: 
 1338:   ifp = (struct interface *) vty->index;
 1339:   assert (ifp);
 1340: 
 1341:   oi = (struct ospf6_interface *) ifp->info;
 1342:   if (oi == NULL)
 1343:     oi = ospf6_interface_create (ifp);
 1344:   assert (oi);
 1345: 
 1346:   SET_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE);
 1347:   THREAD_OFF (oi->thread_send_hello);
 1348: 
 1349:   for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
 1350:     {
 1351:       THREAD_OFF (on->inactivity_timer);
 1352:       thread_add_event (master, inactivity_timer, on, 0);
 1353:     }
 1354: 
 1355:   return CMD_SUCCESS;
 1356: }
 1357: 
 1358: DEFUN (no_ipv6_ospf6_passive,
 1359:        no_ipv6_ospf6_passive_cmd,
 1360:        "no ipv6 ospf6 passive",
 1361:        NO_STR
 1362:        IP6_STR
 1363:        OSPF6_STR
 1364:        "passive interface: No Adjacency will be formed on this I/F\n"
 1365:        )
 1366: {
 1367:   struct ospf6_interface *oi;
 1368:   struct interface *ifp;
 1369: 
 1370:   ifp = (struct interface *) vty->index;
 1371:   assert (ifp);
 1372: 
 1373:   oi = (struct ospf6_interface *) ifp->info;
 1374:   if (oi == NULL)
 1375:     oi = ospf6_interface_create (ifp);
 1376:   assert (oi);
 1377: 
 1378:   UNSET_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE);
 1379:   THREAD_OFF (oi->thread_send_hello);
 1380:   oi->thread_send_hello =
 1381:     thread_add_event (master, ospf6_hello_send, oi, 0);
 1382: 
 1383:   return CMD_SUCCESS;
 1384: }
 1385: 
 1386: DEFUN (ipv6_ospf6_mtu_ignore,
 1387:        ipv6_ospf6_mtu_ignore_cmd,
 1388:        "ipv6 ospf6 mtu-ignore",
 1389:        IP6_STR
 1390:        OSPF6_STR
 1391:        "Ignore MTU mismatch on this interface\n"
 1392:        )
 1393: {
 1394:   struct ospf6_interface *oi;
 1395:   struct interface *ifp;
 1396: 
 1397:   ifp = (struct interface *) vty->index;
 1398:   assert (ifp);
 1399: 
 1400:   oi = (struct ospf6_interface *) ifp->info;
 1401:   if (oi == NULL)
 1402:     oi = ospf6_interface_create (ifp);
 1403:   assert (oi);
 1404: 
 1405:   oi->mtu_ignore = 1;
 1406: 
 1407:   return CMD_SUCCESS;
 1408: }
 1409: 
 1410: DEFUN (no_ipv6_ospf6_mtu_ignore,
 1411:        no_ipv6_ospf6_mtu_ignore_cmd,
 1412:        "no ipv6 ospf6 mtu-ignore",
 1413:        NO_STR
 1414:        IP6_STR
 1415:        OSPF6_STR
 1416:        "Ignore MTU mismatch on this interface\n"
 1417:        )
 1418: {
 1419:   struct ospf6_interface *oi;
 1420:   struct interface *ifp;
 1421: 
 1422:   ifp = (struct interface *) vty->index;
 1423:   assert (ifp);
 1424: 
 1425:   oi = (struct ospf6_interface *) ifp->info;
 1426:   if (oi == NULL)
 1427:     oi = ospf6_interface_create (ifp);
 1428:   assert (oi);
 1429: 
 1430:   oi->mtu_ignore = 0;
 1431: 
 1432:   return CMD_SUCCESS;
 1433: }
 1434: 
 1435: DEFUN (ipv6_ospf6_advertise_prefix_list,
 1436:        ipv6_ospf6_advertise_prefix_list_cmd,
 1437:        "ipv6 ospf6 advertise prefix-list WORD",
 1438:        IP6_STR
 1439:        OSPF6_STR
 1440:        "Advertising options\n"
 1441:        "Filter prefix using prefix-list\n"
 1442:        "Prefix list name\n"
 1443:        )
 1444: {
 1445:   struct ospf6_interface *oi;
 1446:   struct interface *ifp;
 1447: 
 1448:   ifp = (struct interface *) vty->index;
 1449:   assert (ifp);
 1450: 
 1451:   oi = (struct ospf6_interface *) ifp->info;
 1452:   if (oi == NULL)
 1453:     oi = ospf6_interface_create (ifp);
 1454:   assert (oi);
 1455: 
 1456:   if (oi->plist_name)
 1457:     XFREE (MTYPE_PREFIX_LIST_STR, oi->plist_name);
 1458:   oi->plist_name = XSTRDUP (MTYPE_PREFIX_LIST_STR, argv[0]);
 1459: 
 1460:   ospf6_interface_connected_route_update (oi->interface);
 1461: 
 1462:   if (oi->area)
 1463:     {
 1464:       OSPF6_LINK_LSA_SCHEDULE (oi);
 1465:       if (oi->state == OSPF6_INTERFACE_DR)
 1466:         {
 1467:           OSPF6_NETWORK_LSA_SCHEDULE (oi);
 1468:           OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);
 1469:         }
 1470:       OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area);
 1471:     }
 1472: 
 1473:   return CMD_SUCCESS;
 1474: }
 1475: 
 1476: DEFUN (no_ipv6_ospf6_advertise_prefix_list,
 1477:        no_ipv6_ospf6_advertise_prefix_list_cmd,
 1478:        "no ipv6 ospf6 advertise prefix-list",
 1479:        NO_STR
 1480:        IP6_STR
 1481:        OSPF6_STR
 1482:        "Advertising options\n"
 1483:        "Filter prefix using prefix-list\n"
 1484:        )
 1485: {
 1486:   struct ospf6_interface *oi;
 1487:   struct interface *ifp;
 1488: 
 1489:   ifp = (struct interface *) vty->index;
 1490:   assert (ifp);
 1491: 
 1492:   oi = (struct ospf6_interface *) ifp->info;
 1493:   if (oi == NULL)
 1494:     oi = ospf6_interface_create (ifp);
 1495:   assert (oi);
 1496: 
 1497:   if (oi->plist_name)
 1498:     {
 1499:       XFREE (MTYPE_PREFIX_LIST_STR, oi->plist_name);
 1500:       oi->plist_name = NULL;
 1501:     }
 1502: 
 1503:   ospf6_interface_connected_route_update (oi->interface);
 1504: 
 1505:   if (oi->area)
 1506:     {
 1507:       OSPF6_LINK_LSA_SCHEDULE (oi);
 1508:       if (oi->state == OSPF6_INTERFACE_DR)
 1509:         {
 1510:           OSPF6_NETWORK_LSA_SCHEDULE (oi);
 1511:           OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);
 1512:         }
 1513:       OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area);
 1514:     }
 1515: 
 1516:   return CMD_SUCCESS;
 1517: }
 1518: 
 1519: static int
 1520: config_write_ospf6_interface (struct vty *vty)
 1521: {
 1522:   struct listnode *i;
 1523:   struct ospf6_interface *oi;
 1524:   struct interface *ifp;
 1525: 
 1526:   for (ALL_LIST_ELEMENTS_RO (iflist, i, ifp))
 1527:     {
 1528:       oi = (struct ospf6_interface *) ifp->info;
 1529:       if (oi == NULL)
 1530:         continue;
 1531: 
 1532:       vty_out (vty, "interface %s%s",
 1533:                oi->interface->name, VNL);
 1534: 
 1535:       if (ifp->desc)
 1536:         vty_out (vty, " description %s%s", ifp->desc, VNL);
 1537:       if (ifp->mtu6 != oi->ifmtu)
 1538:         vty_out (vty, " ipv6 ospf6 ifmtu %d%s", oi->ifmtu, VNL);
 1539: 
 1540:       if (oi->cost != OSPF6_INTERFACE_COST)
 1541:         vty_out (vty, " ipv6 ospf6 cost %d%s",
 1542:                  oi->cost, VNL);
 1543: 
 1544:       if (oi->hello_interval != OSPF6_INTERFACE_HELLO_INTERVAL)
 1545:         vty_out (vty, " ipv6 ospf6 hello-interval %d%s",
 1546:                  oi->hello_interval, VNL);
 1547: 
 1548:       if (oi->dead_interval != OSPF6_INTERFACE_DEAD_INTERVAL)
 1549:         vty_out (vty, " ipv6 ospf6 dead-interval %d%s",
 1550:                  oi->dead_interval, VNL);
 1551: 
 1552:       if (oi->rxmt_interval != OSPF6_INTERFACE_RXMT_INTERVAL)
 1553:         vty_out (vty, " ipv6 ospf6 retransmit-interval %d%s",
 1554:                  oi->rxmt_interval, VNL);
 1555: 
 1556:       if (oi->priority != OSPF6_INTERFACE_PRIORITY)
 1557:         vty_out (vty, " ipv6 ospf6 priority %d%s",
 1558:                  oi->priority, VNL);
 1559: 
 1560:       if (oi->transdelay != OSPF6_INTERFACE_TRANSDELAY)
 1561:         vty_out (vty, " ipv6 ospf6 transmit-delay %d%s",
 1562:                  oi->transdelay, VNL);
 1563: 
 1564:       if (oi->instance_id != OSPF6_INTERFACE_INSTANCE_ID)
 1565:         vty_out (vty, " ipv6 ospf6 instance-id %d%s",
 1566:                  oi->instance_id, VNL);
 1567: 
 1568:       if (oi->plist_name)
 1569:         vty_out (vty, " ipv6 ospf6 advertise prefix-list %s%s",
 1570:                  oi->plist_name, VNL);
 1571: 
 1572:       if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
 1573:         vty_out (vty, " ipv6 ospf6 passive%s", VNL);
 1574: 
 1575:       if (oi->mtu_ignore)
 1576:         vty_out (vty, " ipv6 ospf6 mtu-ignore%s", VNL);
 1577: 
 1578:       vty_out (vty, "!%s", VNL);
 1579:     }
 1580:   return 0;
 1581: }
 1582: 
 1583: static struct cmd_node interface_node =
 1584: {
 1585:   INTERFACE_NODE,
 1586:   "%s(config-if)# ",
 1587:   1 /* VTYSH */
 1588: };
 1589: 
 1590: void
 1591: ospf6_interface_init (void)
 1592: {
 1593:   /* Install interface node. */
 1594:   install_node (&interface_node, config_write_ospf6_interface);
 1595: 
 1596:   install_element (VIEW_NODE, &show_ipv6_ospf6_interface_cmd);
 1597:   install_element (VIEW_NODE, &show_ipv6_ospf6_interface_prefix_cmd);
 1598:   install_element (VIEW_NODE, &show_ipv6_ospf6_interface_prefix_detail_cmd);
 1599:   install_element (VIEW_NODE, &show_ipv6_ospf6_interface_prefix_match_cmd);
 1600:   install_element (VIEW_NODE, &show_ipv6_ospf6_interface_ifname_cmd);
 1601:   install_element (VIEW_NODE, &show_ipv6_ospf6_interface_ifname_prefix_cmd);
 1602:   install_element (VIEW_NODE, &show_ipv6_ospf6_interface_ifname_prefix_detail_cmd);
 1603:   install_element (VIEW_NODE, &show_ipv6_ospf6_interface_ifname_prefix_match_cmd);
 1604:   install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_cmd);
 1605:   install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_prefix_cmd);
 1606:   install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_prefix_detail_cmd);
 1607:   install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_prefix_match_cmd);
 1608:   install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_ifname_cmd);
 1609:   install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_ifname_prefix_cmd);
 1610:   install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_ifname_prefix_detail_cmd);
 1611:   install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_ifname_prefix_match_cmd);
 1612: 
 1613:   install_element (CONFIG_NODE, &interface_cmd);
 1614:   install_default (INTERFACE_NODE);
 1615:   install_element (INTERFACE_NODE, &interface_desc_cmd);
 1616:   install_element (INTERFACE_NODE, &no_interface_desc_cmd);
 1617:   install_element (INTERFACE_NODE, &ipv6_ospf6_cost_cmd);
 1618:   install_element (INTERFACE_NODE, &ipv6_ospf6_ifmtu_cmd);
 1619:   install_element (INTERFACE_NODE, &no_ipv6_ospf6_ifmtu_cmd);
 1620:   install_element (INTERFACE_NODE, &ipv6_ospf6_deadinterval_cmd);
 1621:   install_element (INTERFACE_NODE, &ipv6_ospf6_hellointerval_cmd);
 1622:   install_element (INTERFACE_NODE, &ipv6_ospf6_priority_cmd);
 1623:   install_element (INTERFACE_NODE, &ipv6_ospf6_retransmitinterval_cmd);
 1624:   install_element (INTERFACE_NODE, &ipv6_ospf6_transmitdelay_cmd);
 1625:   install_element (INTERFACE_NODE, &ipv6_ospf6_instance_cmd);
 1626: 
 1627:   install_element (INTERFACE_NODE, &ipv6_ospf6_passive_cmd);
 1628:   install_element (INTERFACE_NODE, &no_ipv6_ospf6_passive_cmd);
 1629: 
 1630:   install_element (INTERFACE_NODE, &ipv6_ospf6_mtu_ignore_cmd);
 1631:   install_element (INTERFACE_NODE, &no_ipv6_ospf6_mtu_ignore_cmd);
 1632: 
 1633:   install_element (INTERFACE_NODE, &ipv6_ospf6_advertise_prefix_list_cmd);
 1634:   install_element (INTERFACE_NODE, &no_ipv6_ospf6_advertise_prefix_list_cmd);
 1635: }
 1636: 
 1637: DEFUN (debug_ospf6_interface,
 1638:        debug_ospf6_interface_cmd,
 1639:        "debug ospf6 interface",
 1640:        DEBUG_STR
 1641:        OSPF6_STR
 1642:        "Debug OSPFv3 Interface\n"
 1643:       )
 1644: {
 1645:   OSPF6_DEBUG_INTERFACE_ON ();
 1646:   return CMD_SUCCESS;
 1647: }
 1648: 
 1649: DEFUN (no_debug_ospf6_interface,
 1650:        no_debug_ospf6_interface_cmd,
 1651:        "no debug ospf6 interface",
 1652:        NO_STR
 1653:        DEBUG_STR
 1654:        OSPF6_STR
 1655:        "Debug OSPFv3 Interface\n"
 1656:       )
 1657: {
 1658:   OSPF6_DEBUG_INTERFACE_OFF ();
 1659:   return CMD_SUCCESS;
 1660: }
 1661: 
 1662: int
 1663: config_write_ospf6_debug_interface (struct vty *vty)
 1664: {
 1665:   if (IS_OSPF6_DEBUG_INTERFACE)
 1666:     vty_out (vty, "debug ospf6 interface%s", VNL);
 1667:   return 0;
 1668: }
 1669: 
 1670: void
 1671: install_element_ospf6_debug_interface (void)
 1672: {
 1673:   install_element (ENABLE_NODE, &debug_ospf6_interface_cmd);
 1674:   install_element (ENABLE_NODE, &no_debug_ospf6_interface_cmd);
 1675:   install_element (CONFIG_NODE, &debug_ospf6_interface_cmd);
 1676:   install_element (CONFIG_NODE, &no_debug_ospf6_interface_cmd);
 1677: }
 1678: 
 1679: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>