File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / ospfd / ospf_opaque.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:12 2016 UTC (7 years, 8 months ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

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

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