2 * This is an implementation of rfc2370.
3 * Copyright (C) 2001 KDD R&D Laboratories, Inc.
4 * http://www.kddlabs.co.jp/
6 * This file is part of GNU Zebra.
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
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.
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
24 /***** MTYPE definitions are not reflected to "memory.h" yet. *****/
25 #define MTYPE_OSPF_OPAQUE_FUNCTAB MTYPE_TMP
26 #define MTYPE_OPAQUE_INFO_PER_TYPE MTYPE_TMP
27 #define MTYPE_OPAQUE_INFO_PER_ID MTYPE_TMP
42 #include "sockunion.h" /* for inet_aton() */
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"
60 /*------------------------------------------------------------------------*
61 * Followings are initialize/terminate functions for Opaque-LSAs handling.
62 *------------------------------------------------------------------------*/
64 #include "ospfd/ospf_te.h"
65 #include "ospfd/ospf_ri.h"
67 #ifdef SUPPORT_OSPF_API
68 int ospf_apiserver_init (void);
69 void ospf_apiserver_term (void);
70 /* Init apiserver? It's disabled by default. */
71 int ospf_apiserver_enable;
72 #endif /* SUPPORT_OSPF_API */
74 static void ospf_opaque_register_vty (void);
75 static void ospf_opaque_funclist_init (void);
76 static void ospf_opaque_funclist_term (void);
77 static void free_opaque_info_per_type (void *val);
78 static void free_opaque_info_per_id (void *val);
79 static int ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa);
80 static int ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa);
83 ospf_opaque_init (void)
85 ospf_opaque_register_vty ();
86 ospf_opaque_funclist_init ();
88 if (ospf_mpls_te_init () != 0)
91 if (ospf_router_info_init () != 0)
94 #ifdef SUPPORT_OSPF_API
95 if ((ospf_apiserver_enable) && (ospf_apiserver_init () != 0))
97 #endif /* SUPPORT_OSPF_API */
103 ospf_opaque_term (void)
105 ospf_mpls_te_term ();
107 ospf_router_info_term ();
109 #ifdef SUPPORT_OSPF_API
110 ospf_apiserver_term ();
111 #endif /* SUPPORT_OSPF_API */
113 ospf_opaque_funclist_term ();
118 ospf_opaque_type9_lsa_init (struct ospf_interface *oi)
120 if (oi->opaque_lsa_self != NULL)
121 list_delete (oi->opaque_lsa_self);
123 oi->opaque_lsa_self = list_new ();
124 oi->opaque_lsa_self->del = free_opaque_info_per_type;
125 oi->t_opaque_lsa_self = NULL;
130 ospf_opaque_type9_lsa_term (struct ospf_interface *oi)
132 OSPF_TIMER_OFF (oi->t_opaque_lsa_self);
133 if (oi->opaque_lsa_self != NULL)
134 list_delete (oi->opaque_lsa_self);
135 oi->opaque_lsa_self = NULL;
140 ospf_opaque_type10_lsa_init (struct ospf_area *area)
142 if (area->opaque_lsa_self != NULL)
143 list_delete (area->opaque_lsa_self);
145 area->opaque_lsa_self = list_new ();
146 area->opaque_lsa_self->del = free_opaque_info_per_type;
147 area->t_opaque_lsa_self = NULL;
149 #ifdef MONITOR_LSDB_CHANGE
150 area->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
151 area->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
152 #endif /* MONITOR_LSDB_CHANGE */
157 ospf_opaque_type10_lsa_term (struct ospf_area *area)
159 #ifdef MONITOR_LSDB_CHANGE
160 area->lsdb->new_lsa_hook =
161 area->lsdb->del_lsa_hook = NULL;
162 #endif /* MONITOR_LSDB_CHANGE */
164 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
165 if (area->opaque_lsa_self != NULL)
166 list_delete (area->opaque_lsa_self);
167 area->opaque_lsa_self = NULL;
172 ospf_opaque_type11_lsa_init (struct ospf *top)
174 if (top->opaque_lsa_self != NULL)
175 list_delete (top->opaque_lsa_self);
177 top->opaque_lsa_self = list_new ();
178 top->opaque_lsa_self->del = free_opaque_info_per_type;
179 top->t_opaque_lsa_self = NULL;
181 #ifdef MONITOR_LSDB_CHANGE
182 top->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
183 top->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
184 #endif /* MONITOR_LSDB_CHANGE */
189 ospf_opaque_type11_lsa_term (struct ospf *top)
191 #ifdef MONITOR_LSDB_CHANGE
192 top->lsdb->new_lsa_hook =
193 top->lsdb->del_lsa_hook = NULL;
194 #endif /* MONITOR_LSDB_CHANGE */
196 OSPF_TIMER_OFF (top->t_opaque_lsa_self);
197 if (top->opaque_lsa_self != NULL)
198 list_delete (top->opaque_lsa_self);
199 top->opaque_lsa_self = NULL;
204 ospf_opaque_type_name (u_char opaque_type)
206 const char *name = "Unknown";
210 case OPAQUE_TYPE_WILDCARD: /* This is a special assignment! */
213 case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA:
214 name = "Traffic Engineering LSA";
216 case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC:
217 name = "Sycamore optical topology description";
219 case OPAQUE_TYPE_GRACE_LSA:
222 case OPAQUE_TYPE_INTER_AS_LSA:
223 name = "Inter-AS TE-v2 LSA";
225 case OPAQUE_TYPE_ROUTER_INFORMATION_LSA:
226 name = "Router Information LSA";
229 if (OPAQUE_TYPE_RANGE_UNASSIGNED (opaque_type))
233 u_int32_t bigger_range = opaque_type;
235 * Get around type-limits warning: comparison is always true due to limited range of data type
237 if (OPAQUE_TYPE_RANGE_RESERVED (bigger_range))
238 name = "Private/Experimental";
245 /*------------------------------------------------------------------------*
246 * Followings are management functions to store user specified callbacks.
247 *------------------------------------------------------------------------*/
249 struct opaque_info_per_type; /* Forward declaration. */
251 struct ospf_opaque_functab
254 struct opaque_info_per_type *oipt;
256 int (* new_if_hook)(struct interface *ifp);
257 int (* del_if_hook)(struct interface *ifp);
258 void (* ism_change_hook)(struct ospf_interface *oi, int old_status);
259 void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status);
260 void (* config_write_router)(struct vty *vty);
261 void (* config_write_if )(struct vty *vty, struct interface *ifp);
262 void (* config_write_debug )(struct vty *vty);
263 void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa);
264 int (* lsa_originator)(void *arg);
265 struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa);
266 int (* new_lsa_hook)(struct ospf_lsa *lsa);
267 int (* del_lsa_hook)(struct ospf_lsa *lsa);
270 /* Handle LSA-9/10/11 altogether. */
271 static struct list *ospf_opaque_wildcard_funclist;
272 static struct list *ospf_opaque_type9_funclist;
273 static struct list *ospf_opaque_type10_funclist;
274 static struct list *ospf_opaque_type11_funclist;
277 ospf_opaque_del_functab (void *val)
279 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, val);
284 ospf_opaque_funclist_init (void)
286 struct list *funclist;
288 funclist = ospf_opaque_wildcard_funclist = list_new ();
289 funclist->del = ospf_opaque_del_functab;
291 funclist = ospf_opaque_type9_funclist = list_new ();
292 funclist->del = ospf_opaque_del_functab;
294 funclist = ospf_opaque_type10_funclist = list_new ();
295 funclist->del = ospf_opaque_del_functab;
297 funclist = ospf_opaque_type11_funclist = list_new ();
298 funclist->del = ospf_opaque_del_functab;
303 ospf_opaque_funclist_term (void)
305 struct list *funclist;
307 funclist = ospf_opaque_wildcard_funclist;
308 list_delete (funclist);
310 funclist = ospf_opaque_type9_funclist;
311 list_delete (funclist);
313 funclist = ospf_opaque_type10_funclist;
314 list_delete (funclist);
316 funclist = ospf_opaque_type11_funclist;
317 list_delete (funclist);
322 ospf_get_opaque_funclist (u_char lsa_type)
324 struct list *funclist = NULL;
328 case OPAQUE_TYPE_WILDCARD:
330 * This is an ugly trick to handle type-9/10/11 LSA altogether.
331 * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor
332 * an officially assigned opaque-type.
333 * Though it is possible that the value might be officially used
334 * in the future, we use it internally as a special label, for now.
336 funclist = ospf_opaque_wildcard_funclist;
338 case OSPF_OPAQUE_LINK_LSA:
339 funclist = ospf_opaque_type9_funclist;
341 case OSPF_OPAQUE_AREA_LSA:
342 funclist = ospf_opaque_type10_funclist;
344 case OSPF_OPAQUE_AS_LSA:
345 funclist = ospf_opaque_type11_funclist;
348 zlog_warn ("ospf_get_opaque_funclist: Unexpected LSA-type(%u)", lsa_type);
354 /* XXX: such a huge argument list can /not/ be healthy... */
356 ospf_register_opaque_functab (
359 int (* new_if_hook)(struct interface *ifp),
360 int (* del_if_hook)(struct interface *ifp),
361 void (* ism_change_hook)(struct ospf_interface *oi, int old_status),
362 void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status),
363 void (* config_write_router)(struct vty *vty),
364 void (* config_write_if )(struct vty *vty, struct interface *ifp),
365 void (* config_write_debug )(struct vty *vty),
366 void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa),
367 int (* lsa_originator)(void *arg),
368 struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa),
369 int (* new_lsa_hook)(struct ospf_lsa *lsa),
370 int (* del_lsa_hook)(struct ospf_lsa *lsa))
372 struct list *funclist;
373 struct ospf_opaque_functab *new;
376 if ((funclist = ospf_get_opaque_funclist (lsa_type)) == NULL)
378 zlog_warn ("ospf_register_opaque_functab: Cannot get funclist"
379 " for Type-%u LSAs?",
385 struct listnode *node, *nnode;
386 struct ospf_opaque_functab *functab;
388 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
389 if (functab->opaque_type == opaque_type)
391 zlog_warn ("ospf_register_opaque_functab: Duplicated entry?:"
392 " lsa_type(%u), opaque_type(%u)",
393 lsa_type, opaque_type);
398 if ((new = XCALLOC (MTYPE_OSPF_OPAQUE_FUNCTAB,
399 sizeof (struct ospf_opaque_functab))) == NULL)
401 zlog_warn ("ospf_register_opaque_functab: XMALLOC: %s",
402 safe_strerror (errno));
406 new->opaque_type = opaque_type;
408 new->new_if_hook = new_if_hook;
409 new->del_if_hook = del_if_hook;
410 new->ism_change_hook = ism_change_hook;
411 new->nsm_change_hook = nsm_change_hook;
412 new->config_write_router = config_write_router;
413 new->config_write_if = config_write_if;
414 new->config_write_debug = config_write_debug;
415 new->show_opaque_info = show_opaque_info;
416 new->lsa_originator = lsa_originator;
417 new->lsa_refresher = lsa_refresher;
418 new->new_lsa_hook = new_lsa_hook;
419 new->del_lsa_hook = del_lsa_hook;
421 listnode_add (funclist, new);
429 ospf_delete_opaque_functab (u_char lsa_type, u_char opaque_type)
431 struct list *funclist;
432 struct listnode *node, *nnode;
433 struct ospf_opaque_functab *functab;
435 if ((funclist = ospf_get_opaque_funclist (lsa_type)) != NULL)
436 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
438 if (functab->opaque_type == opaque_type)
440 /* Cleanup internal control information, if it still remains. */
441 if (functab->oipt != NULL)
442 free_opaque_info_per_type (functab->oipt);
444 /* Dequeue listnode entry from the list. */
445 listnode_delete (funclist, functab);
447 /* Avoid misjudgement in the next lookup. */
448 if (listcount (funclist) == 0)
449 funclist->head = funclist->tail = NULL;
451 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, functab);
459 static struct ospf_opaque_functab *
460 ospf_opaque_functab_lookup (struct ospf_lsa *lsa)
462 struct list *funclist;
463 struct listnode *node;
464 struct ospf_opaque_functab *functab;
465 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
467 if ((funclist = ospf_get_opaque_funclist (lsa->data->type)) != NULL)
468 for (ALL_LIST_ELEMENTS_RO (funclist, node, functab))
469 if (functab->opaque_type == key)
475 /*------------------------------------------------------------------------*
476 * Followings are management functions for self-originated LSA entries.
477 *------------------------------------------------------------------------*/
480 * Opaque-LSA control information per opaque-type.
481 * Single Opaque-Type may have multiple instances; each of them will be
482 * identified by their opaque-id.
484 struct opaque_info_per_type
489 enum { PROC_NORMAL, PROC_SUSPEND } status;
492 * Thread for (re-)origination scheduling for this opaque-type.
494 * Initial origination of Opaque-LSAs is controlled by generic
495 * Opaque-LSA handling module so that same opaque-type entries are
496 * called all at once when certain conditions are met.
497 * However, there might be cases that some Opaque-LSA clients need
498 * to (re-)originate their own Opaque-LSAs out-of-sync with others.
499 * This thread is prepared for that specific purpose.
501 struct thread *t_opaque_lsa_self;
504 * Backpointer to an "owner" which is LSA-type dependent.
505 * type-9: struct ospf_interface
506 * type-10: struct ospf_area
507 * type-11: struct ospf
511 /* Collection of callback functions for this opaque-type. */
512 struct ospf_opaque_functab *functab;
514 /* List of Opaque-LSA control informations per opaque-id. */
515 struct list *id_list;
518 /* Opaque-LSA control information per opaque-id. */
519 struct opaque_info_per_id
523 /* Thread for refresh/flush scheduling for this opaque-type/id. */
524 struct thread *t_opaque_lsa_self;
526 /* Backpointer to Opaque-LSA control information per opaque-type. */
527 struct opaque_info_per_type *opqctl_type;
529 /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
530 struct ospf_lsa *lsa;
533 static struct opaque_info_per_type *register_opaque_info_per_type (struct ospf_opaque_functab *functab, struct ospf_lsa *new);
534 static struct opaque_info_per_type *lookup_opaque_info_by_type (struct ospf_lsa *lsa);
535 static struct opaque_info_per_id *register_opaque_info_per_id (struct opaque_info_per_type *oipt, struct ospf_lsa *new);
536 static struct opaque_info_per_id *lookup_opaque_info_by_id (struct opaque_info_per_type *oipt, struct ospf_lsa *lsa);
537 static struct opaque_info_per_id *register_opaque_lsa (struct ospf_lsa *new);
540 static struct opaque_info_per_type *
541 register_opaque_info_per_type (struct ospf_opaque_functab *functab,
542 struct ospf_lsa *new)
545 struct opaque_info_per_type *oipt;
547 if ((oipt = XCALLOC (MTYPE_OPAQUE_INFO_PER_TYPE,
548 sizeof (struct opaque_info_per_type))) == NULL)
550 zlog_warn ("register_opaque_info_per_type: XMALLOC: %s", safe_strerror (errno));
554 switch (new->data->type)
556 case OSPF_OPAQUE_LINK_LSA:
557 oipt->owner = new->oi;
558 listnode_add (new->oi->opaque_lsa_self, oipt);
560 case OSPF_OPAQUE_AREA_LSA:
561 oipt->owner = new->area;
562 listnode_add (new->area->opaque_lsa_self, oipt);
564 case OSPF_OPAQUE_AS_LSA:
565 top = ospf_lookup ();
566 if (new->area != NULL && (top = new->area->ospf) == NULL)
568 free_opaque_info_per_type ((void *) oipt);
570 goto out; /* This case may not exist. */
573 listnode_add (top->opaque_lsa_self, oipt);
576 zlog_warn ("register_opaque_info_per_type: Unexpected LSA-type(%u)", new->data->type);
577 free_opaque_info_per_type ((void *) oipt);
579 goto out; /* This case may not exist. */
582 oipt->lsa_type = new->data->type;
583 oipt->opaque_type = GET_OPAQUE_TYPE (ntohl (new->data->id.s_addr));
584 oipt->status = PROC_NORMAL;
585 oipt->t_opaque_lsa_self = NULL;
586 oipt->functab = functab;
587 functab->oipt = oipt;
588 oipt->id_list = list_new ();
589 oipt->id_list->del = free_opaque_info_per_id;
596 free_opaque_info_per_type (void *val)
598 struct opaque_info_per_type *oipt = (struct opaque_info_per_type *) val;
599 struct opaque_info_per_id *oipi;
600 struct ospf_lsa *lsa;
601 struct listnode *node, *nnode;
603 /* Control information per opaque-id may still exist. */
604 for (ALL_LIST_ELEMENTS (oipt->id_list, node, nnode, oipi))
606 if ((lsa = oipi->lsa) == NULL)
608 if (IS_LSA_MAXAGE (lsa))
610 ospf_opaque_lsa_flush_schedule (lsa);
613 /* Remove "oipt" from its owner's self-originated LSA list. */
614 switch (oipt->lsa_type)
616 case OSPF_OPAQUE_LINK_LSA:
618 struct ospf_interface *oi = (struct ospf_interface *)(oipt->owner);
619 listnode_delete (oi->opaque_lsa_self, oipt);
622 case OSPF_OPAQUE_AREA_LSA:
624 struct ospf_area *area = (struct ospf_area *)(oipt->owner);
625 listnode_delete (area->opaque_lsa_self, oipt);
628 case OSPF_OPAQUE_AS_LSA:
630 struct ospf *top = (struct ospf *)(oipt->owner);
631 listnode_delete (top->opaque_lsa_self, oipt);
635 zlog_warn ("free_opaque_info_per_type: Unexpected LSA-type(%u)", oipt->lsa_type);
636 break; /* This case may not exist. */
639 OSPF_TIMER_OFF (oipt->t_opaque_lsa_self);
640 list_delete (oipt->id_list);
641 XFREE (MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
645 static struct opaque_info_per_type *
646 lookup_opaque_info_by_type (struct ospf_lsa *lsa)
649 struct ospf_area *area;
650 struct ospf_interface *oi;
651 struct list *listtop = NULL;
652 struct listnode *node, *nnode;
653 struct opaque_info_per_type *oipt = NULL;
654 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
656 switch (lsa->data->type)
658 case OSPF_OPAQUE_LINK_LSA:
659 if ((oi = lsa->oi) != NULL)
660 listtop = oi->opaque_lsa_self;
662 zlog_warn ("Type-9 Opaque-LSA: Reference to OI is missing?");
664 case OSPF_OPAQUE_AREA_LSA:
665 if ((area = lsa->area) != NULL)
666 listtop = area->opaque_lsa_self;
668 zlog_warn ("Type-10 Opaque-LSA: Reference to AREA is missing?");
670 case OSPF_OPAQUE_AS_LSA:
671 top = ospf_lookup ();
672 if ((area = lsa->area) != NULL && (top = area->ospf) == NULL)
674 zlog_warn ("Type-11 Opaque-LSA: Reference to OSPF is missing?");
675 break; /* Unlikely to happen. */
677 listtop = top->opaque_lsa_self;
680 zlog_warn ("lookup_opaque_info_by_type: Unexpected LSA-type(%u)", lsa->data->type);
685 for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt))
686 if (oipt->opaque_type == key)
692 static struct opaque_info_per_id *
693 register_opaque_info_per_id (struct opaque_info_per_type *oipt,
694 struct ospf_lsa *new)
696 struct opaque_info_per_id *oipi;
698 if ((oipi = XCALLOC (MTYPE_OPAQUE_INFO_PER_ID,
699 sizeof (struct opaque_info_per_id))) == NULL)
701 zlog_warn ("register_opaque_info_per_id: XMALLOC: %s", safe_strerror (errno));
704 oipi->opaque_id = GET_OPAQUE_ID (ntohl (new->data->id.s_addr));
705 oipi->t_opaque_lsa_self = NULL;
706 oipi->opqctl_type = oipt;
707 oipi->lsa = ospf_lsa_lock (new);
709 listnode_add (oipt->id_list, oipi);
716 free_opaque_info_per_id (void *val)
718 struct opaque_info_per_id *oipi = (struct opaque_info_per_id *) val;
720 OSPF_TIMER_OFF (oipi->t_opaque_lsa_self);
721 if (oipi->lsa != NULL)
722 ospf_lsa_unlock (&oipi->lsa);
723 XFREE (MTYPE_OPAQUE_INFO_PER_ID, oipi);
727 static struct opaque_info_per_id *
728 lookup_opaque_info_by_id (struct opaque_info_per_type *oipt,
729 struct ospf_lsa *lsa)
731 struct listnode *node, *nnode;
732 struct opaque_info_per_id *oipi;
733 u_int32_t key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
735 for (ALL_LIST_ELEMENTS (oipt->id_list, node, nnode, oipi))
736 if (oipi->opaque_id == key)
742 static struct opaque_info_per_id *
743 register_opaque_lsa (struct ospf_lsa *new)
745 struct ospf_opaque_functab *functab;
746 struct opaque_info_per_type *oipt;
747 struct opaque_info_per_id *oipi = NULL;
749 if ((functab = ospf_opaque_functab_lookup (new)) == NULL)
752 if ((oipt = lookup_opaque_info_by_type (new)) == NULL
753 && (oipt = register_opaque_info_per_type (functab, new)) == NULL)
756 if ((oipi = register_opaque_info_per_id (oipt, new)) == NULL)
763 /*------------------------------------------------------------------------*
764 * Followings are (vty) configuration functions for Opaque-LSAs handling.
765 *------------------------------------------------------------------------*/
767 DEFUN (capability_opaque,
768 capability_opaque_cmd,
770 "Enable specific OSPF feature\n"
773 struct ospf *ospf = (struct ospf *) vty->index;
775 /* Turn on the "master switch" of opaque-lsa capability. */
776 if (!CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
778 if (IS_DEBUG_OSPF_EVENT)
779 zlog_debug ("Opaque capability: OFF -> ON");
781 SET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
782 ospf_renegotiate_optional_capabilities (ospf);
787 ALIAS (capability_opaque,
788 ospf_opaque_capable_cmd,
790 "OSPF specific commands\n"
791 "Enable the Opaque-LSA capability (rfc2370)\n")
793 DEFUN (no_capability_opaque,
794 no_capability_opaque_cmd,
795 "no capability opaque",
797 "Enable specific OSPF feature\n"
800 struct ospf *ospf = (struct ospf *) vty->index;
802 /* Turn off the "master switch" of opaque-lsa capability. */
803 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
805 if (IS_DEBUG_OSPF_EVENT)
806 zlog_debug ("Opaque capability: ON -> OFF");
808 UNSET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
809 ospf_renegotiate_optional_capabilities (ospf);
814 ALIAS (no_capability_opaque,
815 no_ospf_opaque_capable_cmd,
816 "no ospf opaque-lsa",
818 "OSPF specific commands\n"
819 "Disable the Opaque-LSA capability (rfc2370)\n")
822 ospf_opaque_register_vty (void)
824 install_element (OSPF_NODE, &capability_opaque_cmd);
825 install_element (OSPF_NODE, &no_capability_opaque_cmd);
826 install_element (OSPF_NODE, &ospf_opaque_capable_cmd);
827 install_element (OSPF_NODE, &no_ospf_opaque_capable_cmd);
831 /*------------------------------------------------------------------------*
832 * Followings are collection of user-registered function callers.
833 *------------------------------------------------------------------------*/
836 opaque_lsa_new_if_callback (struct list *funclist, struct interface *ifp)
838 struct listnode *node, *nnode;
839 struct ospf_opaque_functab *functab;
842 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
843 if (functab->new_if_hook != NULL)
844 if ((* functab->new_if_hook)(ifp) != 0)
852 opaque_lsa_del_if_callback (struct list *funclist, struct interface *ifp)
854 struct listnode *node, *nnode;
855 struct ospf_opaque_functab *functab;
858 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
859 if (functab->del_if_hook != NULL)
860 if ((* functab->del_if_hook)(ifp) != 0)
868 opaque_lsa_ism_change_callback (struct list *funclist,
869 struct ospf_interface *oi, int old_status)
871 struct listnode *node, *nnode;
872 struct ospf_opaque_functab *functab;
874 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
875 if (functab->ism_change_hook != NULL)
876 (* functab->ism_change_hook)(oi, old_status);
882 opaque_lsa_nsm_change_callback (struct list *funclist,
883 struct ospf_neighbor *nbr, int old_status)
885 struct listnode *node, *nnode;
886 struct ospf_opaque_functab *functab;
888 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
889 if (functab->nsm_change_hook != NULL)
890 (* functab->nsm_change_hook)(nbr, old_status);
895 opaque_lsa_config_write_router_callback (struct list *funclist,
898 struct listnode *node, *nnode;
899 struct ospf_opaque_functab *functab;
901 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
902 if (functab->config_write_router != NULL)
903 (* functab->config_write_router)(vty);
908 opaque_lsa_config_write_if_callback (struct list *funclist,
909 struct vty *vty, struct interface *ifp)
911 struct listnode *node, *nnode;
912 struct ospf_opaque_functab *functab;
914 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
915 if (functab->config_write_if != NULL)
916 (* functab->config_write_if)(vty, ifp);
921 opaque_lsa_config_write_debug_callback (struct list *funclist, struct vty *vty)
923 struct listnode *node, *nnode;
924 struct ospf_opaque_functab *functab;
926 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
927 if (functab->config_write_debug != NULL)
928 (* functab->config_write_debug)(vty);
933 opaque_lsa_originate_callback (struct list *funclist, void *lsa_type_dependent)
935 struct listnode *node, *nnode;
936 struct ospf_opaque_functab *functab;
939 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
940 if (functab->lsa_originator != NULL)
941 if ((* functab->lsa_originator)(lsa_type_dependent) != 0)
949 new_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
951 struct listnode *node, *nnode;
952 struct ospf_opaque_functab *functab;
955 /* This function handles ALL types of LSAs, not only opaque ones. */
956 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
957 if (functab->new_lsa_hook != NULL)
958 if ((* functab->new_lsa_hook)(lsa) != 0)
966 del_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
968 struct listnode *node, *nnode;
969 struct ospf_opaque_functab *functab;
972 /* This function handles ALL types of LSAs, not only opaque ones. */
973 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
974 if (functab->del_lsa_hook != NULL)
975 if ((* functab->del_lsa_hook)(lsa) != 0)
982 /*------------------------------------------------------------------------*
983 * Followings are glue functions to call Opaque-LSA specific processing.
984 *------------------------------------------------------------------------*/
987 ospf_opaque_new_if (struct interface *ifp)
989 struct list *funclist;
992 funclist = ospf_opaque_wildcard_funclist;
993 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
996 funclist = ospf_opaque_type9_funclist;
997 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
1000 funclist = ospf_opaque_type10_funclist;
1001 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
1004 funclist = ospf_opaque_type11_funclist;
1005 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
1014 ospf_opaque_del_if (struct interface *ifp)
1016 struct list *funclist;
1019 funclist = ospf_opaque_wildcard_funclist;
1020 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1023 funclist = ospf_opaque_type9_funclist;
1024 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1027 funclist = ospf_opaque_type10_funclist;
1028 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1031 funclist = ospf_opaque_type11_funclist;
1032 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1041 ospf_opaque_ism_change (struct ospf_interface *oi, int old_status)
1043 struct list *funclist;
1045 funclist = ospf_opaque_wildcard_funclist;
1046 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1048 funclist = ospf_opaque_type9_funclist;
1049 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1051 funclist = ospf_opaque_type10_funclist;
1052 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1054 funclist = ospf_opaque_type11_funclist;
1055 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1061 ospf_opaque_nsm_change (struct ospf_neighbor *nbr, int old_state)
1064 struct list *funclist;
1066 if ((top = oi_to_top (nbr->oi)) == NULL)
1069 if (old_state != NSM_Full && nbr->state == NSM_Full)
1071 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
1073 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1075 if (IS_DEBUG_OSPF_EVENT)
1076 zlog_debug ("Opaque-LSA: Now get operational!");
1078 SET_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT);
1081 ospf_opaque_lsa_originate_schedule (nbr->oi, NULL);
1085 if (old_state == NSM_Full && nbr->state != NSM_Full)
1089 * If no more opaque-capable full-state neighbor remains in the
1090 * flooding scope which corresponds to Opaque-LSA type, periodic
1091 * LS flooding should be stopped.
1097 funclist = ospf_opaque_wildcard_funclist;
1098 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1100 funclist = ospf_opaque_type9_funclist;
1101 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1103 funclist = ospf_opaque_type10_funclist;
1104 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1106 funclist = ospf_opaque_type11_funclist;
1107 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1114 ospf_opaque_config_write_router (struct vty *vty, struct ospf *ospf)
1116 struct list *funclist;
1118 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
1119 vty_out (vty, " capability opaque%s", VTY_NEWLINE);
1121 funclist = ospf_opaque_wildcard_funclist;
1122 opaque_lsa_config_write_router_callback (funclist, vty);
1124 funclist = ospf_opaque_type9_funclist;
1125 opaque_lsa_config_write_router_callback (funclist, vty);
1127 funclist = ospf_opaque_type10_funclist;
1128 opaque_lsa_config_write_router_callback (funclist, vty);
1130 funclist = ospf_opaque_type11_funclist;
1131 opaque_lsa_config_write_router_callback (funclist, vty);
1137 ospf_opaque_config_write_if (struct vty *vty, struct interface *ifp)
1139 struct list *funclist;
1141 funclist = ospf_opaque_wildcard_funclist;
1142 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1144 funclist = ospf_opaque_type9_funclist;
1145 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1147 funclist = ospf_opaque_type10_funclist;
1148 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1150 funclist = ospf_opaque_type11_funclist;
1151 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1157 ospf_opaque_config_write_debug (struct vty *vty)
1159 struct list *funclist;
1161 funclist = ospf_opaque_wildcard_funclist;
1162 opaque_lsa_config_write_debug_callback (funclist, vty);
1164 funclist = ospf_opaque_type9_funclist;
1165 opaque_lsa_config_write_debug_callback (funclist, vty);
1167 funclist = ospf_opaque_type10_funclist;
1168 opaque_lsa_config_write_debug_callback (funclist, vty);
1170 funclist = ospf_opaque_type11_funclist;
1171 opaque_lsa_config_write_debug_callback (funclist, vty);
1177 show_opaque_info_detail (struct vty *vty, struct ospf_lsa *lsa)
1179 struct lsa_header *lsah = (struct lsa_header *) lsa->data;
1180 u_int32_t lsid = ntohl (lsah->id.s_addr);
1181 u_char opaque_type = GET_OPAQUE_TYPE (lsid);
1182 u_int32_t opaque_id = GET_OPAQUE_ID (lsid);
1183 struct ospf_opaque_functab *functab;
1185 /* Switch output functionality by vty address. */
1188 vty_out (vty, " Opaque-Type %u (%s)%s", opaque_type,
1189 ospf_opaque_type_name (opaque_type), VTY_NEWLINE);
1190 vty_out (vty, " Opaque-ID 0x%x%s", opaque_id, VTY_NEWLINE);
1192 vty_out (vty, " Opaque-Info: %u octets of data%s%s",
1193 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1194 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)",
1199 zlog_debug (" Opaque-Type %u (%s)", opaque_type,
1200 ospf_opaque_type_name (opaque_type));
1201 zlog_debug (" Opaque-ID 0x%x", opaque_id);
1203 zlog_debug (" Opaque-Info: %u octets of data%s",
1204 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1205 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)");
1208 /* Call individual output functions. */
1209 if ((functab = ospf_opaque_functab_lookup (lsa)) != NULL)
1210 if (functab->show_opaque_info != NULL)
1211 (* functab->show_opaque_info)(vty, lsa);
1217 ospf_opaque_lsa_dump (struct stream *s, u_int16_t length)
1219 struct ospf_lsa lsa;
1221 lsa.data = (struct lsa_header *) STREAM_PNT (s);
1222 show_opaque_info_detail (NULL, &lsa);
1227 ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa)
1229 struct list *funclist;
1233 * Some Opaque-LSA user may want to monitor every LSA installation
1234 * into the LSDB, regardless with target LSA type.
1236 funclist = ospf_opaque_wildcard_funclist;
1237 if (new_lsa_callback (funclist, lsa) != 0)
1240 funclist = ospf_opaque_type9_funclist;
1241 if (new_lsa_callback (funclist, lsa) != 0)
1244 funclist = ospf_opaque_type10_funclist;
1245 if (new_lsa_callback (funclist, lsa) != 0)
1248 funclist = ospf_opaque_type11_funclist;
1249 if (new_lsa_callback (funclist, lsa) != 0)
1258 ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa)
1260 struct list *funclist;
1264 * Some Opaque-LSA user may want to monitor every LSA deletion
1265 * from the LSDB, regardless with target LSA type.
1267 funclist = ospf_opaque_wildcard_funclist;
1268 if (del_lsa_callback (funclist, lsa) != 0)
1271 funclist = ospf_opaque_type9_funclist;
1272 if (del_lsa_callback (funclist, lsa) != 0)
1275 funclist = ospf_opaque_type10_funclist;
1276 if (del_lsa_callback (funclist, lsa) != 0)
1279 funclist = ospf_opaque_type11_funclist;
1280 if (del_lsa_callback (funclist, lsa) != 0)
1288 /*------------------------------------------------------------------------*
1289 * Followings are Opaque-LSA origination/refresh management functions.
1290 *------------------------------------------------------------------------*/
1292 static int ospf_opaque_type9_lsa_originate (struct thread *t);
1293 static int ospf_opaque_type10_lsa_originate (struct thread *t);
1294 static int ospf_opaque_type11_lsa_originate (struct thread *t);
1295 static void ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg);
1298 ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0)
1301 struct ospf_area *area;
1302 struct listnode *node, *nnode;
1303 struct opaque_info_per_type *oipt;
1306 if ((top = oi_to_top (oi)) == NULL || (area = oi->area) == NULL)
1308 zlog_warn ("ospf_opaque_lsa_originate_schedule: Invalid argument?");
1312 /* It may not a right time to schedule origination now. */
1313 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1315 if (IS_DEBUG_OSPF_EVENT)
1316 zlog_debug ("ospf_opaque_lsa_originate_schedule: Not operational.");
1317 goto out; /* This is not an error. */
1324 * There might be some entries that have been waiting for triggering
1325 * of per opaque-type re-origination get resumed.
1327 ospf_opaque_lsa_reoriginate_resume ( oi->opaque_lsa_self, (void *) oi);
1328 ospf_opaque_lsa_reoriginate_resume (area->opaque_lsa_self, (void *) area);
1329 ospf_opaque_lsa_reoriginate_resume ( top->opaque_lsa_self, (void *) top);
1332 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1334 if (! list_isempty (ospf_opaque_type9_funclist)
1335 && list_isempty (oi->opaque_lsa_self)
1336 && oi->t_opaque_lsa_self == NULL)
1338 if (IS_DEBUG_OSPF_EVENT)
1339 zlog_debug ("Schedule Type-9 Opaque-LSA origination in %d ms later.", delay);
1340 oi->t_opaque_lsa_self =
1341 thread_add_timer_msec (master, ospf_opaque_type9_lsa_originate, oi, delay);
1342 delay += top->min_ls_interval;
1345 if (! list_isempty (ospf_opaque_type10_funclist)
1346 && list_isempty (area->opaque_lsa_self)
1347 && area->t_opaque_lsa_self == NULL)
1350 * One AREA may contain multiple OIs, but above 2nd and 3rd
1351 * conditions prevent from scheduling the originate function
1354 if (IS_DEBUG_OSPF_EVENT)
1355 zlog_debug ("Schedule Type-10 Opaque-LSA origination in %d ms later.", delay);
1356 area->t_opaque_lsa_self =
1357 thread_add_timer_msec (master, ospf_opaque_type10_lsa_originate,
1359 delay += top->min_ls_interval;
1362 if (! list_isempty (ospf_opaque_type11_funclist)
1363 && list_isempty (top->opaque_lsa_self)
1364 && top->t_opaque_lsa_self == NULL)
1367 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1368 * conditions prevent from scheduling the originate function
1371 if (IS_DEBUG_OSPF_EVENT)
1372 zlog_debug ("Schedule Type-11 Opaque-LSA origination in %d ms later.", delay);
1373 top->t_opaque_lsa_self =
1374 thread_add_timer_msec (master, ospf_opaque_type11_lsa_originate,
1376 delay += top->min_ls_interval;
1380 * Following section treats a special situation that this node's
1381 * opaque capability has changed as "ON -> OFF -> ON".
1383 if (! list_isempty (ospf_opaque_type9_funclist)
1384 && ! list_isempty (oi->opaque_lsa_self))
1386 for (ALL_LIST_ELEMENTS (oi->opaque_lsa_self, node, nnode, oipt))
1389 * removed the test for
1390 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1391 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1394 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1395 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
1398 ospf_opaque_lsa_reoriginate_schedule ((void *) oi,
1399 OSPF_OPAQUE_LINK_LSA, oipt->opaque_type);
1403 if (! list_isempty (ospf_opaque_type10_funclist)
1404 && ! list_isempty (area->opaque_lsa_self))
1406 for (ALL_LIST_ELEMENTS (area->opaque_lsa_self, node, nnode, oipt))
1409 * removed the test for
1410 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1411 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1414 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1415 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
1418 ospf_opaque_lsa_reoriginate_schedule ((void *) area,
1419 OSPF_OPAQUE_AREA_LSA, oipt->opaque_type);
1423 if (! list_isempty (ospf_opaque_type11_funclist)
1424 && ! list_isempty (top->opaque_lsa_self))
1426 for (ALL_LIST_ELEMENTS (top->opaque_lsa_self, node, nnode, oipt))
1429 * removed the test for
1430 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1431 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1434 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1435 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
1438 ospf_opaque_lsa_reoriginate_schedule ((void *) top,
1439 OSPF_OPAQUE_AS_LSA, oipt->opaque_type);
1451 ospf_opaque_type9_lsa_originate (struct thread *t)
1453 struct ospf_interface *oi;
1456 oi = THREAD_ARG (t);
1457 oi->t_opaque_lsa_self = NULL;
1459 if (IS_DEBUG_OSPF_EVENT)
1460 zlog_debug ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
1463 rc = opaque_lsa_originate_callback (ospf_opaque_type9_funclist, oi);
1469 ospf_opaque_type10_lsa_originate (struct thread *t)
1471 struct ospf_area *area;
1474 area = THREAD_ARG (t);
1475 area->t_opaque_lsa_self = NULL;
1477 if (IS_DEBUG_OSPF_EVENT)
1478 zlog_debug ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
1479 inet_ntoa (area->area_id));
1481 rc = opaque_lsa_originate_callback (ospf_opaque_type10_funclist, area);
1487 ospf_opaque_type11_lsa_originate (struct thread *t)
1492 top = THREAD_ARG (t);
1493 top->t_opaque_lsa_self = NULL;
1495 if (IS_DEBUG_OSPF_EVENT)
1496 zlog_debug ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
1498 rc = opaque_lsa_originate_callback (ospf_opaque_type11_funclist, top);
1504 ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg)
1506 struct listnode *node, *nnode;
1507 struct opaque_info_per_type *oipt;
1508 struct ospf_opaque_functab *functab;
1510 if (listtop == NULL)
1514 * Pickup oipt entries those which in SUSPEND status, and give
1515 * them a chance to start re-origination now.
1517 for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt))
1519 if (oipt->status != PROC_SUSPEND)
1522 oipt->status = PROC_NORMAL;
1524 if ((functab = oipt->functab) == NULL
1525 || functab->lsa_originator == NULL)
1528 if ((* functab->lsa_originator)(arg) != 0)
1530 zlog_warn ("ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", oipt->opaque_type);
1540 ospf_opaque_lsa_install (struct ospf_lsa *lsa, int rt_recalc)
1542 struct ospf_lsa *new = NULL;
1543 struct opaque_info_per_type *oipt;
1544 struct opaque_info_per_id *oipi;
1547 /* Don't take "rt_recalc" into consideration for now. *//* XXX */
1549 if (! IS_LSA_SELF (lsa))
1551 new = lsa; /* Don't touch this LSA. */
1555 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
1556 zlog_debug ("Install Type-%u Opaque-LSA: [opaque-type=%u, opaque-id=%x]", lsa->data->type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)));
1558 /* Replace the existing lsa with the new one. */
1559 if ((oipt = lookup_opaque_info_by_type (lsa)) != NULL
1560 && (oipi = lookup_opaque_info_by_id (oipt, lsa)) != NULL)
1562 ospf_lsa_unlock (&oipi->lsa);
1563 oipi->lsa = ospf_lsa_lock (lsa);
1565 /* Register the new lsa entry and get its control info. */
1567 if ((oipi = register_opaque_lsa (lsa)) == NULL)
1569 zlog_warn ("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1574 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1575 * for periodic refresh of self-originated Opaque-LSAs.
1577 switch (lsa->data->type)
1579 case OSPF_OPAQUE_LINK_LSA:
1580 if ((top = oi_to_top (lsa->oi)) == NULL)
1582 /* Above conditions must have passed. */
1583 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1587 case OSPF_OPAQUE_AREA_LSA:
1588 if (lsa->area == NULL || (top = lsa->area->ospf) == NULL)
1590 /* Above conditions must have passed. */
1591 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1595 case OSPF_OPAQUE_AS_LSA:
1596 top = ospf_lookup ();
1597 if (lsa->area != NULL && (top = lsa->area->ospf) == NULL)
1599 /* Above conditions must have passed. */
1600 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1605 zlog_warn ("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", lsa->data->type);
1609 ospf_refresher_register_lsa (top, lsa);
1617 ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
1620 struct ospf_opaque_functab *functab;
1621 struct ospf_lsa *new = NULL;
1623 ospf = ospf_lookup ();
1625 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL
1626 || functab->lsa_refresher == NULL)
1629 * Though this LSA seems to have originated on this node, the
1630 * handling module for this "lsa-type and opaque-type" was
1631 * already deleted sometime ago.
1632 * Anyway, this node still has a responsibility to flush this
1633 * LSA from the routing domain.
1635 if (IS_DEBUG_OSPF_EVENT)
1636 zlog_debug ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id));
1638 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
1639 ospf_lsa_flush (ospf, lsa);
1642 new = (* functab->lsa_refresher)(lsa);
1647 /*------------------------------------------------------------------------*
1648 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1649 * triggered by external interventions (vty session, signaling, etc).
1650 *------------------------------------------------------------------------*/
1652 #define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
1654 (T) = thread_add_timer_msec (master, (F), (L), (V))
1656 static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type);
1657 static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t);
1658 static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t);
1659 static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t);
1660 static int ospf_opaque_lsa_refresh_timer (struct thread *t);
1663 ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
1664 u_char lsa_type, u_char opaque_type)
1667 struct ospf_area dummy, *area = NULL;
1668 struct ospf_interface *oi = NULL;
1670 struct ospf_lsa *lsa;
1671 struct opaque_info_per_type *oipt;
1672 int (*func) (struct thread * t) = NULL;
1677 case OSPF_OPAQUE_LINK_LSA:
1678 if ((oi = (struct ospf_interface *) lsa_type_dependent) == NULL)
1680 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1681 " Type-9 Opaque-LSA: Invalid parameter?");
1684 if ((top = oi_to_top (oi)) == NULL)
1686 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1690 if (!list_isempty (ospf_opaque_type9_funclist)
1691 && list_isempty (oi->opaque_lsa_self)
1692 && oi->t_opaque_lsa_self != NULL)
1694 zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u):"
1695 " Common origination for OI(%s) has already started",
1696 opaque_type, IF_NAME (oi));
1699 func = ospf_opaque_type9_lsa_reoriginate_timer;
1701 case OSPF_OPAQUE_AREA_LSA:
1702 if ((area = (struct ospf_area *) lsa_type_dependent) == NULL)
1704 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1705 " Type-10 Opaque-LSA: Invalid parameter?");
1708 if ((top = area->ospf) == NULL)
1710 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1711 " AREA(%s) -> TOP?", inet_ntoa (area->area_id));
1714 if (!list_isempty (ospf_opaque_type10_funclist)
1715 && list_isempty (area->opaque_lsa_self)
1716 && area->t_opaque_lsa_self != NULL)
1718 zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u):"
1719 " Common origination for AREA(%s) has already started",
1720 opaque_type, inet_ntoa (area->area_id));
1723 func = ospf_opaque_type10_lsa_reoriginate_timer;
1725 case OSPF_OPAQUE_AS_LSA:
1726 if ((top = (struct ospf *) lsa_type_dependent) == NULL)
1728 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1729 " Type-11 Opaque-LSA: Invalid parameter?");
1732 if (!list_isempty (ospf_opaque_type11_funclist)
1733 && list_isempty (top->opaque_lsa_self)
1734 && top->t_opaque_lsa_self != NULL)
1736 zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u):"
1737 " Common origination has already started", opaque_type);
1741 /* Fake "area" to pass "ospf" to a lookup function later. */
1745 func = ospf_opaque_type11_lsa_reoriginate_timer;
1748 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1749 " Unexpected LSA-type(%u)",
1754 /* It may not a right time to schedule reorigination now. */
1755 if (!CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1757 if (IS_DEBUG_OSPF_EVENT)
1758 zlog_debug ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
1759 goto out; /* This is not an error. */
1762 /* Generate a dummy lsa to be passed for a lookup function. */
1763 lsa = pseudo_lsa (oi, area, lsa_type, opaque_type);
1765 if ((oipt = lookup_opaque_info_by_type (lsa)) == NULL)
1767 struct ospf_opaque_functab *functab;
1768 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL)
1770 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1771 " No associated function?: lsa_type(%u),"
1773 lsa_type, opaque_type);
1776 if ((oipt = register_opaque_info_per_type (functab, lsa)) == NULL)
1778 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1779 " Cannot get a control info?: lsa_type(%u),"
1781 lsa_type, opaque_type);
1786 if (oipt->t_opaque_lsa_self != NULL)
1788 if (IS_DEBUG_OSPF_EVENT)
1789 zlog_debug ("Type-%u Opaque-LSA has already scheduled to"
1790 " RE-ORIGINATE: [opaque-type=%u]",
1791 lsa_type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
1796 * Different from initial origination time, in which various conditions
1797 * (opaque capability, neighbor status etc) are assured by caller of
1798 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1799 * it is highly possible that these conditions might not be satisfied
1800 * at the time of re-origination function is to be called.
1802 delay = top->min_ls_interval; /* XXX */
1804 if (IS_DEBUG_OSPF_EVENT)
1805 zlog_debug ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
1806 " ms later: [opaque-type=%u]",
1808 GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
1810 OSPF_OPAQUE_TIMER_ON (oipt->t_opaque_lsa_self, func, oipt, delay);
1816 static struct ospf_lsa *
1817 pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area,
1818 u_char lsa_type, u_char opaque_type)
1820 static struct ospf_lsa lsa = { 0 };
1821 static struct lsa_header lsah = { 0 };
1828 lsah.type = lsa_type;
1829 tmp = SET_OPAQUE_LSID (opaque_type, 0); /* Opaque-ID is unused here. */
1830 lsah.id.s_addr = htonl (tmp);
1836 ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t)
1838 struct opaque_info_per_type *oipt;
1839 struct ospf_opaque_functab *functab;
1841 struct ospf_interface *oi;
1844 oipt = THREAD_ARG (t);
1845 oipt->t_opaque_lsa_self = NULL;
1847 if ((functab = oipt->functab) == NULL
1848 || functab->lsa_originator == NULL)
1850 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1854 oi = (struct ospf_interface *) oipt->owner;
1855 if ((top = oi_to_top (oi)) == NULL)
1857 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1861 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)
1862 || ! ospf_if_is_enable (oi)
1863 || ospf_nbr_count_opaque_capable (oi) == 0)
1865 if (IS_DEBUG_OSPF_EVENT)
1866 zlog_debug ("Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
1868 oipt->status = PROC_SUSPEND;
1873 if (IS_DEBUG_OSPF_EVENT)
1874 zlog_debug ("Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)", oipt->opaque_type, IF_NAME (oi));
1876 rc = (* functab->lsa_originator)(oi);
1882 ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t)
1884 struct opaque_info_per_type *oipt;
1885 struct ospf_opaque_functab *functab;
1886 struct listnode *node, *nnode;
1888 struct ospf_area *area;
1889 struct ospf_interface *oi;
1892 oipt = THREAD_ARG (t);
1893 oipt->t_opaque_lsa_self = NULL;
1895 if ((functab = oipt->functab) == NULL
1896 || functab->lsa_originator == NULL)
1898 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1902 area = (struct ospf_area *) oipt->owner;
1903 if (area == NULL || (top = area->ospf) == NULL)
1905 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1909 /* There must be at least one "opaque-capable, full-state" neighbor. */
1911 for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi))
1913 if ((n = ospf_nbr_count_opaque_capable (oi)) > 0)
1917 if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1919 if (IS_DEBUG_OSPF_EVENT)
1920 zlog_debug ("Suspend re-origination of Type-10 Opaque-LSAs"
1921 " (opaque-type=%u) for a while...",
1924 oipt->status = PROC_SUSPEND;
1929 if (IS_DEBUG_OSPF_EVENT)
1930 zlog_debug ("Timer[Type10-LSA]: Re-originate Opaque-LSAs"
1931 " (opaque-type=%u) for Area %s",
1932 oipt->opaque_type, inet_ntoa (area->area_id));
1934 rc = (* functab->lsa_originator)(area);
1940 ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t)
1942 struct opaque_info_per_type *oipt;
1943 struct ospf_opaque_functab *functab;
1947 oipt = THREAD_ARG (t);
1948 oipt->t_opaque_lsa_self = NULL;
1950 if ((functab = oipt->functab) == NULL
1951 || functab->lsa_originator == NULL)
1953 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer:"
1954 " No associated function?");
1958 if ((top = (struct ospf *) oipt->owner) == NULL)
1960 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1964 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1966 if (IS_DEBUG_OSPF_EVENT)
1967 zlog_debug ("Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
1969 oipt->status = PROC_SUSPEND;
1974 if (IS_DEBUG_OSPF_EVENT)
1975 zlog_debug ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type);
1977 rc = (* functab->lsa_originator)(top);
1983 ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
1985 struct opaque_info_per_type *oipt;
1986 struct opaque_info_per_id *oipi;
1987 struct ospf_lsa *lsa;
1991 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
1992 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
1994 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
1998 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
1999 if ((lsa = oipi->lsa) == NULL)
2001 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
2005 if (oipi->t_opaque_lsa_self != NULL)
2007 if (IS_DEBUG_OSPF_EVENT)
2008 zlog_debug ("Type-%u Opaque-LSA has already scheduled to REFRESH: [opaque-type=%u, opaque-id=%x]", lsa->data->type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)));
2012 /* Delete this lsa from neighbor retransmit-list. */
2013 switch (lsa->data->type)
2015 case OSPF_OPAQUE_LINK_LSA:
2016 case OSPF_OPAQUE_AREA_LSA:
2017 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
2019 case OSPF_OPAQUE_AS_LSA:
2020 top = ospf_lookup ();
2021 if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
2022 top = lsa0->area->ospf;
2023 ospf_ls_retransmit_delete_nbr_as (top, lsa);
2026 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2030 delay = ospf_lsa_refresh_delay (lsa);
2032 if (IS_DEBUG_OSPF_EVENT)
2033 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)));
2035 OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self,
2036 ospf_opaque_lsa_refresh_timer, oipi, delay * 1000);
2042 ospf_opaque_lsa_refresh_timer (struct thread *t)
2044 struct opaque_info_per_id *oipi;
2045 struct ospf_opaque_functab *functab;
2046 struct ospf_lsa *lsa;
2048 if (IS_DEBUG_OSPF_EVENT)
2049 zlog_debug ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
2051 oipi = THREAD_ARG (t);
2052 oipi->t_opaque_lsa_self = NULL;
2054 if ((lsa = oipi->lsa) != NULL)
2055 if ((functab = oipi->opqctl_type->functab) != NULL)
2056 if (functab->lsa_refresher != NULL)
2057 (* functab->lsa_refresher)(lsa);
2063 ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
2065 struct opaque_info_per_type *oipt;
2066 struct opaque_info_per_id *oipi;
2067 struct ospf_lsa *lsa;
2070 top = ospf_lookup ();
2072 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
2073 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
2075 zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2079 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2080 if ((lsa = oipi->lsa) == NULL)
2082 zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
2086 /* Delete this lsa from neighbor retransmit-list. */
2087 switch (lsa->data->type)
2089 case OSPF_OPAQUE_LINK_LSA:
2090 case OSPF_OPAQUE_AREA_LSA:
2091 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
2093 case OSPF_OPAQUE_AS_LSA:
2094 if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
2095 top = lsa0->area->ospf;
2096 ospf_ls_retransmit_delete_nbr_as (top, lsa);
2099 zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2103 /* Dequeue listnode entry from the list. */
2104 listnode_delete (oipt->id_list, oipi);
2106 /* Avoid misjudgement in the next lookup. */
2107 if (listcount (oipt->id_list) == 0)
2108 oipt->id_list->head = oipt->id_list->tail = NULL;
2110 /* Disassociate internal control information with the given lsa. */
2111 free_opaque_info_per_id ((void *) oipi);
2113 /* Force given lsa's age to MaxAge. */
2114 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2116 if (IS_DEBUG_OSPF_EVENT)
2117 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)));
2119 /* This lsa will be flushed and removed eventually. */
2120 ospf_lsa_flush (top, lsa);
2127 ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr,
2128 struct ospf_lsa *lsa)
2132 if ((top = oi_to_top (nbr->oi)) == NULL)
2136 * Since these LSA entries are not yet installed into corresponding
2137 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2139 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2140 switch (lsa->data->type)
2142 case OSPF_OPAQUE_LINK_LSA:
2143 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2145 case OSPF_OPAQUE_AREA_LSA:
2146 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2148 case OSPF_OPAQUE_AS_LSA:
2149 ospf_flood_through_as (top, NULL/*inbr*/, lsa);
2152 zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
2155 ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */
2158 /*------------------------------------------------------------------------*
2159 * Followings are util functions; probably be used by Opaque-LSAs only...
2160 *------------------------------------------------------------------------*/
2163 oi_to_top (struct ospf_interface *oi)
2165 struct ospf *top = NULL;
2166 struct ospf_area *area;
2168 if (oi == NULL || (area = oi->area) == NULL || (top = area->ospf) == NULL)
2169 zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");