File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / ospfd / ospf_opaque.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:26:12 2012 UTC (12 years, 5 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_21, v0_99_20_1, v0_99_20, HEAD
quagga

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

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