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

    1: /*
    2:  * This is an implementation of rfc2370.
    3:  * Copyright (C) 2001 KDD R&D Laboratories, Inc.
    4:  * http://www.kddlabs.co.jp/
    5:  *
    6:  * This file is part of GNU Zebra.
    7:  *
    8:  * GNU Zebra is free software; you can redistribute it and/or modify it
    9:  * under the terms of the GNU General Public License as published by the
   10:  * Free Software Foundation; either version 2, or (at your option) any
   11:  * later version.
   12:  * 
   13:  * GNU Zebra is distributed in the hope that it will be useful, but
   14:  * WITHOUT ANY WARRANTY; without even the implied warranty of
   15:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   16:  * General Public License for more details.
   17:  *
   18:  * You should have received a copy of the GNU General Public License
   19:  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
   20:  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   21:  * 02111-1307, USA.
   22:  */
   23: 
   24: /***** MTYPE definitions are not reflected to "memory.h" yet. *****/
   25: #define MTYPE_OSPF_OPAQUE_FUNCTAB	0
   26: #define MTYPE_OPAQUE_INFO_PER_TYPE	0
   27: #define MTYPE_OPAQUE_INFO_PER_ID	0
   28: 
   29: #include <zebra.h>
   30: #ifdef HAVE_OPAQUE_LSA
   31: 
   32: #include "linklist.h"
   33: #include "prefix.h"
   34: #include "if.h"
   35: #include "table.h"
   36: #include "memory.h"
   37: #include "command.h"
   38: #include "vty.h"
   39: #include "stream.h"
   40: #include "log.h"
   41: #include "thread.h"
   42: #include "hash.h"
   43: #include "sockunion.h"		/* for inet_aton() */
   44: 
   45: #include "ospfd/ospfd.h"
   46: #include "ospfd/ospf_interface.h"
   47: #include "ospfd/ospf_ism.h"
   48: #include "ospfd/ospf_asbr.h"
   49: #include "ospfd/ospf_lsa.h"
   50: #include "ospfd/ospf_lsdb.h"
   51: #include "ospfd/ospf_neighbor.h"
   52: #include "ospfd/ospf_nsm.h"
   53: #include "ospfd/ospf_flood.h"
   54: #include "ospfd/ospf_packet.h"
   55: #include "ospfd/ospf_spf.h"
   56: #include "ospfd/ospf_dump.h"
   57: #include "ospfd/ospf_route.h"
   58: #include "ospfd/ospf_ase.h"
   59: #include "ospfd/ospf_zebra.h"
   60: 
   61: /*------------------------------------------------------------------------*
   62:  * Followings are initialize/terminate functions for Opaque-LSAs handling.
   63:  *------------------------------------------------------------------------*/
   64: 
   65: #ifdef HAVE_OSPF_TE
   66: #include "ospfd/ospf_te.h"
   67: #endif /* HAVE_OSPF_TE */
   68: 
   69: #ifdef SUPPORT_OSPF_API
   70: int ospf_apiserver_init (void);
   71: void ospf_apiserver_term (void); 
   72: /* Init apiserver? It's disabled by default. */
   73: int ospf_apiserver_enable;
   74: #endif /* SUPPORT_OSPF_API */
   75: 
   76: static void ospf_opaque_register_vty (void);
   77: static void ospf_opaque_funclist_init (void);
   78: static void ospf_opaque_funclist_term (void);
   79: static void free_opaque_info_per_type (void *val);
   80: static void free_opaque_info_per_id (void *val);
   81: static int ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa);
   82: static int ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa);
   83: 
   84: void
   85: ospf_opaque_init (void)
   86: {
   87:   ospf_opaque_register_vty ();
   88:   ospf_opaque_funclist_init ();
   89: 
   90: #ifdef HAVE_OSPF_TE
   91:   if (ospf_mpls_te_init () != 0)
   92:     exit (1);
   93: #endif /* HAVE_OSPF_TE */
   94: 
   95: #ifdef SUPPORT_OSPF_API
   96:   if ((ospf_apiserver_enable) && (ospf_apiserver_init () != 0))
   97:     exit (1);
   98: #endif /* SUPPORT_OSPF_API */
   99: 
  100:   return;
  101: }
  102: 
  103: void
  104: ospf_opaque_term (void)
  105: {
  106: #ifdef HAVE_OSPF_TE
  107:   ospf_mpls_te_term ();
  108: #endif /* HAVE_OSPF_TE */
  109: 
  110: #ifdef SUPPORT_OSPF_API
  111:   ospf_apiserver_term ();
  112: #endif /* SUPPORT_OSPF_API */
  113: 
  114:   ospf_opaque_funclist_term ();
  115:   return;
  116: }
  117: 
  118: int
  119: ospf_opaque_type9_lsa_init (struct ospf_interface *oi)
  120: {
  121:   if (oi->opaque_lsa_self != NULL)
  122:     list_delete (oi->opaque_lsa_self);
  123: 
  124:   oi->opaque_lsa_self = list_new ();
  125:   oi->opaque_lsa_self->del = free_opaque_info_per_type;
  126:   oi->t_opaque_lsa_self = NULL;
  127:   return 0;
  128: }
  129: 
  130: void
  131: ospf_opaque_type9_lsa_term (struct ospf_interface *oi)
  132: {
  133:   OSPF_TIMER_OFF (oi->t_opaque_lsa_self);
  134:   if (oi->opaque_lsa_self != NULL)
  135:     list_delete (oi->opaque_lsa_self);
  136:   oi->opaque_lsa_self = NULL;
  137:   return;
  138: }
  139: 
  140: int
  141: ospf_opaque_type10_lsa_init (struct ospf_area *area)
  142: {
  143:   if (area->opaque_lsa_self != NULL)
  144:     list_delete (area->opaque_lsa_self);
  145: 
  146:   area->opaque_lsa_self = list_new ();
  147:   area->opaque_lsa_self->del = free_opaque_info_per_type;
  148:   area->t_opaque_lsa_self = NULL;
  149: 
  150: #ifdef MONITOR_LSDB_CHANGE
  151:   area->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
  152:   area->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
  153: #endif /* MONITOR_LSDB_CHANGE */
  154:   return 0;
  155: }
  156: 
  157: void
  158: ospf_opaque_type10_lsa_term (struct ospf_area *area)
  159: {
  160: #ifdef MONITOR_LSDB_CHANGE
  161:   area->lsdb->new_lsa_hook = 
  162:   area->lsdb->del_lsa_hook = NULL;
  163: #endif /* MONITOR_LSDB_CHANGE */
  164: 
  165:   OSPF_TIMER_OFF (area->t_opaque_lsa_self);
  166:   if (area->opaque_lsa_self != NULL)
  167:     list_delete (area->opaque_lsa_self);
  168:   area->opaque_lsa_self = NULL;
  169:   return;
  170: }
  171: 
  172: int
  173: ospf_opaque_type11_lsa_init (struct ospf *top)
  174: {
  175:   if (top->opaque_lsa_self != NULL)
  176:     list_delete (top->opaque_lsa_self);
  177: 
  178:   top->opaque_lsa_self = list_new ();
  179:   top->opaque_lsa_self->del = free_opaque_info_per_type;
  180:   top->t_opaque_lsa_self = NULL;
  181: 
  182: #ifdef MONITOR_LSDB_CHANGE
  183:   top->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
  184:   top->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
  185: #endif /* MONITOR_LSDB_CHANGE */
  186:   return 0;
  187: }
  188: 
  189: void
  190: ospf_opaque_type11_lsa_term (struct ospf *top)
  191: {
  192: #ifdef MONITOR_LSDB_CHANGE
  193:   top->lsdb->new_lsa_hook = 
  194:   top->lsdb->del_lsa_hook = NULL;
  195: #endif /* MONITOR_LSDB_CHANGE */
  196: 
  197:   OSPF_TIMER_OFF (top->t_opaque_lsa_self);
  198:   if (top->opaque_lsa_self != NULL)
  199:     list_delete (top->opaque_lsa_self);
  200:   top->opaque_lsa_self = NULL;
  201:   return;
  202: }
  203: 
  204: static const char *
  205: ospf_opaque_type_name (u_char opaque_type)
  206: {
  207:   const char *name = "Unknown";
  208: 
  209:   switch (opaque_type)
  210:     {
  211:     case OPAQUE_TYPE_WILDCARD: /* This is a special assignment! */
  212:       name = "Wildcard";
  213:       break;
  214:     case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA:
  215:       name = "Traffic Engineering LSA";
  216:       break;
  217:     case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC:
  218:       name = "Sycamore optical topology description";
  219:       break;
  220:     case OPAQUE_TYPE_GRACE_LSA:
  221:       name = "Grace-LSA";
  222:       break;
  223:     default:
  224:       if (OPAQUE_TYPE_RANGE_UNASSIGNED (opaque_type))
  225:         name = "Unassigned";
  226:       else
  227:         {
  228:           u_int32_t bigger_range = opaque_type;
  229:           /*
  230:            * Get around type-limits warning: comparison is always true due to limited range of data type
  231:            */
  232:           if (OPAQUE_TYPE_RANGE_RESERVED (bigger_range))
  233:             name = "Private/Experimental";
  234:         }
  235:       break;
  236:     }
  237:   return name;
  238: }
  239: 
  240: /*------------------------------------------------------------------------*
  241:  * Followings are management functions to store user specified callbacks.
  242:  *------------------------------------------------------------------------*/
  243: 
  244: struct opaque_info_per_type; /* Forward declaration. */
  245: 
  246: struct ospf_opaque_functab
  247: {
  248:   u_char opaque_type;
  249:   struct opaque_info_per_type *oipt;
  250: 
  251:   int (* new_if_hook)(struct interface *ifp);
  252:   int (* del_if_hook)(struct interface *ifp);
  253:   void (* ism_change_hook)(struct ospf_interface *oi, int old_status);
  254:   void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status);
  255:   void (* config_write_router)(struct vty *vty);
  256:   void (* config_write_if    )(struct vty *vty, struct interface *ifp);
  257:   void (* config_write_debug )(struct vty *vty);
  258:   void (* show_opaque_info   )(struct vty *vty, struct ospf_lsa *lsa);
  259:   int  (* lsa_originator)(void *arg);
  260:   struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa);
  261:   int (* new_lsa_hook)(struct ospf_lsa *lsa);
  262:   int (* del_lsa_hook)(struct ospf_lsa *lsa);
  263: };
  264: 
  265: /* Handle LSA-9/10/11 altogether. */
  266: static struct list *ospf_opaque_wildcard_funclist;
  267: static struct list *ospf_opaque_type9_funclist;
  268: static struct list *ospf_opaque_type10_funclist;
  269: static struct list *ospf_opaque_type11_funclist;
  270: 
  271: static void
  272: ospf_opaque_del_functab (void *val)
  273: {
  274:   XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, val);
  275:   return;
  276: }
  277: 
  278: static void
  279: ospf_opaque_funclist_init (void)
  280: {
  281:   struct list *funclist;
  282: 
  283:   funclist = ospf_opaque_wildcard_funclist = list_new ();
  284:   funclist->del = ospf_opaque_del_functab;
  285: 
  286:   funclist = ospf_opaque_type9_funclist  = list_new ();
  287:   funclist->del = ospf_opaque_del_functab;
  288: 
  289:   funclist = ospf_opaque_type10_funclist = list_new ();
  290:   funclist->del = ospf_opaque_del_functab;
  291: 
  292:   funclist = ospf_opaque_type11_funclist = list_new ();
  293:   funclist->del = ospf_opaque_del_functab;
  294:   return;
  295: }
  296: 
  297: static void
  298: ospf_opaque_funclist_term (void)
  299: {
  300:   struct list *funclist;
  301: 
  302:   funclist = ospf_opaque_wildcard_funclist;
  303:   list_delete (funclist);
  304: 
  305:   funclist = ospf_opaque_type9_funclist;
  306:   list_delete (funclist);
  307: 
  308:   funclist = ospf_opaque_type10_funclist;
  309:   list_delete (funclist);
  310: 
  311:   funclist = ospf_opaque_type11_funclist;
  312:   list_delete (funclist);
  313:   return;
  314: }
  315: 
  316: static struct list *
  317: ospf_get_opaque_funclist (u_char lsa_type)
  318: {
  319:   struct list *funclist = NULL;
  320: 
  321:   switch (lsa_type)
  322:     {
  323:     case OPAQUE_TYPE_WILDCARD:
  324:       /* XXX
  325:        * This is an ugly trick to handle type-9/10/11 LSA altogether.
  326:        * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor
  327:        * an officially assigned opaque-type.
  328:        * Though it is possible that the value might be officially used
  329:        * in the future, we use it internally as a special label, for now.
  330:        */
  331:       funclist = ospf_opaque_wildcard_funclist;
  332:       break;
  333:     case OSPF_OPAQUE_LINK_LSA:
  334:       funclist = ospf_opaque_type9_funclist;
  335:       break;
  336:     case OSPF_OPAQUE_AREA_LSA:
  337:       funclist = ospf_opaque_type10_funclist;
  338:       break;
  339:     case OSPF_OPAQUE_AS_LSA:
  340:       funclist = ospf_opaque_type11_funclist;
  341:       break;
  342:     default:
  343:       zlog_warn ("ospf_get_opaque_funclist: Unexpected LSA-type(%u)", lsa_type);
  344:       break;
  345:     }
  346:   return funclist;
  347: }
  348: 
  349: /* XXX: such a huge argument list can /not/ be healthy... */
  350: int
  351: ospf_register_opaque_functab (
  352:   u_char lsa_type,
  353:   u_char opaque_type,
  354:   int (* new_if_hook)(struct interface *ifp),
  355:   int (* del_if_hook)(struct interface *ifp),
  356:   void (* ism_change_hook)(struct ospf_interface *oi, int old_status),
  357:   void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status),
  358:   void (* config_write_router)(struct vty *vty),
  359:   void (* config_write_if    )(struct vty *vty, struct interface *ifp),
  360:   void (* config_write_debug )(struct vty *vty),
  361:   void (* show_opaque_info   )(struct vty *vty, struct ospf_lsa *lsa),
  362:   int  (* lsa_originator)(void *arg),
  363:   struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa),
  364:   int (* new_lsa_hook)(struct ospf_lsa *lsa),
  365:   int (* del_lsa_hook)(struct ospf_lsa *lsa))
  366: {
  367:   struct list *funclist;
  368:   struct ospf_opaque_functab *new;
  369:   int rc = -1;
  370: 
  371:   if ((funclist = ospf_get_opaque_funclist (lsa_type)) == NULL)
  372:     {
  373:       zlog_warn ("ospf_register_opaque_functab: Cannot get funclist"
  374:                  " for Type-%u LSAs?",
  375:                  lsa_type);
  376:       goto out;
  377:     }
  378:   else
  379:     {
  380:       struct listnode *node, *nnode;
  381:       struct ospf_opaque_functab *functab;
  382:       
  383:       for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
  384:         if (functab->opaque_type == opaque_type)
  385:           {
  386:             zlog_warn ("ospf_register_opaque_functab: Duplicated entry?:"
  387:                        " lsa_type(%u), opaque_type(%u)", 
  388:                        lsa_type, opaque_type);
  389:             goto out;
  390:           }
  391:     }
  392: 
  393:   if ((new = XCALLOC (MTYPE_OSPF_OPAQUE_FUNCTAB,
  394: 		      sizeof (struct ospf_opaque_functab))) == NULL)
  395:     {
  396:       zlog_warn ("ospf_register_opaque_functab: XMALLOC: %s",
  397:                  safe_strerror (errno));
  398:       goto out;
  399:     }
  400: 
  401:   new->opaque_type    = opaque_type;
  402:   new->oipt           = NULL;
  403:   new->new_if_hook    = new_if_hook;
  404:   new->del_if_hook    = del_if_hook;
  405:   new->ism_change_hook     = ism_change_hook;
  406:   new->nsm_change_hook     = nsm_change_hook;
  407:   new->config_write_router = config_write_router;
  408:   new->config_write_if     = config_write_if;
  409:   new->config_write_debug  = config_write_debug;
  410:   new->show_opaque_info    = show_opaque_info;
  411:   new->lsa_originator = lsa_originator;
  412:   new->lsa_refresher  = lsa_refresher;
  413:   new->new_lsa_hook   = new_lsa_hook;
  414:   new->del_lsa_hook   = del_lsa_hook;
  415: 
  416:   listnode_add (funclist, new);
  417:   rc = 0;
  418: 
  419: out:
  420:   return rc;
  421: }
  422: 
  423: void
  424: ospf_delete_opaque_functab (u_char lsa_type, u_char opaque_type)
  425: {
  426:   struct list *funclist;
  427:   struct listnode *node, *nnode;
  428:   struct ospf_opaque_functab *functab;
  429: 
  430:   if ((funclist = ospf_get_opaque_funclist (lsa_type)) != NULL)
  431:     for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
  432:       {
  433:         if (functab->opaque_type == opaque_type)
  434:           {
  435:             /* Cleanup internal control information, if it still remains. */
  436:             if (functab->oipt != NULL)
  437:               free_opaque_info_per_type (functab->oipt);
  438: 
  439:             /* Dequeue listnode entry from the list. */
  440:             listnode_delete (funclist, functab);
  441: 
  442:             /* Avoid misjudgement in the next lookup. */
  443:             if (listcount (funclist) == 0)
  444:               funclist->head = funclist->tail = NULL;
  445: 
  446:             XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, functab);
  447:             break;
  448: 	  }
  449:       }
  450: 
  451:   return;
  452: }
  453: 
  454: static struct ospf_opaque_functab *
  455: ospf_opaque_functab_lookup (struct ospf_lsa *lsa)
  456: {
  457:   struct list *funclist;
  458:   struct listnode *node;
  459:   struct ospf_opaque_functab *functab;
  460:   u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
  461: 
  462:   if ((funclist = ospf_get_opaque_funclist (lsa->data->type)) != NULL)
  463:     for (ALL_LIST_ELEMENTS_RO (funclist, node, functab))
  464:       if (functab->opaque_type == key)
  465:         return functab;
  466: 
  467:   return NULL;
  468: }
  469: 
  470: /*------------------------------------------------------------------------*
  471:  * Followings are management functions for self-originated LSA entries.
  472:  *------------------------------------------------------------------------*/
  473: 
  474: /*
  475:  * Opaque-LSA control information per opaque-type.
  476:  * Single Opaque-Type may have multiple instances; each of them will be
  477:  * identified by their opaque-id.
  478:  */
  479: struct opaque_info_per_type
  480: {
  481:   u_char lsa_type;
  482:   u_char opaque_type;
  483: 
  484:   enum { PROC_NORMAL, PROC_SUSPEND } status;
  485: 
  486:   /*
  487:    * Thread for (re-)origination scheduling for this opaque-type.
  488:    *
  489:    * Initial origination of Opaque-LSAs is controlled by generic
  490:    * Opaque-LSA handling module so that same opaque-type entries are
  491:    * called all at once when certain conditions are met.
  492:    * However, there might be cases that some Opaque-LSA clients need
  493:    * to (re-)originate their own Opaque-LSAs out-of-sync with others.
  494:    * This thread is prepared for that specific purpose.
  495:    */
  496:   struct thread *t_opaque_lsa_self;
  497: 
  498:   /*
  499:    * Backpointer to an "owner" which is LSA-type dependent.
  500:    *   type-9:  struct ospf_interface
  501:    *   type-10: struct ospf_area
  502:    *   type-11: struct ospf
  503:    */
  504:   void *owner;
  505: 
  506:   /* Collection of callback functions for this opaque-type. */
  507:   struct ospf_opaque_functab *functab;
  508: 
  509:   /* List of Opaque-LSA control informations per opaque-id. */
  510:   struct list *id_list;
  511: };
  512: 
  513: /* Opaque-LSA control information per opaque-id. */
  514: struct opaque_info_per_id
  515: {
  516:   u_int32_t opaque_id;
  517: 
  518:   /* Thread for refresh/flush scheduling for this opaque-type/id. */
  519:   struct thread *t_opaque_lsa_self;
  520: 
  521:   /* Backpointer to Opaque-LSA control information per opaque-type. */
  522:   struct opaque_info_per_type *opqctl_type;
  523: 
  524:   /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
  525:   struct ospf_lsa *lsa;
  526: };
  527: 
  528: static struct opaque_info_per_type *register_opaque_info_per_type (struct ospf_opaque_functab *functab, struct ospf_lsa *new);
  529: static struct opaque_info_per_type *lookup_opaque_info_by_type (struct ospf_lsa *lsa);
  530: static struct opaque_info_per_id *register_opaque_info_per_id (struct opaque_info_per_type *oipt, struct ospf_lsa *new);
  531: static struct opaque_info_per_id *lookup_opaque_info_by_id (struct opaque_info_per_type *oipt, struct ospf_lsa *lsa);
  532: static struct opaque_info_per_id *register_opaque_lsa (struct ospf_lsa *new);
  533: 
  534: 
  535: static struct opaque_info_per_type *
  536: register_opaque_info_per_type (struct ospf_opaque_functab *functab,
  537:                                struct ospf_lsa *new)
  538: {
  539:   struct ospf *top;
  540:   struct opaque_info_per_type *oipt;
  541: 
  542:   if ((oipt = XCALLOC (MTYPE_OPAQUE_INFO_PER_TYPE,
  543: 		       sizeof (struct opaque_info_per_type))) == NULL)
  544:     {
  545:       zlog_warn ("register_opaque_info_per_type: XMALLOC: %s", safe_strerror (errno));
  546:       goto out;
  547:     }
  548: 
  549:   switch (new->data->type)
  550:     {
  551:     case OSPF_OPAQUE_LINK_LSA:
  552:       oipt->owner = new->oi;
  553:       listnode_add (new->oi->opaque_lsa_self, oipt);
  554:       break;
  555:     case OSPF_OPAQUE_AREA_LSA:
  556:       oipt->owner = new->area;
  557:       listnode_add (new->area->opaque_lsa_self, oipt);
  558:       break;
  559:     case OSPF_OPAQUE_AS_LSA:
  560:       top = ospf_lookup ();
  561:       if (new->area != NULL && (top = new->area->ospf) == NULL)
  562:         {
  563:           free_opaque_info_per_type ((void *) oipt);
  564:           oipt = NULL;
  565:           goto out; /* This case may not exist. */
  566:         }
  567:       oipt->owner = top;
  568:       listnode_add (top->opaque_lsa_self, oipt);
  569:       break;
  570:     default:
  571:       zlog_warn ("register_opaque_info_per_type: Unexpected LSA-type(%u)", new->data->type);
  572:       free_opaque_info_per_type ((void *) oipt);
  573:       oipt = NULL;
  574:       goto out; /* This case may not exist. */
  575:     }
  576: 
  577:   oipt->lsa_type = new->data->type;
  578:   oipt->opaque_type = GET_OPAQUE_TYPE (ntohl (new->data->id.s_addr));
  579:   oipt->status = PROC_NORMAL;
  580:   oipt->t_opaque_lsa_self = NULL;
  581:   oipt->functab = functab;
  582:   functab->oipt = oipt;
  583:   oipt->id_list = list_new ();
  584:   oipt->id_list->del = free_opaque_info_per_id;
  585: 
  586: out:
  587:   return oipt;
  588: }
  589: 
  590: static void
  591: free_opaque_info_per_type (void *val)
  592: {
  593:   struct opaque_info_per_type *oipt = (struct opaque_info_per_type *) val;
  594:   struct opaque_info_per_id *oipi;
  595:   struct ospf_lsa *lsa;
  596:   struct listnode *node, *nnode;
  597: 
  598:   /* Control information per opaque-id may still exist. */
  599:   for (ALL_LIST_ELEMENTS (oipt->id_list, node, nnode, oipi))
  600:     {
  601:       if ((lsa = oipi->lsa) == NULL)
  602:         continue;
  603:       if (IS_LSA_MAXAGE (lsa))
  604:         continue;
  605:       ospf_opaque_lsa_flush_schedule (lsa);
  606:     }
  607: 
  608:   /* Remove "oipt" from its owner's self-originated LSA list. */
  609:   switch (oipt->lsa_type)
  610:     {
  611:     case OSPF_OPAQUE_LINK_LSA:
  612:       {
  613:         struct ospf_interface *oi = (struct ospf_interface *)(oipt->owner);
  614:         listnode_delete (oi->opaque_lsa_self, oipt);
  615:         break;
  616:       }
  617:     case OSPF_OPAQUE_AREA_LSA:
  618:       {
  619:         struct ospf_area *area = (struct ospf_area *)(oipt->owner);
  620:         listnode_delete (area->opaque_lsa_self, oipt);
  621:         break;
  622:       }
  623:     case OSPF_OPAQUE_AS_LSA:
  624:       {
  625:         struct ospf *top = (struct ospf *)(oipt->owner);
  626:         listnode_delete (top->opaque_lsa_self, oipt);
  627:         break;
  628:       }
  629:     default:
  630:       zlog_warn ("free_opaque_info_per_type: Unexpected LSA-type(%u)", oipt->lsa_type);
  631:       break; /* This case may not exist. */
  632:     }
  633: 
  634:   OSPF_TIMER_OFF (oipt->t_opaque_lsa_self);
  635:   list_delete (oipt->id_list);
  636:   XFREE (MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
  637:   return;
  638: }
  639: 
  640: static struct opaque_info_per_type *
  641: lookup_opaque_info_by_type (struct ospf_lsa *lsa)
  642: {
  643:   struct ospf *top;
  644:   struct ospf_area *area;
  645:   struct ospf_interface *oi;
  646:   struct list *listtop = NULL;
  647:   struct listnode *node, *nnode;
  648:   struct opaque_info_per_type *oipt = NULL;
  649:   u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
  650: 
  651:   switch (lsa->data->type)
  652:     {
  653:     case OSPF_OPAQUE_LINK_LSA:
  654:       if ((oi = lsa->oi) != NULL)
  655:         listtop = oi->opaque_lsa_self;
  656:       else
  657:         zlog_warn ("Type-9 Opaque-LSA: Reference to OI is missing?");
  658:       break;
  659:     case OSPF_OPAQUE_AREA_LSA:
  660:       if ((area = lsa->area) != NULL)
  661:         listtop = area->opaque_lsa_self;
  662:       else
  663:         zlog_warn ("Type-10 Opaque-LSA: Reference to AREA is missing?");
  664:       break;
  665:     case OSPF_OPAQUE_AS_LSA:
  666:       top = ospf_lookup ();
  667:       if ((area = lsa->area) != NULL && (top = area->ospf) == NULL)
  668:         {
  669:           zlog_warn ("Type-11 Opaque-LSA: Reference to OSPF is missing?");
  670:           break; /* Unlikely to happen. */
  671:         }
  672:       listtop = top->opaque_lsa_self;
  673:       break;
  674:     default:
  675:       zlog_warn ("lookup_opaque_info_by_type: Unexpected LSA-type(%u)", lsa->data->type);
  676:       break;
  677:     }
  678: 
  679:   if (listtop != NULL)
  680:     for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt))
  681:       if (oipt->opaque_type == key)
  682:         return oipt;
  683: 
  684:   return NULL;
  685: }
  686: 
  687: static struct opaque_info_per_id *
  688: register_opaque_info_per_id (struct opaque_info_per_type *oipt,
  689:                              struct ospf_lsa *new)
  690: {
  691:   struct opaque_info_per_id *oipi;
  692: 
  693:   if ((oipi = XCALLOC (MTYPE_OPAQUE_INFO_PER_ID,
  694: 		       sizeof (struct opaque_info_per_id))) == NULL)
  695:     {
  696:       zlog_warn ("register_opaque_info_per_id: XMALLOC: %s", safe_strerror (errno));
  697:       goto out;
  698:     }
  699:   oipi->opaque_id = GET_OPAQUE_ID (ntohl (new->data->id.s_addr));
  700:   oipi->t_opaque_lsa_self = NULL;
  701:   oipi->opqctl_type = oipt;
  702:   oipi->lsa = ospf_lsa_lock (new);
  703: 
  704:   listnode_add (oipt->id_list, oipi);
  705: 
  706: out:
  707:   return oipi;
  708: }
  709: 
  710: static void
  711: free_opaque_info_per_id (void *val)
  712: {
  713:   struct opaque_info_per_id *oipi = (struct opaque_info_per_id *) val;
  714: 
  715:   OSPF_TIMER_OFF (oipi->t_opaque_lsa_self);
  716:   if (oipi->lsa != NULL)
  717:     ospf_lsa_unlock (&oipi->lsa);
  718:   XFREE (MTYPE_OPAQUE_INFO_PER_ID, oipi);
  719:   return;
  720: }
  721: 
  722: static struct opaque_info_per_id *
  723: lookup_opaque_info_by_id (struct opaque_info_per_type *oipt,
  724:                           struct ospf_lsa *lsa)
  725: {
  726:   struct listnode *node, *nnode;
  727:   struct opaque_info_per_id   *oipi;
  728:   u_int32_t key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
  729: 
  730:   for (ALL_LIST_ELEMENTS (oipt->id_list, node, nnode, oipi))
  731:     if (oipi->opaque_id == key)
  732:       return oipi;
  733: 
  734:   return NULL;
  735: }
  736: 
  737: static struct opaque_info_per_id *
  738: register_opaque_lsa (struct ospf_lsa *new)
  739: {
  740:   struct ospf_opaque_functab *functab;
  741:   struct opaque_info_per_type *oipt;
  742:   struct opaque_info_per_id *oipi = NULL;
  743: 
  744:   if ((functab = ospf_opaque_functab_lookup (new)) == NULL)
  745:     goto out;
  746: 
  747:   if ((oipt = lookup_opaque_info_by_type (new)) == NULL
  748:   &&  (oipt = register_opaque_info_per_type (functab, new)) == NULL)
  749:     goto out;
  750: 
  751:   if ((oipi = register_opaque_info_per_id (oipt, new)) == NULL)
  752:     goto out;
  753: 
  754: out:
  755:   return oipi;
  756: }
  757: 
  758: /*------------------------------------------------------------------------*
  759:  * Followings are (vty) configuration functions for Opaque-LSAs handling.
  760:  *------------------------------------------------------------------------*/
  761: 
  762: DEFUN (capability_opaque,
  763:        capability_opaque_cmd,
  764:        "capability opaque",
  765:        "Enable specific OSPF feature\n"
  766:        "Opaque LSA\n")
  767: {
  768:   struct ospf *ospf = (struct ospf *) vty->index;
  769: 
  770:   /* Turn on the "master switch" of opaque-lsa capability. */
  771:   if (!CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
  772:     {
  773:       if (IS_DEBUG_OSPF_EVENT)
  774:         zlog_debug ("Opaque capability: OFF -> ON");
  775: 
  776:       SET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
  777:       ospf_renegotiate_optional_capabilities (ospf);
  778:     }
  779:   return CMD_SUCCESS;
  780: }
  781: 
  782: ALIAS (capability_opaque,
  783:        ospf_opaque_capable_cmd,
  784:        "ospf opaque-lsa",
  785:        "OSPF specific commands\n"
  786:        "Enable the Opaque-LSA capability (rfc2370)\n")
  787: 
  788: DEFUN (no_capability_opaque,
  789:        no_capability_opaque_cmd,
  790:        "no capability opaque",
  791:        NO_STR
  792:        "Enable specific OSPF feature\n"
  793:        "Opaque LSA\n")
  794: {
  795:   struct ospf *ospf = (struct ospf *) vty->index;
  796: 
  797:   /* Turn off the "master switch" of opaque-lsa capability. */
  798:   if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
  799:     {
  800:       if (IS_DEBUG_OSPF_EVENT)
  801:         zlog_debug ("Opaque capability: ON -> OFF");
  802: 
  803:       UNSET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
  804:       ospf_renegotiate_optional_capabilities (ospf);
  805:     }
  806:   return CMD_SUCCESS;
  807: }
  808: 
  809: ALIAS (no_capability_opaque,
  810:        no_ospf_opaque_capable_cmd,
  811:        "no ospf opaque-lsa",
  812:        NO_STR
  813:        "OSPF specific commands\n"
  814:        "Disable the Opaque-LSA capability (rfc2370)\n")
  815: 
  816: static void
  817: ospf_opaque_register_vty (void)
  818: {
  819:   install_element (OSPF_NODE, &capability_opaque_cmd);
  820:   install_element (OSPF_NODE, &no_capability_opaque_cmd);
  821:   install_element (OSPF_NODE, &ospf_opaque_capable_cmd);
  822:   install_element (OSPF_NODE, &no_ospf_opaque_capable_cmd);
  823:   return;
  824: }
  825: 
  826: /*------------------------------------------------------------------------*
  827:  * Followings are collection of user-registered function callers.
  828:  *------------------------------------------------------------------------*/
  829: 
  830: static int
  831: opaque_lsa_new_if_callback (struct list *funclist, struct interface *ifp)
  832: {
  833:   struct listnode *node, *nnode;
  834:   struct ospf_opaque_functab *functab;
  835:   int rc = -1;
  836: 
  837:   for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
  838:     if (functab->new_if_hook != NULL)
  839:       if ((* functab->new_if_hook)(ifp) != 0)
  840:         goto out;
  841:   rc = 0;
  842: out:
  843:   return rc;
  844: }
  845: 
  846: static int
  847: opaque_lsa_del_if_callback (struct list *funclist, struct interface *ifp)
  848: {
  849:   struct listnode *node, *nnode;
  850:   struct ospf_opaque_functab *functab;
  851:   int rc = -1;
  852: 
  853:   for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
  854:     if (functab->del_if_hook != NULL)
  855:       if ((* functab->del_if_hook)(ifp) != 0)
  856:         goto out;
  857:   rc = 0;
  858: out:
  859:   return rc;
  860: }
  861: 
  862: static void
  863: opaque_lsa_ism_change_callback (struct list *funclist,
  864:                                 struct ospf_interface *oi, int old_status)
  865: {
  866:   struct listnode *node, *nnode;
  867:   struct ospf_opaque_functab *functab;
  868: 
  869:   for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
  870:     if (functab->ism_change_hook != NULL)
  871:       (* functab->ism_change_hook)(oi, old_status);
  872: 
  873:   return;
  874: }
  875: 
  876: static void
  877: opaque_lsa_nsm_change_callback (struct list *funclist,
  878:                                 struct ospf_neighbor *nbr, int old_status)
  879: {
  880:   struct listnode *node, *nnode;
  881:   struct ospf_opaque_functab *functab;
  882: 
  883:   for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
  884:     if (functab->nsm_change_hook != NULL)
  885:       (* functab->nsm_change_hook)(nbr, old_status);
  886:   return;
  887: }
  888: 
  889: static void
  890: opaque_lsa_config_write_router_callback (struct list *funclist, 
  891:                                          struct vty *vty)
  892: {
  893:   struct listnode *node, *nnode;
  894:   struct ospf_opaque_functab *functab;
  895: 
  896:   for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
  897:     if (functab->config_write_router != NULL)
  898:       (* functab->config_write_router)(vty);
  899:   return;
  900: }
  901: 
  902: static void
  903: opaque_lsa_config_write_if_callback (struct list *funclist,
  904:                                      struct vty *vty, struct interface *ifp)
  905: {
  906:   struct listnode *node, *nnode;
  907:   struct ospf_opaque_functab *functab;
  908: 
  909:   for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
  910:     if (functab->config_write_if != NULL)
  911:       (* functab->config_write_if)(vty, ifp);
  912:   return;
  913: }
  914: 
  915: static void
  916: opaque_lsa_config_write_debug_callback (struct list *funclist, struct vty *vty)
  917: {
  918:   struct listnode *node, *nnode;
  919:   struct ospf_opaque_functab *functab;
  920: 
  921:   for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
  922:     if (functab->config_write_debug != NULL)
  923:       (* functab->config_write_debug)(vty);
  924:   return;
  925: }
  926: 
  927: static int
  928: opaque_lsa_originate_callback (struct list *funclist, void *lsa_type_dependent)
  929: {
  930:   struct listnode *node, *nnode;
  931:   struct ospf_opaque_functab *functab;
  932:   int rc = -1;
  933: 
  934:   for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
  935:     if (functab->lsa_originator != NULL)
  936:       if ((* functab->lsa_originator)(lsa_type_dependent) != 0)
  937:          goto out;
  938:   rc = 0;
  939: out:
  940:   return rc;
  941: }
  942: 
  943: static int
  944: new_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
  945: {
  946:   struct listnode *node, *nnode;
  947:   struct ospf_opaque_functab *functab;
  948:   int rc = -1;
  949: 
  950:   /* This function handles ALL types of LSAs, not only opaque ones. */
  951:   for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
  952:     if (functab->new_lsa_hook != NULL)
  953:       if ((* functab->new_lsa_hook)(lsa) != 0)
  954:         goto out;
  955:   rc = 0;
  956: out:
  957:   return rc;
  958: }
  959: 
  960: static int
  961: del_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
  962: {
  963:   struct listnode *node, *nnode;
  964:   struct ospf_opaque_functab *functab;
  965:   int rc = -1;
  966: 
  967:   /* This function handles ALL types of LSAs, not only opaque ones. */
  968:   for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
  969:     if (functab->del_lsa_hook != NULL)
  970:       if ((* functab->del_lsa_hook)(lsa) != 0)
  971:         goto out;
  972:   rc = 0;
  973: out:
  974:   return rc;
  975: }
  976: 
  977: /*------------------------------------------------------------------------*
  978:  * Followings are glue functions to call Opaque-LSA specific processing.
  979:  *------------------------------------------------------------------------*/
  980: 
  981: int
  982: ospf_opaque_new_if (struct interface *ifp)
  983: {
  984:   struct list *funclist;
  985:   int rc = -1;
  986: 
  987:   funclist = ospf_opaque_wildcard_funclist;
  988:   if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
  989:     goto out;
  990: 
  991:   funclist = ospf_opaque_type9_funclist;
  992:   if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
  993:     goto out;
  994: 
  995:   funclist = ospf_opaque_type10_funclist;
  996:   if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
  997:     goto out;
  998: 
  999:   funclist = ospf_opaque_type11_funclist;
 1000:   if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
 1001:     goto out;
 1002: 
 1003:   rc = 0;
 1004: out:
 1005:   return rc;
 1006: }
 1007: 
 1008: int
 1009: ospf_opaque_del_if (struct interface *ifp)
 1010: {
 1011:   struct list *funclist;
 1012:   int rc = -1;
 1013: 
 1014:   funclist = ospf_opaque_wildcard_funclist;
 1015:   if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
 1016:     goto out;
 1017: 
 1018:   funclist = ospf_opaque_type9_funclist;
 1019:   if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
 1020:     goto out;
 1021: 
 1022:   funclist = ospf_opaque_type10_funclist;
 1023:   if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
 1024:     goto out;
 1025: 
 1026:   funclist = ospf_opaque_type11_funclist;
 1027:   if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
 1028:     goto out;
 1029: 
 1030:   rc = 0;
 1031: out:
 1032:   return rc;
 1033: }
 1034: 
 1035: void
 1036: ospf_opaque_ism_change (struct ospf_interface *oi, int old_status)
 1037: {
 1038:   struct list *funclist;
 1039: 
 1040:   funclist = ospf_opaque_wildcard_funclist;
 1041:   opaque_lsa_ism_change_callback (funclist, oi, old_status);
 1042: 
 1043:   funclist = ospf_opaque_type9_funclist;
 1044:   opaque_lsa_ism_change_callback (funclist, oi, old_status);
 1045: 
 1046:   funclist = ospf_opaque_type10_funclist;
 1047:   opaque_lsa_ism_change_callback (funclist, oi, old_status);
 1048: 
 1049:   funclist = ospf_opaque_type11_funclist;
 1050:   opaque_lsa_ism_change_callback (funclist, oi, old_status);
 1051: 
 1052:   return;
 1053: }
 1054: 
 1055: void
 1056: ospf_opaque_nsm_change (struct ospf_neighbor *nbr, int old_state)
 1057: {
 1058:   struct ospf *top;
 1059:   struct list *funclist;
 1060: 
 1061:   if ((top = oi_to_top (nbr->oi)) == NULL)
 1062:     goto out;
 1063: 
 1064:   if (old_state != NSM_Full && nbr->state == NSM_Full)
 1065:     {
 1066:       if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
 1067:         {
 1068:           if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
 1069:             {
 1070:               if (IS_DEBUG_OSPF_EVENT)
 1071:                 zlog_debug ("Opaque-LSA: Now get operational!");
 1072: 
 1073:               SET_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT);
 1074:             }
 1075: 
 1076:           ospf_opaque_lsa_originate_schedule (nbr->oi, NULL);
 1077:         }
 1078:     }
 1079:   else
 1080:   if (old_state == NSM_Full && nbr->state != NSM_Full)
 1081:     {
 1082: #ifdef NOTYET
 1083:       /*
 1084:        * If no more opaque-capable full-state neighbor remains in the
 1085:        * flooding scope which corresponds to Opaque-LSA type, periodic
 1086:        * LS flooding should be stopped.
 1087:        */
 1088: #endif /* NOTYET */
 1089:       ;
 1090:     }
 1091: 
 1092:   funclist = ospf_opaque_wildcard_funclist;
 1093:   opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
 1094: 
 1095:   funclist = ospf_opaque_type9_funclist;
 1096:   opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
 1097: 
 1098:   funclist = ospf_opaque_type10_funclist;
 1099:   opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
 1100: 
 1101:   funclist = ospf_opaque_type11_funclist;
 1102:   opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
 1103: 
 1104: out:
 1105:   return;
 1106: }
 1107: 
 1108: void
 1109: ospf_opaque_config_write_router (struct vty *vty, struct ospf *ospf)
 1110: {
 1111:   struct list *funclist;
 1112: 
 1113:   if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
 1114:     vty_out (vty, " capability opaque%s", VTY_NEWLINE);
 1115: 
 1116:   funclist = ospf_opaque_wildcard_funclist;
 1117:   opaque_lsa_config_write_router_callback (funclist, vty);
 1118: 
 1119:   funclist = ospf_opaque_type9_funclist;
 1120:   opaque_lsa_config_write_router_callback (funclist, vty);
 1121: 
 1122:   funclist = ospf_opaque_type10_funclist;
 1123:   opaque_lsa_config_write_router_callback (funclist, vty);
 1124: 
 1125:   funclist = ospf_opaque_type11_funclist;
 1126:   opaque_lsa_config_write_router_callback (funclist, vty);
 1127: 
 1128:   return;
 1129: }
 1130: 
 1131: void
 1132: ospf_opaque_config_write_if (struct vty *vty, struct interface *ifp)
 1133: {
 1134:   struct list *funclist;
 1135: 
 1136:   funclist = ospf_opaque_wildcard_funclist;
 1137:   opaque_lsa_config_write_if_callback (funclist, vty, ifp);
 1138: 
 1139:   funclist = ospf_opaque_type9_funclist;
 1140:   opaque_lsa_config_write_if_callback (funclist, vty, ifp);
 1141: 
 1142:   funclist = ospf_opaque_type10_funclist;
 1143:   opaque_lsa_config_write_if_callback (funclist, vty, ifp);
 1144: 
 1145:   funclist = ospf_opaque_type11_funclist;
 1146:   opaque_lsa_config_write_if_callback (funclist, vty, ifp);
 1147: 
 1148:   return;
 1149: }
 1150: 
 1151: void
 1152: ospf_opaque_config_write_debug (struct vty *vty)
 1153: {
 1154:   struct list *funclist;
 1155: 
 1156:   funclist = ospf_opaque_wildcard_funclist;
 1157:   opaque_lsa_config_write_debug_callback (funclist, vty);
 1158: 
 1159:   funclist = ospf_opaque_type9_funclist;
 1160:   opaque_lsa_config_write_debug_callback (funclist, vty);
 1161: 
 1162:   funclist = ospf_opaque_type10_funclist;
 1163:   opaque_lsa_config_write_debug_callback (funclist, vty);
 1164: 
 1165:   funclist = ospf_opaque_type11_funclist;
 1166:   opaque_lsa_config_write_debug_callback (funclist, vty);
 1167: 
 1168:   return;
 1169: }
 1170: 
 1171: void
 1172: show_opaque_info_detail (struct vty *vty, struct ospf_lsa *lsa)
 1173: {
 1174:   struct lsa_header *lsah = (struct lsa_header *) lsa->data;
 1175:   u_int32_t lsid = ntohl (lsah->id.s_addr);
 1176:   u_char    opaque_type = GET_OPAQUE_TYPE (lsid);
 1177:   u_int32_t opaque_id = GET_OPAQUE_ID (lsid);
 1178:   struct ospf_opaque_functab *functab;
 1179: 
 1180:   /* Switch output functionality by vty address. */
 1181:   if (vty != NULL)
 1182:     {
 1183:       vty_out (vty, "  Opaque-Type %u (%s)%s", opaque_type,
 1184: 	       ospf_opaque_type_name (opaque_type), VTY_NEWLINE);
 1185:       vty_out (vty, "  Opaque-ID   0x%x%s", opaque_id, VTY_NEWLINE);
 1186: 
 1187:       vty_out (vty, "  Opaque-Info: %u octets of data%s%s",
 1188:                ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
 1189:                VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)",
 1190:                VTY_NEWLINE);
 1191:     }
 1192:   else
 1193:     {
 1194:       zlog_debug ("    Opaque-Type %u (%s)", opaque_type,
 1195: 		 ospf_opaque_type_name (opaque_type));
 1196:       zlog_debug ("    Opaque-ID   0x%x", opaque_id);
 1197: 
 1198:       zlog_debug ("    Opaque-Info: %u octets of data%s",
 1199:                ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
 1200:                VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)");
 1201:     }
 1202: 
 1203:   /* Call individual output functions. */
 1204:   if ((functab = ospf_opaque_functab_lookup (lsa)) != NULL)
 1205:     if (functab->show_opaque_info != NULL)
 1206:       (* functab->show_opaque_info)(vty, lsa);
 1207: 
 1208:   return;
 1209: }
 1210: 
 1211: void
 1212: ospf_opaque_lsa_dump (struct stream *s, u_int16_t length)
 1213: {
 1214:   struct ospf_lsa lsa;
 1215: 
 1216:   lsa.data = (struct lsa_header *) STREAM_PNT (s);
 1217:   show_opaque_info_detail (NULL, &lsa);
 1218:   return;
 1219: }
 1220: 
 1221: static int
 1222: ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa)
 1223: {
 1224:   struct list *funclist;
 1225:   int rc = -1;
 1226: 
 1227:   /*
 1228:    * Some Opaque-LSA user may want to monitor every LSA installation
 1229:    * into the LSDB, regardless with target LSA type.
 1230:    */
 1231:   funclist = ospf_opaque_wildcard_funclist;
 1232:   if (new_lsa_callback (funclist, lsa) != 0)
 1233:     goto out;
 1234: 
 1235:   funclist = ospf_opaque_type9_funclist;
 1236:   if (new_lsa_callback (funclist, lsa) != 0)
 1237:     goto out;
 1238: 
 1239:   funclist = ospf_opaque_type10_funclist;
 1240:   if (new_lsa_callback (funclist, lsa) != 0)
 1241:     goto out;
 1242: 
 1243:   funclist = ospf_opaque_type11_funclist;
 1244:   if (new_lsa_callback (funclist, lsa) != 0)
 1245:     goto out;
 1246: 
 1247:   rc = 0;
 1248: out:
 1249:   return rc;
 1250: }
 1251: 
 1252: static int
 1253: ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa)
 1254: {
 1255:   struct list *funclist;
 1256:   int rc = -1;
 1257: 
 1258:   /*
 1259:    * Some Opaque-LSA user may want to monitor every LSA deletion
 1260:    * from the LSDB, regardless with target LSA type.
 1261:    */
 1262:   funclist = ospf_opaque_wildcard_funclist;
 1263:   if (del_lsa_callback (funclist, lsa) != 0)
 1264:     goto out;
 1265: 
 1266:   funclist = ospf_opaque_type9_funclist;
 1267:   if (del_lsa_callback (funclist, lsa) != 0)
 1268:     goto out;
 1269: 
 1270:   funclist = ospf_opaque_type10_funclist;
 1271:   if (del_lsa_callback (funclist, lsa) != 0)
 1272:     goto out;
 1273: 
 1274:   funclist = ospf_opaque_type11_funclist;
 1275:   if (del_lsa_callback (funclist, lsa) != 0)
 1276:     goto out;
 1277: 
 1278:   rc = 0;
 1279: out:
 1280:   return rc;
 1281: }
 1282: 
 1283: /*------------------------------------------------------------------------*
 1284:  * Followings are Opaque-LSA origination/refresh management functions.
 1285:  *------------------------------------------------------------------------*/
 1286: 
 1287: static int ospf_opaque_type9_lsa_originate (struct thread *t);
 1288: static int ospf_opaque_type10_lsa_originate (struct thread *t);
 1289: static int ospf_opaque_type11_lsa_originate (struct thread *t);
 1290: static void ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg);
 1291: 
 1292: void
 1293: ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0)
 1294: {
 1295:   struct ospf *top;
 1296:   struct ospf_area *area;
 1297:   struct listnode *node, *nnode;
 1298:   struct opaque_info_per_type *oipt;
 1299:   int delay = 0;
 1300: 
 1301:   if ((top = oi_to_top (oi)) == NULL || (area = oi->area) == NULL)
 1302:     {
 1303:       zlog_warn ("ospf_opaque_lsa_originate_schedule: Invalid argument?");
 1304:       goto out;
 1305:     }
 1306: 
 1307:   /* It may not a right time to schedule origination now. */
 1308:   if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
 1309:     {
 1310:       if (IS_DEBUG_OSPF_EVENT)
 1311:         zlog_debug ("ospf_opaque_lsa_originate_schedule: Not operational.");
 1312:       goto out; /* This is not an error. */
 1313:     }
 1314:   if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
 1315:     {
 1316:       if (IS_DEBUG_OSPF_EVENT)
 1317:         zlog_debug ("ospf_opaque_lsa_originate_schedule: Under blockade.");
 1318:       goto out; /* This is not an error, too. */
 1319:     }
 1320: 
 1321:   if (delay0 != NULL)
 1322:     delay = *delay0;
 1323: 
 1324:   /*
 1325:    * There might be some entries that have been waiting for triggering
 1326:    * of per opaque-type re-origination get resumed.
 1327:    */
 1328:   ospf_opaque_lsa_reoriginate_resume (  oi->opaque_lsa_self, (void *)   oi);
 1329:   ospf_opaque_lsa_reoriginate_resume (area->opaque_lsa_self, (void *) area);
 1330:   ospf_opaque_lsa_reoriginate_resume ( top->opaque_lsa_self, (void *)  top);
 1331: 
 1332:   /*
 1333:    * Now, schedule origination of all Opaque-LSAs per opaque-type.
 1334:    */
 1335:   if (! list_isempty (ospf_opaque_type9_funclist)
 1336:   &&    list_isempty (oi->opaque_lsa_self)
 1337:   &&    oi->t_opaque_lsa_self == NULL)
 1338:     {
 1339:       if (IS_DEBUG_OSPF_EVENT)
 1340:         zlog_debug ("Schedule Type-9 Opaque-LSA origination in %d sec later.", delay);
 1341:       oi->t_opaque_lsa_self =
 1342: 	thread_add_timer (master, ospf_opaque_type9_lsa_originate, oi, delay);
 1343:       delay += OSPF_MIN_LS_INTERVAL;
 1344:     }
 1345: 
 1346:   if (! list_isempty (ospf_opaque_type10_funclist)
 1347:   &&    list_isempty (area->opaque_lsa_self)
 1348:   &&    area->t_opaque_lsa_self == NULL)
 1349:     {
 1350:       /*
 1351:        * One AREA may contain multiple OIs, but above 2nd and 3rd
 1352:        * conditions prevent from scheduling the originate function
 1353:        * again and again.
 1354:        */
 1355:       if (IS_DEBUG_OSPF_EVENT)
 1356:         zlog_debug ("Schedule Type-10 Opaque-LSA origination in %d sec later.", delay);
 1357:       area->t_opaque_lsa_self =
 1358:         thread_add_timer (master, ospf_opaque_type10_lsa_originate,
 1359:                           area, delay);
 1360:       delay += OSPF_MIN_LS_INTERVAL;
 1361:     }
 1362: 
 1363:   if (! list_isempty (ospf_opaque_type11_funclist)
 1364:   &&    list_isempty (top->opaque_lsa_self)
 1365:   &&    top->t_opaque_lsa_self == NULL)
 1366:     {
 1367:       /*
 1368:        * One OSPF may contain multiple AREAs, but above 2nd and 3rd
 1369:        * conditions prevent from scheduling the originate function
 1370:        * again and again.
 1371:        */
 1372:       if (IS_DEBUG_OSPF_EVENT)
 1373:         zlog_debug ("Schedule Type-11 Opaque-LSA origination in %d sec later.", delay);
 1374:       top->t_opaque_lsa_self =
 1375:         thread_add_timer (master, ospf_opaque_type11_lsa_originate,
 1376:                           top, delay);
 1377:       delay += OSPF_MIN_LS_INTERVAL;
 1378:     }
 1379: 
 1380:   /*
 1381:    * Following section treats a special situation that this node's
 1382:    * opaque capability has changed as "ON -> OFF -> ON".
 1383:    */
 1384:   if (! list_isempty (ospf_opaque_type9_funclist)
 1385:   &&  ! list_isempty (oi->opaque_lsa_self))
 1386:     {
 1387:       for (ALL_LIST_ELEMENTS (oi->opaque_lsa_self, node, nnode, oipt))
 1388:         {
 1389: 	  /* 
 1390: 	   * removed the test for
 1391: 	   *   (! list_isempty (oipt->id_list))   * Handler is already active. *
 1392:            * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
 1393: 	   * not being empty.
 1394: 	   */
 1395:           if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
 1396:               || oipt->status == PROC_SUSPEND)   /* Cannot originate now. */
 1397:               continue;
 1398: 
 1399:           ospf_opaque_lsa_reoriginate_schedule ((void *) oi,
 1400:             OSPF_OPAQUE_LINK_LSA, oipt->opaque_type);
 1401:         }
 1402:     }
 1403: 
 1404:   if (! list_isempty (ospf_opaque_type10_funclist)
 1405:   &&  ! list_isempty (area->opaque_lsa_self))
 1406:     {
 1407:       for (ALL_LIST_ELEMENTS (area->opaque_lsa_self, node, nnode, oipt))
 1408:         {
 1409: 	  /* 
 1410: 	   * removed the test for
 1411: 	   *   (! list_isempty (oipt->id_list))   * Handler is already active. *
 1412:            * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
 1413: 	   * not being empty.
 1414: 	   */
 1415:           if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
 1416:               || oipt->status == PROC_SUSPEND)   /* Cannot originate now. */
 1417:             continue;
 1418: 
 1419:           ospf_opaque_lsa_reoriginate_schedule ((void *) area,
 1420:             OSPF_OPAQUE_AREA_LSA, oipt->opaque_type);
 1421:         }
 1422:     }
 1423: 
 1424:   if (! list_isempty (ospf_opaque_type11_funclist)
 1425:   &&  ! list_isempty (top->opaque_lsa_self))
 1426:     {
 1427:       for (ALL_LIST_ELEMENTS (top->opaque_lsa_self, node, nnode, oipt))
 1428:         {
 1429: 	  /* 
 1430: 	   * removed the test for
 1431: 	   *   (! list_isempty (oipt->id_list))   * Handler is already active. *
 1432:            * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
 1433: 	   * not being empty.
 1434: 	   */
 1435:           if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
 1436:               || oipt->status == PROC_SUSPEND)   /* Cannot originate now. */
 1437:             continue;
 1438: 
 1439:           ospf_opaque_lsa_reoriginate_schedule ((void *) top,
 1440:             OSPF_OPAQUE_AS_LSA, oipt->opaque_type);
 1441:         }
 1442:     }
 1443: 
 1444:   if (delay0 != NULL)
 1445:     *delay0 = delay;
 1446: 
 1447: out:
 1448:   return;
 1449: }
 1450: 
 1451: static int
 1452: ospf_opaque_type9_lsa_originate (struct thread *t)
 1453: {
 1454:   struct ospf_interface *oi;
 1455:   int rc;
 1456: 
 1457:   oi = THREAD_ARG (t);
 1458:   oi->t_opaque_lsa_self = NULL;
 1459: 
 1460:   if (IS_DEBUG_OSPF_EVENT)
 1461:     zlog_debug ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
 1462:                 IF_NAME (oi));
 1463: 
 1464:   rc = opaque_lsa_originate_callback (ospf_opaque_type9_funclist, oi);
 1465: 
 1466:   return rc;
 1467: }
 1468: 
 1469: static int
 1470: ospf_opaque_type10_lsa_originate (struct thread *t)
 1471: {
 1472:   struct ospf_area *area;
 1473:   int rc;
 1474: 
 1475:   area = THREAD_ARG (t);
 1476:   area->t_opaque_lsa_self = NULL;
 1477: 
 1478:   if (IS_DEBUG_OSPF_EVENT)
 1479:     zlog_debug ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
 1480:                 inet_ntoa (area->area_id));
 1481: 
 1482:   rc = opaque_lsa_originate_callback (ospf_opaque_type10_funclist, area);
 1483: 
 1484:   return rc;
 1485: }
 1486: 
 1487: static int
 1488: ospf_opaque_type11_lsa_originate (struct thread *t)
 1489: {
 1490:   struct ospf *top;
 1491:   int rc;
 1492: 
 1493:   top = THREAD_ARG (t);
 1494:   top->t_opaque_lsa_self = NULL;
 1495: 
 1496:   if (IS_DEBUG_OSPF_EVENT)
 1497:     zlog_debug ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
 1498: 
 1499:   rc = opaque_lsa_originate_callback (ospf_opaque_type11_funclist, top);
 1500: 
 1501:   return rc;
 1502: }
 1503: 
 1504: static void
 1505: ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg)
 1506: {
 1507:   struct listnode *node, *nnode;
 1508:   struct opaque_info_per_type *oipt;
 1509:   struct ospf_opaque_functab *functab;
 1510: 
 1511:   if (listtop == NULL)
 1512:     goto out;
 1513: 
 1514:   /*
 1515:    * Pickup oipt entries those which in SUSPEND status, and give
 1516:    * them a chance to start re-origination now.
 1517:    */
 1518:   for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt))
 1519:     {
 1520:       if (oipt->status != PROC_SUSPEND)
 1521:           continue;
 1522: 
 1523:       oipt->status = PROC_NORMAL;
 1524: 
 1525:       if ((functab = oipt->functab) == NULL
 1526:           || functab->lsa_originator  == NULL)
 1527:         continue;
 1528: 
 1529:       if ((* functab->lsa_originator)(arg) != 0)
 1530:         {
 1531:           zlog_warn ("ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", oipt->opaque_type);
 1532:           continue;
 1533:         }
 1534:     }
 1535: 
 1536: out:
 1537:   return;
 1538: }
 1539: 
 1540: struct ospf_lsa *
 1541: ospf_opaque_lsa_install (struct ospf_lsa *lsa, int rt_recalc)
 1542: {
 1543:   struct ospf_lsa *new = NULL;
 1544:   struct opaque_info_per_type *oipt;
 1545:   struct opaque_info_per_id *oipi;
 1546:   struct ospf *top;
 1547: 
 1548:   /* Don't take "rt_recalc" into consideration for now. *//* XXX */
 1549: 
 1550:   if (! IS_LSA_SELF (lsa))
 1551:     {
 1552:       new = lsa; /* Don't touch this LSA. */
 1553:       goto out;
 1554:     }
 1555: 
 1556:   if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
 1557:     zlog_debug ("Install Type-%u Opaque-LSA: [opaque-type=%u, opaque-id=%x]", lsa->data->type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)));
 1558: 
 1559:   /* Replace the existing lsa with the new one. */
 1560:   if ((oipt = lookup_opaque_info_by_type (lsa)) != NULL
 1561:       && (oipi = lookup_opaque_info_by_id (oipt, lsa)) != NULL)
 1562:     {
 1563:       ospf_lsa_unlock (&oipi->lsa);
 1564:       oipi->lsa = ospf_lsa_lock (lsa);
 1565:     }
 1566:   /* Register the new lsa entry and get its control info. */
 1567:   else
 1568:   if ((oipi = register_opaque_lsa (lsa)) == NULL)
 1569:     {
 1570:       zlog_warn ("ospf_opaque_lsa_install: register_opaque_lsa() ?");
 1571:       goto out;
 1572:     }
 1573: 
 1574:   /*
 1575:    * Make use of a common mechanism (ospf_lsa_refresh_walker)
 1576:    * for periodic refresh of self-originated Opaque-LSAs.
 1577:    */
 1578:   switch (lsa->data->type)
 1579:     {
 1580:     case OSPF_OPAQUE_LINK_LSA:
 1581:       if ((top = oi_to_top (lsa->oi)) == NULL)
 1582:         {
 1583:           /* Above conditions must have passed. */
 1584:           zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
 1585:           goto out;
 1586:         }
 1587:       break;
 1588:     case OSPF_OPAQUE_AREA_LSA:
 1589:       if (lsa->area == NULL || (top = lsa->area->ospf) == NULL)
 1590:         {
 1591:           /* Above conditions must have passed. */
 1592:           zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
 1593:           goto out;
 1594:         }
 1595:       break;
 1596:     case OSPF_OPAQUE_AS_LSA:
 1597:       top = ospf_lookup ();
 1598:       if (lsa->area != NULL && (top = lsa->area->ospf) == NULL)
 1599:         {
 1600:           /* Above conditions must have passed. */
 1601:           zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
 1602:           goto out;
 1603:         }
 1604:       break;
 1605:     default:
 1606:       zlog_warn ("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", lsa->data->type);
 1607:       goto out;
 1608:     }
 1609: 
 1610:   ospf_refresher_register_lsa (top, lsa);
 1611:   new = lsa;
 1612: 
 1613: out:
 1614:   return new;
 1615: }
 1616: 
 1617: struct ospf_lsa *
 1618: ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
 1619: {
 1620:   struct ospf *ospf;
 1621:   struct ospf_opaque_functab *functab;
 1622:   struct ospf_lsa *new = NULL;
 1623:   
 1624:   ospf = ospf_lookup ();
 1625: 
 1626:   if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL
 1627:       || functab->lsa_refresher == NULL)
 1628:     {
 1629:       /*
 1630:        * Though this LSA seems to have originated on this node, the
 1631:        * handling module for this "lsa-type and opaque-type" was
 1632:        * already deleted sometime ago.
 1633:        * Anyway, this node still has a responsibility to flush this
 1634:        * LSA from the routing domain.
 1635:        */
 1636:       if (IS_DEBUG_OSPF_EVENT)
 1637:         zlog_debug ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id));
 1638: 
 1639:       lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
 1640:       ospf_lsa_flush (ospf, lsa);
 1641:     }
 1642:   else
 1643:     new = (* functab->lsa_refresher)(lsa);
 1644: 
 1645:   return new;
 1646: }
 1647: 
 1648: /*------------------------------------------------------------------------*
 1649:  * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
 1650:  * triggered by external interventions (vty session, signaling, etc).
 1651:  *------------------------------------------------------------------------*/
 1652: 
 1653: #define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
 1654:       if (!(T)) \
 1655:         (T) = thread_add_timer (master, (F), (L), (V))
 1656: 
 1657: static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type);
 1658: static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t);
 1659: static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t);
 1660: static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t);
 1661: static int ospf_opaque_lsa_refresh_timer (struct thread *t);
 1662: 
 1663: void
 1664: ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
 1665:                                       u_char lsa_type, u_char opaque_type)
 1666: {
 1667:   struct ospf *top;
 1668:   struct ospf_area dummy, *area = NULL;
 1669:   struct ospf_interface *oi = NULL;
 1670: 
 1671:   struct ospf_lsa *lsa;
 1672:   struct opaque_info_per_type *oipt;
 1673:   int (*func) (struct thread * t) = NULL;
 1674:   int delay;
 1675: 
 1676:   switch (lsa_type)
 1677:     {
 1678:     case OSPF_OPAQUE_LINK_LSA:
 1679:       if ((oi = (struct ospf_interface *) lsa_type_dependent) == NULL)
 1680:         {
 1681:           zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
 1682:                      " Type-9 Opaque-LSA: Invalid parameter?");
 1683:           goto out;
 1684:         }
 1685:       if ((top = oi_to_top (oi)) == NULL)
 1686:         {
 1687:           zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
 1688:                      IF_NAME (oi));
 1689:           goto out;
 1690:         }
 1691:       if (!list_isempty (ospf_opaque_type9_funclist)
 1692:           && list_isempty (oi->opaque_lsa_self)
 1693:           && oi->t_opaque_lsa_self != NULL)
 1694:         {
 1695:           zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u):"
 1696:                      " Common origination for OI(%s) has already started",
 1697:                      opaque_type, IF_NAME (oi));
 1698:           goto out;
 1699:         }
 1700:       func = ospf_opaque_type9_lsa_reoriginate_timer;
 1701:       break;
 1702:     case OSPF_OPAQUE_AREA_LSA:
 1703:       if ((area = (struct ospf_area *) lsa_type_dependent) == NULL)
 1704:         {
 1705:           zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
 1706:                      " Type-10 Opaque-LSA: Invalid parameter?");
 1707:           goto out;
 1708:         }
 1709:       if ((top = area->ospf) == NULL)
 1710:         {
 1711:           zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
 1712:                      " AREA(%s) -> TOP?", inet_ntoa (area->area_id));
 1713:           goto out;
 1714:         }
 1715:       if (!list_isempty (ospf_opaque_type10_funclist)
 1716:           && list_isempty (area->opaque_lsa_self)
 1717:           && area->t_opaque_lsa_self != NULL)
 1718:         {
 1719:           zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u):"
 1720:                      " Common origination for AREA(%s) has already started",
 1721:                      opaque_type, inet_ntoa (area->area_id));
 1722:           goto out;
 1723:         }
 1724:       func = ospf_opaque_type10_lsa_reoriginate_timer;
 1725:       break;
 1726:     case OSPF_OPAQUE_AS_LSA:
 1727:       if ((top = (struct ospf *) lsa_type_dependent) == NULL)
 1728:         {
 1729:           zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
 1730:                      " Type-11 Opaque-LSA: Invalid parameter?");
 1731:           goto out;
 1732:         }
 1733:       if (!list_isempty (ospf_opaque_type11_funclist)
 1734:           && list_isempty (top->opaque_lsa_self)
 1735:           && top->t_opaque_lsa_self != NULL)
 1736:         {
 1737:           zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u):"
 1738:                      " Common origination has already started", opaque_type);
 1739:           goto out;
 1740:         }
 1741: 
 1742:       /* Fake "area" to pass "ospf" to a lookup function later. */
 1743:       dummy.ospf = top;
 1744:       area = &dummy;
 1745: 
 1746:       func = ospf_opaque_type11_lsa_reoriginate_timer;
 1747:       break;
 1748:     default:
 1749:       zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
 1750:                  " Unexpected LSA-type(%u)",
 1751:                  lsa_type);
 1752:       goto out;
 1753:     }
 1754: 
 1755:   /* It may not a right time to schedule reorigination now. */
 1756:   if (!CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
 1757:     {
 1758:       if (IS_DEBUG_OSPF_EVENT)
 1759:         zlog_debug ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
 1760:       goto out;                 /* This is not an error. */
 1761:     }
 1762:   if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
 1763:     {
 1764:       if (IS_DEBUG_OSPF_EVENT)
 1765:         zlog_debug ("ospf_opaque_lsa_reoriginate_schedule: Under blockade.");
 1766:       goto out;                 /* This is not an error, too. */
 1767:     }
 1768: 
 1769:   /* Generate a dummy lsa to be passed for a lookup function. */
 1770:   lsa = pseudo_lsa (oi, area, lsa_type, opaque_type);
 1771: 
 1772:   if ((oipt = lookup_opaque_info_by_type (lsa)) == NULL)
 1773:     {
 1774:       struct ospf_opaque_functab *functab;
 1775:       if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL)
 1776:         {
 1777:           zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
 1778:                      " No associated function?: lsa_type(%u),"
 1779:                      " opaque_type(%u)",
 1780:                      lsa_type, opaque_type);
 1781:           goto out;
 1782:         }
 1783:       if ((oipt = register_opaque_info_per_type (functab, lsa)) == NULL)
 1784:         {
 1785:           zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
 1786:                      " Cannot get a control info?: lsa_type(%u),"
 1787:                      " opaque_type(%u)",
 1788:                      lsa_type, opaque_type);
 1789:           goto out;
 1790:         }
 1791:     }
 1792: 
 1793:   if (oipt->t_opaque_lsa_self != NULL)
 1794:     {
 1795:       if (IS_DEBUG_OSPF_EVENT)
 1796:         zlog_debug ("Type-%u Opaque-LSA has already scheduled to"
 1797:                    " RE-ORIGINATE: [opaque-type=%u]",
 1798:                    lsa_type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
 1799:       goto out;
 1800:     }
 1801: 
 1802:   /*
 1803:    * Different from initial origination time, in which various conditions
 1804:    * (opaque capability, neighbor status etc) are assured by caller of
 1805:    * the originating function "ospf_opaque_lsa_originate_schedule ()",
 1806:    * it is highly possible that these conditions might not be satisfied
 1807:    * at the time of re-origination function is to be called.
 1808:    */
 1809:   delay = OSPF_MIN_LS_INTERVAL; /* XXX */
 1810: 
 1811:   if (IS_DEBUG_OSPF_EVENT)
 1812:     zlog_debug ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
 1813:                " sec later: [opaque-type=%u]", 
 1814:                lsa_type, delay, 
 1815:                GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
 1816: 
 1817:   OSPF_OPAQUE_TIMER_ON (oipt->t_opaque_lsa_self, func, oipt, delay);
 1818: 
 1819: out:
 1820:   return;
 1821: }
 1822: 
 1823: static struct ospf_lsa *
 1824: pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area,
 1825:             u_char lsa_type, u_char opaque_type)
 1826: {
 1827:   static struct ospf_lsa lsa = { 0 };
 1828:   static struct lsa_header lsah = { 0 };
 1829:   u_int32_t tmp;
 1830: 
 1831:   lsa.oi   = oi;
 1832:   lsa.area = area;
 1833:   lsa.data = &lsah;
 1834: 
 1835:   lsah.type = lsa_type;
 1836:   tmp = SET_OPAQUE_LSID (opaque_type, 0); /* Opaque-ID is unused here. */
 1837:   lsah.id.s_addr = htonl (tmp);
 1838: 
 1839:   return &lsa;
 1840: }
 1841: 
 1842: static int
 1843: ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t)
 1844: {
 1845:   struct opaque_info_per_type *oipt;
 1846:   struct ospf_opaque_functab *functab;
 1847:   struct ospf *top;
 1848:   struct ospf_interface *oi;
 1849:   int rc = -1;
 1850: 
 1851:   oipt = THREAD_ARG (t);
 1852:   oipt->t_opaque_lsa_self = NULL;
 1853: 
 1854:   if ((functab = oipt->functab) == NULL
 1855:   ||   functab->lsa_originator == NULL)
 1856:     {
 1857:       zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
 1858:       goto out;
 1859:     }
 1860: 
 1861:   oi = (struct ospf_interface *) oipt->owner;
 1862:   if ((top = oi_to_top (oi)) == NULL)
 1863:     {
 1864:       zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
 1865:       goto out;
 1866:     }
 1867: 
 1868:   if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)
 1869:   ||  ! ospf_if_is_enable (oi)
 1870:   ||    ospf_nbr_count_opaque_capable (oi) == 0)
 1871:     {
 1872:       if (IS_DEBUG_OSPF_EVENT)
 1873:         zlog_debug ("Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
 1874:     
 1875:       oipt->status = PROC_SUSPEND;
 1876:       rc = 0;
 1877:       goto out;
 1878:     }
 1879: 
 1880:   if (IS_DEBUG_OSPF_EVENT)
 1881:     zlog_debug ("Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)", oipt->opaque_type, IF_NAME (oi));
 1882: 
 1883:   rc = (* functab->lsa_originator)(oi);
 1884: out:
 1885:   return rc;
 1886: }
 1887: 
 1888: static int
 1889: ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t)
 1890: {
 1891:   struct opaque_info_per_type *oipt;
 1892:   struct ospf_opaque_functab *functab;
 1893:   struct listnode *node, *nnode;
 1894:   struct ospf *top;
 1895:   struct ospf_area *area;
 1896:   struct ospf_interface *oi;
 1897:   int n, rc = -1;
 1898: 
 1899:   oipt = THREAD_ARG (t);
 1900:   oipt->t_opaque_lsa_self = NULL;
 1901: 
 1902:   if ((functab = oipt->functab) == NULL
 1903:   ||   functab->lsa_originator == NULL)
 1904:     {
 1905:       zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
 1906:       goto out;
 1907:     }
 1908: 
 1909:   area = (struct ospf_area *) oipt->owner;
 1910:   if (area == NULL || (top = area->ospf) == NULL)
 1911:     {
 1912:       zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
 1913:       goto out;
 1914:     }
 1915: 
 1916:   /* There must be at least one "opaque-capable, full-state" neighbor. */
 1917:   n = 0;
 1918:   for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi))
 1919:     {
 1920:       if ((n = ospf_nbr_count_opaque_capable (oi)) > 0)
 1921:         break;
 1922:     }
 1923: 
 1924:   if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
 1925:     {
 1926:       if (IS_DEBUG_OSPF_EVENT)
 1927:         zlog_debug ("Suspend re-origination of Type-10 Opaque-LSAs"
 1928:                    " (opaque-type=%u) for a while...", 
 1929:                    oipt->opaque_type);
 1930: 
 1931:       oipt->status = PROC_SUSPEND;
 1932:       rc = 0;
 1933:       goto out;
 1934:     }
 1935: 
 1936:   if (IS_DEBUG_OSPF_EVENT)
 1937:     zlog_debug ("Timer[Type10-LSA]: Re-originate Opaque-LSAs"
 1938:                " (opaque-type=%u) for Area %s", 
 1939:                oipt->opaque_type, inet_ntoa (area->area_id));
 1940: 
 1941:   rc = (* functab->lsa_originator)(area);
 1942: out:
 1943:   return rc;
 1944: }
 1945: 
 1946: static int
 1947: ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t)
 1948: {
 1949:   struct opaque_info_per_type *oipt;
 1950:   struct ospf_opaque_functab *functab;
 1951:   struct ospf *top;
 1952:   int rc = -1;
 1953: 
 1954:   oipt = THREAD_ARG (t);
 1955:   oipt->t_opaque_lsa_self = NULL;
 1956: 
 1957:   if ((functab = oipt->functab) == NULL
 1958:       || functab->lsa_originator == NULL)
 1959:     {
 1960:       zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer:"
 1961:                  " No associated function?");
 1962:       goto out;
 1963:     }
 1964: 
 1965:   if ((top = (struct ospf *) oipt->owner) == NULL)
 1966:     {
 1967:       zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
 1968:       goto out;
 1969:     }
 1970: 
 1971:   if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
 1972:     {
 1973:       if (IS_DEBUG_OSPF_EVENT)
 1974:         zlog_debug ("Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
 1975:     
 1976:       oipt->status = PROC_SUSPEND;
 1977:       rc = 0;
 1978:       goto out;
 1979:     }
 1980: 
 1981:   if (IS_DEBUG_OSPF_EVENT)
 1982:     zlog_debug ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type);
 1983: 
 1984:   rc = (* functab->lsa_originator)(top);
 1985: out:
 1986:   return rc;
 1987: }
 1988: 
 1989: void
 1990: ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
 1991: {
 1992:   struct opaque_info_per_type *oipt;
 1993:   struct opaque_info_per_id *oipi;
 1994:   struct ospf_lsa *lsa;
 1995:   int delay;
 1996: 
 1997:   if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
 1998:   ||  (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
 1999:     {
 2000:       zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
 2001:       goto out;
 2002:     }
 2003: 
 2004:   /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
 2005:   if ((lsa = oipi->lsa) == NULL)
 2006:     {
 2007:       zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
 2008:       goto out;
 2009:     }
 2010: 
 2011:   if (oipi->t_opaque_lsa_self != NULL)
 2012:     {
 2013:       if (IS_DEBUG_OSPF_EVENT)
 2014:         zlog_debug ("Type-%u Opaque-LSA has already scheduled to REFRESH: [opaque-type=%u, opaque-id=%x]", lsa->data->type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)));
 2015:       goto out;
 2016:     }
 2017: 
 2018:   /* Delete this lsa from neighbor retransmit-list. */
 2019:   switch (lsa->data->type)
 2020:     {
 2021:     case OSPF_OPAQUE_LINK_LSA:
 2022:     case OSPF_OPAQUE_AREA_LSA:
 2023:       ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
 2024:       break;
 2025:     case OSPF_OPAQUE_AS_LSA:
 2026:       ospf_ls_retransmit_delete_nbr_as (lsa0->area->ospf, lsa);
 2027:       break;
 2028:     default:
 2029:       zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type);
 2030:       goto out;
 2031:     }
 2032: 
 2033:   delay = ospf_lsa_refresh_delay (lsa);
 2034: 
 2035:   if (IS_DEBUG_OSPF_EVENT)
 2036:     zlog_debug ("Schedule Type-%u Opaque-LSA to REFRESH in %d sec later: [opaque-type=%u, opaque-id=%x]", lsa->data->type, delay, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)));
 2037: 
 2038:   OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self,
 2039:                         ospf_opaque_lsa_refresh_timer, oipi, delay);
 2040: out:
 2041:   return;
 2042: }
 2043: 
 2044: static int
 2045: ospf_opaque_lsa_refresh_timer (struct thread *t)
 2046: {
 2047:   struct opaque_info_per_id *oipi;
 2048:   struct ospf_opaque_functab *functab;
 2049:   struct ospf_lsa *lsa;
 2050: 
 2051:   if (IS_DEBUG_OSPF_EVENT)
 2052:     zlog_debug ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
 2053: 
 2054:   oipi = THREAD_ARG (t);
 2055:   oipi->t_opaque_lsa_self = NULL;
 2056: 
 2057:   if ((lsa = oipi->lsa) != NULL)
 2058:     if ((functab = oipi->opqctl_type->functab) != NULL)
 2059:       if (functab->lsa_refresher != NULL)
 2060:         (* functab->lsa_refresher)(lsa);
 2061: 
 2062:   return 0;
 2063: }
 2064: 
 2065: void
 2066: ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
 2067: {
 2068:   struct opaque_info_per_type *oipt;
 2069:   struct opaque_info_per_id *oipi;
 2070:   struct ospf_lsa *lsa;
 2071: 
 2072:   if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
 2073:   ||  (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
 2074:     {
 2075:       zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
 2076:       goto out;
 2077:     }
 2078: 
 2079:   /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
 2080:   if ((lsa = oipi->lsa) == NULL)
 2081:     {
 2082:       zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
 2083:       goto out;
 2084:     }
 2085: 
 2086:   /* Delete this lsa from neighbor retransmit-list. */
 2087:   switch (lsa->data->type)
 2088:     {
 2089:     case OSPF_OPAQUE_LINK_LSA:
 2090:     case OSPF_OPAQUE_AREA_LSA:
 2091:       ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
 2092:       break;
 2093:     case OSPF_OPAQUE_AS_LSA:
 2094:       ospf_ls_retransmit_delete_nbr_as (lsa0->area->ospf, lsa);
 2095:       break;
 2096:     default:
 2097:       zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type);
 2098:       goto out;
 2099:     }
 2100: 
 2101:   /* Dequeue listnode entry from the list. */
 2102:   listnode_delete (oipt->id_list, oipi);
 2103: 
 2104:   /* Avoid misjudgement in the next lookup. */
 2105:   if (listcount (oipt->id_list) == 0)
 2106:     oipt->id_list->head = oipt->id_list->tail = NULL;
 2107: 
 2108:   /* Disassociate internal control information with the given lsa. */
 2109:   free_opaque_info_per_id ((void *) oipi);
 2110: 
 2111:   /* Force given lsa's age to MaxAge. */
 2112:   lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
 2113: 
 2114:   if (IS_DEBUG_OSPF_EVENT)
 2115:     zlog_debug ("Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]", lsa->data->type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)));
 2116: 
 2117:   /* This lsa will be flushed and removed eventually. */
 2118:   ospf_lsa_flush (lsa0->area->ospf, lsa);
 2119: 
 2120: out:
 2121:   return;
 2122: }
 2123: 
 2124: /*------------------------------------------------------------------------*
 2125:  * Followings are control functions to block origination after restart.
 2126:  *------------------------------------------------------------------------*/
 2127: 
 2128: static void ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs, struct ospf_neighbor *inbr, struct ospf_lsa *lsa);
 2129: static void ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi);
 2130: static void ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area);
 2131: static void ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top);
 2132: static unsigned long ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type);
 2133: 
 2134: void
 2135: ospf_opaque_adjust_lsreq (struct ospf_neighbor *nbr, struct list *lsas)
 2136: {
 2137:   struct ospf *top;
 2138:   struct ospf_area *area;
 2139:   struct ospf_interface *oi;
 2140:   struct listnode *node1, *nnode1;
 2141:   struct listnode *node2, *nnode2;
 2142:   struct ospf_lsa *lsa;
 2143: 
 2144:   if ((top = oi_to_top (nbr->oi)) == NULL)
 2145:     goto out;
 2146: 
 2147:   /*
 2148:    * If an instance of self-originated Opaque-LSA is found in the given
 2149:    * LSA list, and it is not installed to LSDB yet, exclude it from the
 2150:    * list "nbr->ls_req". In this way, it is assured that an LSReq message,
 2151:    * which might be sent in the process of flooding, will not request for
 2152:    * the LSA to be flushed immediately; otherwise, depending on timing,
 2153:    * an LSUpd message will carry instances of target LSAs with MaxAge,
 2154:    * while other LSUpd message might carry old LSA instances (non-MaxAge).
 2155:    * Obviously, the latter would trigger miserable situations that repeat
 2156:    * installation and removal of unwanted LSAs indefinitely.
 2157:    */
 2158:   for (ALL_LIST_ELEMENTS (lsas, node1, nnode1, lsa))
 2159:     {
 2160:       /* Filter out unwanted LSAs. */
 2161:       if (! IS_OPAQUE_LSA (lsa->data->type))
 2162:         continue;
 2163:       if (! IPV4_ADDR_SAME (&lsa->data->adv_router, &top->router_id))
 2164:         continue;
 2165: 
 2166:       /*
 2167:        * Don't touch an LSA which has MaxAge; two possible cases.
 2168:        *
 2169:        *   1) This LSA has originally flushed by myself (received LSUpd
 2170:        *      message's router-id is equal to my router-id), and flooded
 2171:        *      back by an opaque-capable router.
 2172:        *
 2173:        *   2) This LSA has expired in an opaque-capable router and thus
 2174:        *      flushed by the router.
 2175:        */
 2176:       if (IS_LSA_MAXAGE (lsa))
 2177:         continue;
 2178: 
 2179:       /* If the LSA has installed in the LSDB, nothing to do here. */
 2180:       if (ospf_lsa_lookup_by_header (nbr->oi->area, lsa->data) != NULL)
 2181:         continue;
 2182: 
 2183:       /* Ok, here we go. */
 2184:       switch (lsa->data->type)
 2185:         {
 2186:         case OSPF_OPAQUE_LINK_LSA:
 2187:           oi = nbr->oi;
 2188:           ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
 2189:           break;
 2190:         case OSPF_OPAQUE_AREA_LSA:
 2191:           area = nbr->oi->area;
 2192:           for (ALL_LIST_ELEMENTS (area->oiflist, node2, nnode2, oi))
 2193:             ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
 2194:           break;
 2195:         case OSPF_OPAQUE_AS_LSA:
 2196:           for (ALL_LIST_ELEMENTS (top->oiflist, node2, nnode2, oi))
 2197:             ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
 2198:           break;
 2199:         default:
 2200:           break;
 2201:         }
 2202:     }
 2203: 
 2204: out:
 2205:   return;
 2206: }
 2207: 
 2208: static void
 2209: ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs,
 2210:                                     struct ospf_neighbor *inbr,
 2211:                                     struct ospf_lsa *lsa)
 2212: {
 2213:   struct route_node *rn;
 2214:   struct ospf_neighbor *onbr;
 2215:   struct ospf_lsa *ls_req;
 2216: 
 2217:   for (rn = route_top (nbrs); rn; rn = route_next (rn))
 2218:     {
 2219:       if ((onbr = rn->info) == NULL)
 2220:         continue;
 2221:       if (onbr == inbr)
 2222:         continue;
 2223:       if ((ls_req = ospf_ls_request_lookup (onbr, lsa)) == NULL)
 2224:         continue;
 2225: 
 2226:       if (IS_DEBUG_OSPF_EVENT)
 2227:         zlog_debug ("LSA[%s]: Exclude this entry from LSReq to send.", dump_lsa_key (lsa));
 2228: 
 2229:       ospf_ls_request_delete (onbr, ls_req);
 2230: /*    ospf_check_nbr_loading (onbr);*//* XXX */
 2231:     }
 2232: 
 2233:   return;
 2234: }
 2235: 
 2236: void
 2237: ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr, 
 2238:                                           struct ospf_lsa *lsa)
 2239: {
 2240:   struct ospf *top;
 2241:   u_char before;
 2242: 
 2243:   if ((top = oi_to_top (nbr->oi)) == NULL)
 2244:     return;
 2245: 
 2246:   before = IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque);
 2247: 
 2248:   /*
 2249:    * Since these LSA entries are not yet installed into corresponding
 2250:    * LSDB, just flush them without calling ospf_ls_maxage() afterward.
 2251:    */
 2252:   lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
 2253:   switch (lsa->data->type)
 2254:     {
 2255:     case OSPF_OPAQUE_LINK_LSA:
 2256:       SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
 2257:       ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
 2258:       break;
 2259:     case OSPF_OPAQUE_AREA_LSA:
 2260:       SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
 2261:       ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
 2262:       break;
 2263:     case OSPF_OPAQUE_AS_LSA:
 2264:       SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
 2265:       ospf_flood_through_as (top, NULL/*inbr*/, lsa);
 2266:       break;
 2267:     default:
 2268:       zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
 2269:       return;
 2270:     }
 2271: 
 2272:   ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */
 2273: 
 2274:   if (before == 0 && IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
 2275:     {
 2276:       if (IS_DEBUG_OSPF_EVENT)
 2277:         zlog_debug ("Block Opaque-LSA origination: OFF -> ON");
 2278:     }
 2279: }
 2280: 
 2281: void
 2282: ospf_opaque_ls_ack_received (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
 2283: {
 2284:   struct ospf *top;
 2285:   int delay;
 2286:   struct ospf_interface *oi;
 2287:   struct listnode *node, *nnode;
 2288: 
 2289:   if ((top = oi_to_top (nbr->oi)) == NULL)
 2290:     return;
 2291:   
 2292:   if (!IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
 2293:     return;
 2294:   
 2295:   switch (lsa->data->type)
 2296:     {
 2297:     case OSPF_OPAQUE_LINK_LSA:
 2298:       if (CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT))
 2299:         ospf_opaque_type9_lsa_rxmt_nbr_check (nbr->oi);
 2300:       /* Callback function... */
 2301:       break;
 2302:     case OSPF_OPAQUE_AREA_LSA:
 2303:       if (CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT))
 2304:         ospf_opaque_type10_lsa_rxmt_nbr_check (nbr->oi->area);
 2305:       /* Callback function... */
 2306:       break;
 2307:     case OSPF_OPAQUE_AS_LSA:
 2308:       if (CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT))
 2309:         ospf_opaque_type11_lsa_rxmt_nbr_check (top);
 2310:       /* Callback function... */
 2311:       break;
 2312:     default:
 2313:       zlog_warn ("ospf_opaque_ls_ack_received: Unexpected LSA-type(%u)", lsa->data->type);
 2314:       return;
 2315:     }
 2316:   
 2317:   if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
 2318:     {
 2319:       if (IS_DEBUG_OSPF_EVENT)
 2320:         zlog_debug ("Block Opaque-LSA origination: ON -> OFF");
 2321:       return; /* Blocking still in progress. */
 2322:     }
 2323:   
 2324:   if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
 2325:     return; /* Opaque capability condition must have changed. */
 2326: 
 2327:   /* Ok, let's start origination of Opaque-LSAs. */
 2328:   delay = OSPF_MIN_LS_INTERVAL;
 2329: 
 2330:   for (ALL_LIST_ELEMENTS (top->oiflist, node, nnode, oi))
 2331:     {
 2332:       if (! ospf_if_is_enable (oi)
 2333:           || ospf_nbr_count_opaque_capable (oi) == 0)
 2334:         continue;
 2335: 
 2336:       ospf_opaque_lsa_originate_schedule (oi, &delay);
 2337:     }
 2338:     
 2339:   return;
 2340: }
 2341: 
 2342: static void
 2343: ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi)
 2344: {
 2345:   unsigned long n;
 2346: 
 2347:   n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_LINK_LSA);
 2348:   if (n == 0)
 2349:     {
 2350:       if (IS_DEBUG_OSPF_EVENT)
 2351:         zlog_debug ("Self-originated type-9 Opaque-LSAs: OI(%s): Flush completed", IF_NAME (oi));
 2352: 
 2353:       UNSET_FLAG (oi->area->ospf->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
 2354:     }
 2355:   return;
 2356: }
 2357: 
 2358: static void
 2359: ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area)
 2360: {
 2361:   struct listnode *node;
 2362:   struct ospf_interface *oi;
 2363:   unsigned long n = 0;
 2364: 
 2365:   for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
 2366:     {
 2367:       if (area->area_id.s_addr != OSPF_AREA_BACKBONE
 2368:           && oi->type == OSPF_IFTYPE_VIRTUALLINK) 
 2369:         continue;
 2370: 
 2371:       n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AREA_LSA);
 2372:       if (n > 0)
 2373:         break;
 2374:     }
 2375: 
 2376:   if (n == 0)
 2377:     {
 2378:       if (IS_DEBUG_OSPF_EVENT)
 2379:         zlog_debug ("Self-originated type-10 Opaque-LSAs: AREA(%s): Flush completed", inet_ntoa (area->area_id));
 2380: 
 2381:       UNSET_FLAG (area->ospf->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
 2382:     }
 2383: 
 2384:   return;
 2385: }
 2386: 
 2387: static void
 2388: ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top)
 2389: {
 2390:   struct listnode *node;
 2391:   struct ospf_interface *oi;
 2392:   unsigned long n = 0;
 2393: 
 2394:   for (ALL_LIST_ELEMENTS_RO (top->oiflist, node, oi))
 2395:     {
 2396:       switch (oi->type)
 2397:         {
 2398:         case OSPF_IFTYPE_VIRTUALLINK:
 2399:           continue;
 2400:         default:
 2401:           break;
 2402:         }
 2403: 
 2404:       n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AS_LSA);
 2405:       if (n > 0)
 2406:         goto out;
 2407:     }
 2408: 
 2409:   if (n == 0)
 2410:     {
 2411:       if (IS_DEBUG_OSPF_EVENT)
 2412:         zlog_debug ("Self-originated type-11 Opaque-LSAs: Flush completed");
 2413: 
 2414:       UNSET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
 2415:     }
 2416: 
 2417: out:
 2418:   return;
 2419: }
 2420: 
 2421: static unsigned long
 2422: ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type)
 2423: {
 2424:   struct route_node *rn;
 2425:   struct ospf_neighbor *nbr;
 2426:   struct ospf *top;
 2427:   unsigned long n = 0;
 2428: 
 2429:   for (rn = route_top (nbrs); rn; rn = route_next (rn))
 2430:     {
 2431:       if ((nbr = rn->info) == NULL)
 2432:         continue;
 2433:       if ((top = oi_to_top (nbr->oi)) == NULL)
 2434:         continue;
 2435:       if (IPV4_ADDR_SAME (&nbr->router_id, &top->router_id))
 2436:         continue;
 2437:       n += ospf_ls_retransmit_count_self (nbr, lsa_type);
 2438:     }
 2439: 
 2440:   return n;
 2441: }
 2442: 
 2443: /*------------------------------------------------------------------------*
 2444:  * Followings are util functions; probably be used by Opaque-LSAs only...
 2445:  *------------------------------------------------------------------------*/
 2446: 
 2447: void
 2448: htonf (float *src, float *dst)
 2449: {
 2450:   u_int32_t lu1, lu2;
 2451: 
 2452:   memcpy (&lu1, src, sizeof (u_int32_t));
 2453:   lu2 = htonl (lu1);
 2454:   memcpy (dst, &lu2, sizeof (u_int32_t));
 2455:   return;
 2456: }
 2457: 
 2458: void
 2459: ntohf (float *src, float *dst)
 2460: {
 2461:   u_int32_t lu1, lu2;
 2462: 
 2463:   memcpy (&lu1, src, sizeof (u_int32_t));
 2464:   lu2 = ntohl (lu1);
 2465:   memcpy (dst, &lu2, sizeof (u_int32_t));
 2466:   return;
 2467: }
 2468: 
 2469: struct ospf *
 2470: oi_to_top (struct ospf_interface *oi)
 2471: {
 2472:   struct ospf *top = NULL;
 2473:   struct ospf_area *area;
 2474: 
 2475:   if (oi == NULL || (area = oi->area) == NULL || (top = area->ospf) == NULL)
 2476:     zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");
 2477: 
 2478:   return top;
 2479: }
 2480: 
 2481: #endif /* HAVE_OPAQUE_LSA */

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