ospf_opaque.c
上传用户:xiaozhuqw
上传日期:2009-11-15
资源大小:1338k
文件大小:70k
源码类别:

网络

开发平台:

Unix_Linux

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