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 along
19 * with this program; see the file COPYING; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
36 #include "sockunion.h" /* for inet_aton() */
38 #include "ospfd/ospfd.h"
39 #include "ospfd/ospf_interface.h"
40 #include "ospfd/ospf_ism.h"
41 #include "ospfd/ospf_asbr.h"
42 #include "ospfd/ospf_lsa.h"
43 #include "ospfd/ospf_lsdb.h"
44 #include "ospfd/ospf_neighbor.h"
45 #include "ospfd/ospf_nsm.h"
46 #include "ospfd/ospf_flood.h"
47 #include "ospfd/ospf_packet.h"
48 #include "ospfd/ospf_spf.h"
49 #include "ospfd/ospf_dump.h"
50 #include "ospfd/ospf_route.h"
51 #include "ospfd/ospf_ase.h"
52 #include "ospfd/ospf_zebra.h"
53 #include "ospfd/ospf_te.h"
54 #include "ospfd/ospf_sr.h"
55 #include "ospfd/ospf_ri.h"
56 #include "ospfd/ospf_ext.h"
58 DEFINE_MTYPE_STATIC(OSPFD
, OSPF_OPAQUE_FUNCTAB
, "OSPF opaque function table")
59 DEFINE_MTYPE_STATIC(OSPFD
, OPAQUE_INFO_PER_TYPE
, "OSPF opaque per-type info")
60 DEFINE_MTYPE_STATIC(OSPFD
, OPAQUE_INFO_PER_ID
, "OSPF opaque per-ID info")
62 /*------------------------------------------------------------------------*
63 * Followings are initialize/terminate functions for Opaque-LSAs handling.
64 *------------------------------------------------------------------------*/
66 #ifdef SUPPORT_OSPF_API
67 int ospf_apiserver_init(void);
68 void ospf_apiserver_term(void);
69 /* Init apiserver? It's disabled by default. */
70 int ospf_apiserver_enable
;
71 #endif /* SUPPORT_OSPF_API */
73 static void ospf_opaque_register_vty(void);
74 static void ospf_opaque_funclist_init(void);
75 static void ospf_opaque_funclist_term(void);
76 static void free_opaque_info_per_type(void *val
);
77 static void free_opaque_info_per_id(void *val
);
78 static void free_opaque_info_owner(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
);
82 void ospf_opaque_init(void)
84 ospf_opaque_register_vty();
85 ospf_opaque_funclist_init();
87 if (ospf_mpls_te_init() != 0)
90 /* Segment Routing init */
91 if (ospf_sr_init() != 0)
94 if (ospf_router_info_init() != 0)
97 if (ospf_ext_init() != 0)
100 #ifdef SUPPORT_OSPF_API
101 if ((ospf_apiserver_enable
) && (ospf_apiserver_init() != 0))
103 #endif /* SUPPORT_OSPF_API */
108 void ospf_opaque_term(void)
112 ospf_router_info_term();
118 #ifdef SUPPORT_OSPF_API
119 ospf_apiserver_term();
120 #endif /* SUPPORT_OSPF_API */
122 ospf_opaque_funclist_term();
126 void ospf_opaque_finish(void)
128 ospf_router_info_finish();
135 int ospf_opaque_type9_lsa_init(struct ospf_interface
*oi
)
137 if (oi
->opaque_lsa_self
!= NULL
)
138 list_delete_and_null(&oi
->opaque_lsa_self
);
140 oi
->opaque_lsa_self
= list_new();
141 oi
->opaque_lsa_self
->del
= free_opaque_info_per_type
;
142 oi
->t_opaque_lsa_self
= NULL
;
146 void ospf_opaque_type9_lsa_term(struct ospf_interface
*oi
)
148 OSPF_TIMER_OFF(oi
->t_opaque_lsa_self
);
149 if (oi
->opaque_lsa_self
!= NULL
)
150 list_delete_and_null(&oi
->opaque_lsa_self
);
151 oi
->opaque_lsa_self
= NULL
;
155 int ospf_opaque_type10_lsa_init(struct ospf_area
*area
)
157 if (area
->opaque_lsa_self
!= NULL
)
158 list_delete_and_null(&area
->opaque_lsa_self
);
160 area
->opaque_lsa_self
= list_new();
161 area
->opaque_lsa_self
->del
= free_opaque_info_per_type
;
162 area
->t_opaque_lsa_self
= NULL
;
164 #ifdef MONITOR_LSDB_CHANGE
165 area
->lsdb
->new_lsa_hook
= ospf_opaque_lsa_install_hook
;
166 area
->lsdb
->del_lsa_hook
= ospf_opaque_lsa_delete_hook
;
167 #endif /* MONITOR_LSDB_CHANGE */
171 void ospf_opaque_type10_lsa_term(struct ospf_area
*area
)
173 #ifdef MONITOR_LSDB_CHANGE
174 area
->lsdb
->new_lsa_hook
= area
->lsdb
->del_lsa_hook
= NULL
;
175 #endif /* MONITOR_LSDB_CHANGE */
177 OSPF_TIMER_OFF(area
->t_opaque_lsa_self
);
178 if (area
->opaque_lsa_self
!= NULL
)
179 list_delete_and_null(&area
->opaque_lsa_self
);
183 int ospf_opaque_type11_lsa_init(struct ospf
*top
)
185 if (top
->opaque_lsa_self
!= NULL
)
186 list_delete_and_null(&top
->opaque_lsa_self
);
188 top
->opaque_lsa_self
= list_new();
189 top
->opaque_lsa_self
->del
= free_opaque_info_per_type
;
190 top
->t_opaque_lsa_self
= NULL
;
192 #ifdef MONITOR_LSDB_CHANGE
193 top
->lsdb
->new_lsa_hook
= ospf_opaque_lsa_install_hook
;
194 top
->lsdb
->del_lsa_hook
= ospf_opaque_lsa_delete_hook
;
195 #endif /* MONITOR_LSDB_CHANGE */
199 void ospf_opaque_type11_lsa_term(struct ospf
*top
)
201 #ifdef MONITOR_LSDB_CHANGE
202 top
->lsdb
->new_lsa_hook
= top
->lsdb
->del_lsa_hook
= NULL
;
203 #endif /* MONITOR_LSDB_CHANGE */
205 OSPF_TIMER_OFF(top
->t_opaque_lsa_self
);
206 if (top
->opaque_lsa_self
!= NULL
)
207 list_delete_and_null(&top
->opaque_lsa_self
);
211 static const char *ospf_opaque_type_name(uint8_t opaque_type
)
213 const char *name
= "Unknown";
215 switch (opaque_type
) {
216 case OPAQUE_TYPE_WILDCARD
: /* This is a special assignment! */
219 case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA
:
220 name
= "Traffic Engineering LSA";
222 case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC
:
223 name
= "Sycamore optical topology description";
225 case OPAQUE_TYPE_GRACE_LSA
:
228 case OPAQUE_TYPE_INTER_AS_LSA
:
229 name
= "Inter-AS TE-v2 LSA";
231 case OPAQUE_TYPE_ROUTER_INFORMATION_LSA
:
232 name
= "Router Information LSA";
234 case OPAQUE_TYPE_EXTENDED_PREFIX_LSA
:
235 name
= "Extended Prefix Opaque LSA";
237 case OPAQUE_TYPE_EXTENDED_LINK_LSA
:
238 name
= "Extended Link Opaque LSA";
241 if (OPAQUE_TYPE_RANGE_UNASSIGNED(opaque_type
))
244 uint32_t bigger_range
= opaque_type
;
246 * Get around type-limits warning: comparison is always
247 * true due to limited range of data type
249 if (OPAQUE_TYPE_RANGE_RESERVED(bigger_range
))
250 name
= "Private/Experimental";
257 /*------------------------------------------------------------------------*
258 * Followings are management functions to store user specified callbacks.
259 *------------------------------------------------------------------------*/
261 struct opaque_info_per_type
; /* Forward declaration. */
263 struct ospf_opaque_functab
{
265 struct opaque_info_per_type
*oipt
;
267 int (*new_if_hook
)(struct interface
*ifp
);
268 int (*del_if_hook
)(struct interface
*ifp
);
269 void (*ism_change_hook
)(struct ospf_interface
*oi
, int old_status
);
270 void (*nsm_change_hook
)(struct ospf_neighbor
*nbr
, int old_status
);
271 void (*config_write_router
)(struct vty
*vty
);
272 void (*config_write_if
)(struct vty
*vty
, struct interface
*ifp
);
273 void (*config_write_debug
)(struct vty
*vty
);
274 void (*show_opaque_info
)(struct vty
*vty
, struct ospf_lsa
*lsa
);
275 int (*lsa_originator
)(void *arg
);
276 struct ospf_lsa
*(*lsa_refresher
)(struct ospf_lsa
*lsa
);
277 int (*new_lsa_hook
)(struct ospf_lsa
*lsa
);
278 int (*del_lsa_hook
)(struct ospf_lsa
*lsa
);
281 /* Handle LSA-9/10/11 altogether. */
282 static struct list
*ospf_opaque_wildcard_funclist
;
283 static struct list
*ospf_opaque_type9_funclist
;
284 static struct list
*ospf_opaque_type10_funclist
;
285 static struct list
*ospf_opaque_type11_funclist
;
287 static void ospf_opaque_del_functab(void *val
)
289 XFREE(MTYPE_OSPF_OPAQUE_FUNCTAB
, val
);
293 static void ospf_opaque_funclist_init(void)
295 struct list
*funclist
;
297 funclist
= ospf_opaque_wildcard_funclist
= list_new();
298 funclist
->del
= ospf_opaque_del_functab
;
300 funclist
= ospf_opaque_type9_funclist
= list_new();
301 funclist
->del
= ospf_opaque_del_functab
;
303 funclist
= ospf_opaque_type10_funclist
= list_new();
304 funclist
->del
= ospf_opaque_del_functab
;
306 funclist
= ospf_opaque_type11_funclist
= list_new();
307 funclist
->del
= ospf_opaque_del_functab
;
311 static void ospf_opaque_funclist_term(void)
313 struct list
*funclist
;
315 funclist
= ospf_opaque_wildcard_funclist
;
316 list_delete_and_null(&funclist
);
318 funclist
= ospf_opaque_type9_funclist
;
319 list_delete_and_null(&funclist
);
321 funclist
= ospf_opaque_type10_funclist
;
322 list_delete_and_null(&funclist
);
324 funclist
= ospf_opaque_type11_funclist
;
325 list_delete_and_null(&funclist
);
329 static struct list
*ospf_get_opaque_funclist(uint8_t lsa_type
)
331 struct list
*funclist
= NULL
;
334 case OPAQUE_TYPE_WILDCARD
:
336 * This is an ugly trick to handle type-9/10/11 LSA altogether.
337 * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor
338 * an officially assigned opaque-type.
339 * Though it is possible that the value might be officially used
340 * in the future, we use it internally as a special label, for
343 funclist
= ospf_opaque_wildcard_funclist
;
345 case OSPF_OPAQUE_LINK_LSA
:
346 funclist
= ospf_opaque_type9_funclist
;
348 case OSPF_OPAQUE_AREA_LSA
:
349 funclist
= ospf_opaque_type10_funclist
;
351 case OSPF_OPAQUE_AS_LSA
:
352 funclist
= ospf_opaque_type11_funclist
;
355 zlog_warn("ospf_get_opaque_funclist: Unexpected LSA-type(%u)",
362 /* XXX: such a huge argument list can /not/ be healthy... */
363 int ospf_register_opaque_functab(
364 uint8_t lsa_type
, uint8_t opaque_type
,
365 int (*new_if_hook
)(struct interface
*ifp
),
366 int (*del_if_hook
)(struct interface
*ifp
),
367 void (*ism_change_hook
)(struct ospf_interface
*oi
, int old_status
),
368 void (*nsm_change_hook
)(struct ospf_neighbor
*nbr
, int old_status
),
369 void (*config_write_router
)(struct vty
*vty
),
370 void (*config_write_if
)(struct vty
*vty
, struct interface
*ifp
),
371 void (*config_write_debug
)(struct vty
*vty
),
372 void (*show_opaque_info
)(struct vty
*vty
, struct ospf_lsa
*lsa
),
373 int (*lsa_originator
)(void *arg
),
374 struct ospf_lsa
*(*lsa_refresher
)(struct ospf_lsa
*lsa
),
375 int (*new_lsa_hook
)(struct ospf_lsa
*lsa
),
376 int (*del_lsa_hook
)(struct ospf_lsa
*lsa
))
378 struct list
*funclist
;
379 struct ospf_opaque_functab
*new;
382 if ((funclist
= ospf_get_opaque_funclist(lsa_type
)) == NULL
) {
384 "ospf_register_opaque_functab: Cannot get funclist"
385 " for Type-%u LSAs?",
389 struct listnode
*node
, *nnode
;
390 struct ospf_opaque_functab
*functab
;
392 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
393 if (functab
->opaque_type
== opaque_type
) {
395 "ospf_register_opaque_functab: Duplicated entry?:"
396 " lsa_type(%u), opaque_type(%u)",
397 lsa_type
, opaque_type
);
402 new = XCALLOC(MTYPE_OSPF_OPAQUE_FUNCTAB
,
403 sizeof(struct ospf_opaque_functab
));
405 new->opaque_type
= opaque_type
;
407 new->new_if_hook
= new_if_hook
;
408 new->del_if_hook
= del_if_hook
;
409 new->ism_change_hook
= ism_change_hook
;
410 new->nsm_change_hook
= nsm_change_hook
;
411 new->config_write_router
= config_write_router
;
412 new->config_write_if
= config_write_if
;
413 new->config_write_debug
= config_write_debug
;
414 new->show_opaque_info
= show_opaque_info
;
415 new->lsa_originator
= lsa_originator
;
416 new->lsa_refresher
= lsa_refresher
;
417 new->new_lsa_hook
= new_lsa_hook
;
418 new->del_lsa_hook
= del_lsa_hook
;
420 listnode_add(funclist
, new);
427 void ospf_delete_opaque_functab(uint8_t lsa_type
, uint8_t opaque_type
)
429 struct list
*funclist
;
430 struct listnode
*node
, *nnode
;
431 struct ospf_opaque_functab
*functab
;
433 if ((funclist
= ospf_get_opaque_funclist(lsa_type
)) != NULL
)
434 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
)) {
435 if (functab
->opaque_type
== opaque_type
) {
436 /* Cleanup internal control information, if it
438 if (functab
->oipt
!= NULL
) {
439 free_opaque_info_per_type(
441 free_opaque_info_owner(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 uint8_t 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
{
488 enum { PROC_NORMAL
, PROC_SUSPEND
} status
;
491 * Thread for (re-)origination scheduling for this opaque-type.
493 * Initial origination of Opaque-LSAs is controlled by generic
494 * Opaque-LSA handling module so that same opaque-type entries are
495 * called all at once when certain conditions are met.
496 * However, there might be cases that some Opaque-LSA clients need
497 * to (re-)originate their own Opaque-LSAs out-of-sync with others.
498 * This thread is prepared for that specific purpose.
500 struct thread
*t_opaque_lsa_self
;
503 * Backpointer to an "owner" which is LSA-type dependent.
504 * type-9: struct ospf_interface
505 * type-10: struct ospf_area
506 * type-11: struct ospf
510 /* Collection of callback functions for this opaque-type. */
511 struct ospf_opaque_functab
*functab
;
513 /* List of Opaque-LSA control informations per opaque-id. */
514 struct list
*id_list
;
517 /* Opaque-LSA control information per opaque-id. */
518 struct opaque_info_per_id
{
521 /* Thread for refresh/flush scheduling for this opaque-type/id. */
522 struct thread
*t_opaque_lsa_self
;
524 /* Backpointer to Opaque-LSA control information per opaque-type. */
525 struct opaque_info_per_type
*opqctl_type
;
527 /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
528 struct ospf_lsa
*lsa
;
531 static struct opaque_info_per_type
*
532 register_opaque_info_per_type(struct ospf_opaque_functab
*functab
,
533 struct ospf_lsa
*new);
534 static struct opaque_info_per_type
*
535 lookup_opaque_info_by_type(struct ospf_lsa
*lsa
);
536 static struct opaque_info_per_id
*
537 register_opaque_info_per_id(struct opaque_info_per_type
*oipt
,
538 struct ospf_lsa
*new);
539 static struct opaque_info_per_id
*
540 lookup_opaque_info_by_id(struct opaque_info_per_type
*oipt
,
541 struct ospf_lsa
*lsa
);
542 static struct opaque_info_per_id
*register_opaque_lsa(struct ospf_lsa
*new);
545 static struct opaque_info_per_type
*
546 register_opaque_info_per_type(struct ospf_opaque_functab
*functab
,
547 struct ospf_lsa
*new)
550 struct opaque_info_per_type
*oipt
;
552 oipt
= XCALLOC(MTYPE_OPAQUE_INFO_PER_TYPE
,
553 sizeof(struct opaque_info_per_type
));
555 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_by_vrf_id(new->vrf_id
);
566 if (new->area
!= NULL
&& (top
= new->area
->ospf
) == NULL
) {
567 free_opaque_info_per_type((void *)oipt
);
568 free_opaque_info_owner(oipt
);
570 goto out
; /* This case may not exist. */
573 listnode_add(top
->opaque_lsa_self
, oipt
);
577 "register_opaque_info_per_type: Unexpected LSA-type(%u)",
579 free_opaque_info_per_type((void *)oipt
);
580 free_opaque_info_owner(oipt
);
582 goto out
; /* This case may not exist. */
585 oipt
->lsa_type
= new->data
->type
;
586 oipt
->opaque_type
= GET_OPAQUE_TYPE(ntohl(new->data
->id
.s_addr
));
587 oipt
->status
= PROC_NORMAL
;
588 oipt
->t_opaque_lsa_self
= NULL
;
589 oipt
->functab
= functab
;
590 functab
->oipt
= oipt
;
591 oipt
->id_list
= list_new();
592 oipt
->id_list
->del
= free_opaque_info_per_id
;
598 /* Remove "oipt" from its owner's self-originated LSA list. */
599 static void free_opaque_info_owner(void *val
)
601 struct opaque_info_per_type
*oipt
= (struct opaque_info_per_type
*)val
;
603 switch (oipt
->lsa_type
) {
604 case OSPF_OPAQUE_LINK_LSA
: {
605 struct ospf_interface
*oi
=
606 (struct ospf_interface
*)(oipt
->owner
);
607 listnode_delete(oi
->opaque_lsa_self
, oipt
);
610 case OSPF_OPAQUE_AREA_LSA
: {
611 struct ospf_area
*area
= (struct ospf_area
*)(oipt
->owner
);
612 listnode_delete(area
->opaque_lsa_self
, oipt
);
615 case OSPF_OPAQUE_AS_LSA
: {
616 struct ospf
*top
= (struct ospf
*)(oipt
->owner
);
617 listnode_delete(top
->opaque_lsa_self
, oipt
);
621 zlog_warn("free_opaque_info_owner: Unexpected LSA-type(%u)",
623 break; /* This case may not exist. */
627 static void free_opaque_info_per_type(void *val
)
629 struct opaque_info_per_type
*oipt
= (struct opaque_info_per_type
*)val
;
630 struct opaque_info_per_id
*oipi
;
631 struct ospf_lsa
*lsa
;
632 struct listnode
*node
, *nnode
;
634 /* Control information per opaque-id may still exist. */
635 for (ALL_LIST_ELEMENTS(oipt
->id_list
, node
, nnode
, oipi
)) {
636 if ((lsa
= oipi
->lsa
) == NULL
)
638 if (IS_LSA_MAXAGE(lsa
))
640 ospf_opaque_lsa_flush_schedule(lsa
);
643 OSPF_TIMER_OFF(oipt
->t_opaque_lsa_self
);
644 list_delete_and_null(&oipt
->id_list
);
645 XFREE(MTYPE_OPAQUE_INFO_PER_TYPE
, oipt
);
649 static struct opaque_info_per_type
*
650 lookup_opaque_info_by_type(struct ospf_lsa
*lsa
)
653 struct ospf_area
*area
;
654 struct ospf_interface
*oi
;
655 struct list
*listtop
= NULL
;
656 struct listnode
*node
, *nnode
;
657 struct opaque_info_per_type
*oipt
= NULL
;
658 uint8_t key
= GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
));
660 switch (lsa
->data
->type
) {
661 case OSPF_OPAQUE_LINK_LSA
:
662 if ((oi
= lsa
->oi
) != NULL
)
663 listtop
= oi
->opaque_lsa_self
;
666 "Type-9 Opaque-LSA: Reference to OI is missing?");
668 case OSPF_OPAQUE_AREA_LSA
:
669 if ((area
= lsa
->area
) != NULL
)
670 listtop
= area
->opaque_lsa_self
;
673 "Type-10 Opaque-LSA: Reference to AREA is missing?");
675 case OSPF_OPAQUE_AS_LSA
:
676 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
677 if ((area
= lsa
->area
) != NULL
&& (top
= area
->ospf
) == NULL
) {
679 "Type-11 Opaque-LSA: Reference to OSPF is missing?");
680 break; /* Unlikely to happen. */
682 listtop
= top
->opaque_lsa_self
;
685 zlog_warn("lookup_opaque_info_by_type: Unexpected LSA-type(%u)",
691 for (ALL_LIST_ELEMENTS(listtop
, node
, nnode
, oipt
))
692 if (oipt
->opaque_type
== key
)
698 static struct opaque_info_per_id
*
699 register_opaque_info_per_id(struct opaque_info_per_type
*oipt
,
700 struct ospf_lsa
*new)
702 struct opaque_info_per_id
*oipi
;
704 oipi
= XCALLOC(MTYPE_OPAQUE_INFO_PER_ID
,
705 sizeof(struct opaque_info_per_id
));
707 oipi
->opaque_id
= GET_OPAQUE_ID(ntohl(new->data
->id
.s_addr
));
708 oipi
->t_opaque_lsa_self
= NULL
;
709 oipi
->opqctl_type
= oipt
;
710 oipi
->lsa
= ospf_lsa_lock(new);
712 listnode_add(oipt
->id_list
, oipi
);
717 static void free_opaque_info_per_id(void *val
)
719 struct opaque_info_per_id
*oipi
= (struct opaque_info_per_id
*)val
;
721 OSPF_TIMER_OFF(oipi
->t_opaque_lsa_self
);
722 if (oipi
->lsa
!= NULL
)
723 ospf_lsa_unlock(&oipi
->lsa
);
724 XFREE(MTYPE_OPAQUE_INFO_PER_ID
, oipi
);
728 static struct opaque_info_per_id
*
729 lookup_opaque_info_by_id(struct opaque_info_per_type
*oipt
,
730 struct ospf_lsa
*lsa
)
732 struct listnode
*node
, *nnode
;
733 struct opaque_info_per_id
*oipi
;
734 uint32_t key
= GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
));
736 for (ALL_LIST_ELEMENTS(oipt
->id_list
, node
, nnode
, oipi
))
737 if (oipi
->opaque_id
== key
)
743 static struct opaque_info_per_id
*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 VTY_DECLVAR_INSTANCE_CONTEXT(ospf
, ospf
);
775 /* Turn on the "master switch" of opaque-lsa capability. */
776 if (!CHECK_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
)) {
777 if (IS_DEBUG_OSPF_EVENT
)
778 zlog_debug("Opaque capability: OFF -> ON");
780 SET_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
);
781 ospf_renegotiate_optional_capabilities(ospf
);
789 "OSPF specific commands\n"
790 "Enable the Opaque-LSA capability (rfc2370)\n")
792 return capability_opaque(self
, vty
, argc
, argv
);
795 DEFUN (no_capability_opaque
,
796 no_capability_opaque_cmd
,
797 "no capability opaque",
799 "Enable specific OSPF feature\n"
802 VTY_DECLVAR_INSTANCE_CONTEXT(ospf
, ospf
);
804 /* Turn off the "master switch" of opaque-lsa capability. */
805 if (CHECK_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
)) {
806 if (IS_DEBUG_OSPF_EVENT
)
807 zlog_debug("Opaque capability: ON -> OFF");
809 UNSET_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
);
810 ospf_renegotiate_optional_capabilities(ospf
);
815 DEFUN (no_ospf_opaque
,
817 "no ospf opaque-lsa",
819 "OSPF specific commands\n"
820 "Enable the Opaque-LSA capability (rfc2370)\n")
822 return no_capability_opaque(self
, vty
, argc
, argv
);
825 static void ospf_opaque_register_vty(void)
827 install_element(OSPF_NODE
, &capability_opaque_cmd
);
828 install_element(OSPF_NODE
, &no_capability_opaque_cmd
);
829 install_element(OSPF_NODE
, &ospf_opaque_cmd
);
830 install_element(OSPF_NODE
, &no_ospf_opaque_cmd
);
834 /*------------------------------------------------------------------------*
835 * Followings are collection of user-registered function callers.
836 *------------------------------------------------------------------------*/
838 static int opaque_lsa_new_if_callback(struct list
*funclist
,
839 struct interface
*ifp
)
841 struct listnode
*node
, *nnode
;
842 struct ospf_opaque_functab
*functab
;
845 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
846 if (functab
->new_if_hook
!= NULL
)
847 if ((*functab
->new_if_hook
)(ifp
) != 0)
854 static int opaque_lsa_del_if_callback(struct list
*funclist
,
855 struct interface
*ifp
)
857 struct listnode
*node
, *nnode
;
858 struct ospf_opaque_functab
*functab
;
861 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
862 if (functab
->del_if_hook
!= NULL
)
863 if ((*functab
->del_if_hook
)(ifp
) != 0)
870 static void opaque_lsa_ism_change_callback(struct list
*funclist
,
871 struct ospf_interface
*oi
,
874 struct listnode
*node
, *nnode
;
875 struct ospf_opaque_functab
*functab
;
877 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
878 if (functab
->ism_change_hook
!= NULL
)
879 (*functab
->ism_change_hook
)(oi
, old_status
);
884 static void opaque_lsa_nsm_change_callback(struct list
*funclist
,
885 struct ospf_neighbor
*nbr
,
888 struct listnode
*node
, *nnode
;
889 struct ospf_opaque_functab
*functab
;
891 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
892 if (functab
->nsm_change_hook
!= NULL
)
893 (*functab
->nsm_change_hook
)(nbr
, old_status
);
897 static void opaque_lsa_config_write_router_callback(struct list
*funclist
,
900 struct listnode
*node
, *nnode
;
901 struct ospf_opaque_functab
*functab
;
903 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
904 if (functab
->config_write_router
!= NULL
)
905 (*functab
->config_write_router
)(vty
);
909 static void opaque_lsa_config_write_if_callback(struct list
*funclist
,
911 struct interface
*ifp
)
913 struct listnode
*node
, *nnode
;
914 struct ospf_opaque_functab
*functab
;
916 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
917 if (functab
->config_write_if
!= NULL
)
918 (*functab
->config_write_if
)(vty
, ifp
);
922 static void opaque_lsa_config_write_debug_callback(struct list
*funclist
,
925 struct listnode
*node
, *nnode
;
926 struct ospf_opaque_functab
*functab
;
928 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
929 if (functab
->config_write_debug
!= NULL
)
930 (*functab
->config_write_debug
)(vty
);
934 static int opaque_lsa_originate_callback(struct list
*funclist
,
935 void *lsa_type_dependent
)
937 struct listnode
*node
, *nnode
;
938 struct ospf_opaque_functab
*functab
;
941 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
942 if (functab
->lsa_originator
!= NULL
)
943 if ((*functab
->lsa_originator
)(lsa_type_dependent
) != 0)
950 static int new_lsa_callback(struct list
*funclist
, struct ospf_lsa
*lsa
)
952 struct listnode
*node
, *nnode
;
953 struct ospf_opaque_functab
*functab
;
956 /* This function handles ALL types of LSAs, not only opaque ones. */
957 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
958 if (functab
->new_lsa_hook
!= NULL
)
959 if ((*functab
->new_lsa_hook
)(lsa
) != 0)
966 static int 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 *------------------------------------------------------------------------*/
986 int ospf_opaque_new_if(struct interface
*ifp
)
988 struct list
*funclist
;
991 funclist
= ospf_opaque_wildcard_funclist
;
992 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
995 funclist
= ospf_opaque_type9_funclist
;
996 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
999 funclist
= ospf_opaque_type10_funclist
;
1000 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
1003 funclist
= ospf_opaque_type11_funclist
;
1004 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
1012 int ospf_opaque_del_if(struct interface
*ifp
)
1014 struct list
*funclist
;
1017 funclist
= ospf_opaque_wildcard_funclist
;
1018 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1021 funclist
= ospf_opaque_type9_funclist
;
1022 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1025 funclist
= ospf_opaque_type10_funclist
;
1026 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1029 funclist
= ospf_opaque_type11_funclist
;
1030 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1038 void ospf_opaque_ism_change(struct ospf_interface
*oi
, int old_status
)
1040 struct list
*funclist
;
1042 funclist
= ospf_opaque_wildcard_funclist
;
1043 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1045 funclist
= ospf_opaque_type9_funclist
;
1046 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1048 funclist
= ospf_opaque_type10_funclist
;
1049 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1051 funclist
= ospf_opaque_type11_funclist
;
1052 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1057 void ospf_opaque_nsm_change(struct ospf_neighbor
*nbr
, int old_state
)
1060 struct list
*funclist
;
1062 if ((top
= oi_to_top(nbr
->oi
)) == NULL
)
1065 if (old_state
!= NSM_Full
&& nbr
->state
== NSM_Full
) {
1066 if (CHECK_FLAG(nbr
->options
, OSPF_OPTION_O
)) {
1067 if (!CHECK_FLAG(top
->opaque
,
1068 OPAQUE_OPERATION_READY_BIT
)) {
1069 if (IS_DEBUG_OSPF_EVENT
)
1071 "Opaque-LSA: Now get operational!");
1073 SET_FLAG(top
->opaque
,
1074 OPAQUE_OPERATION_READY_BIT
);
1077 ospf_opaque_lsa_originate_schedule(nbr
->oi
, NULL
);
1079 } else if (old_state
== NSM_Full
&& nbr
->state
!= NSM_Full
) {
1082 * If no more opaque-capable full-state neighbor remains in the
1083 * flooding scope which corresponds to Opaque-LSA type, periodic
1084 * LS flooding should be stopped.
1090 funclist
= ospf_opaque_wildcard_funclist
;
1091 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1093 funclist
= ospf_opaque_type9_funclist
;
1094 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1096 funclist
= ospf_opaque_type10_funclist
;
1097 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1099 funclist
= ospf_opaque_type11_funclist
;
1100 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1106 void ospf_opaque_config_write_router(struct vty
*vty
, struct ospf
*ospf
)
1108 struct list
*funclist
;
1110 if (CHECK_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
))
1111 vty_out(vty
, " capability opaque\n");
1113 funclist
= ospf_opaque_wildcard_funclist
;
1114 opaque_lsa_config_write_router_callback(funclist
, vty
);
1116 funclist
= ospf_opaque_type9_funclist
;
1117 opaque_lsa_config_write_router_callback(funclist
, vty
);
1119 funclist
= ospf_opaque_type10_funclist
;
1120 opaque_lsa_config_write_router_callback(funclist
, vty
);
1122 funclist
= ospf_opaque_type11_funclist
;
1123 opaque_lsa_config_write_router_callback(funclist
, vty
);
1128 void ospf_opaque_config_write_if(struct vty
*vty
, struct interface
*ifp
)
1130 struct list
*funclist
;
1132 funclist
= ospf_opaque_wildcard_funclist
;
1133 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1135 funclist
= ospf_opaque_type9_funclist
;
1136 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1138 funclist
= ospf_opaque_type10_funclist
;
1139 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1141 funclist
= ospf_opaque_type11_funclist
;
1142 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1147 void ospf_opaque_config_write_debug(struct vty
*vty
)
1149 struct list
*funclist
;
1151 funclist
= ospf_opaque_wildcard_funclist
;
1152 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1154 funclist
= ospf_opaque_type9_funclist
;
1155 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1157 funclist
= ospf_opaque_type10_funclist
;
1158 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1160 funclist
= ospf_opaque_type11_funclist
;
1161 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1166 void show_opaque_info_detail(struct vty
*vty
, struct ospf_lsa
*lsa
)
1168 struct lsa_header
*lsah
= (struct lsa_header
*)lsa
->data
;
1169 uint32_t lsid
= ntohl(lsah
->id
.s_addr
);
1170 uint8_t opaque_type
= GET_OPAQUE_TYPE(lsid
);
1171 uint32_t opaque_id
= GET_OPAQUE_ID(lsid
);
1172 struct ospf_opaque_functab
*functab
;
1174 /* Switch output functionality by vty address. */
1176 vty_out(vty
, " Opaque-Type %u (%s)\n", opaque_type
,
1177 ospf_opaque_type_name(opaque_type
));
1178 vty_out(vty
, " Opaque-ID 0x%x\n", opaque_id
);
1180 vty_out(vty
, " Opaque-Info: %u octets of data%s\n",
1181 ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
,
1182 VALID_OPAQUE_INFO_LEN(lsah
) ? "" : "(Invalid length?)");
1184 zlog_debug(" Opaque-Type %u (%s)", opaque_type
,
1185 ospf_opaque_type_name(opaque_type
));
1186 zlog_debug(" Opaque-ID 0x%x", opaque_id
);
1188 zlog_debug(" Opaque-Info: %u octets of data%s",
1189 ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
,
1190 VALID_OPAQUE_INFO_LEN(lsah
) ? ""
1191 : "(Invalid length?)");
1194 /* Call individual output functions. */
1195 if ((functab
= ospf_opaque_functab_lookup(lsa
)) != NULL
)
1196 if (functab
->show_opaque_info
!= NULL
)
1197 (*functab
->show_opaque_info
)(vty
, lsa
);
1202 void ospf_opaque_lsa_dump(struct stream
*s
, uint16_t length
)
1204 struct ospf_lsa lsa
;
1206 lsa
.data
= (struct lsa_header
*)stream_pnt(s
);
1207 show_opaque_info_detail(NULL
, &lsa
);
1211 static int ospf_opaque_lsa_install_hook(struct ospf_lsa
*lsa
)
1213 struct list
*funclist
;
1217 * Some Opaque-LSA user may want to monitor every LSA installation
1218 * into the LSDB, regardless with target LSA type.
1220 funclist
= ospf_opaque_wildcard_funclist
;
1221 if (new_lsa_callback(funclist
, lsa
) != 0)
1224 funclist
= ospf_opaque_type9_funclist
;
1225 if (new_lsa_callback(funclist
, lsa
) != 0)
1228 funclist
= ospf_opaque_type10_funclist
;
1229 if (new_lsa_callback(funclist
, lsa
) != 0)
1232 funclist
= ospf_opaque_type11_funclist
;
1233 if (new_lsa_callback(funclist
, lsa
) != 0)
1241 static int ospf_opaque_lsa_delete_hook(struct ospf_lsa
*lsa
)
1243 struct list
*funclist
;
1247 * Some Opaque-LSA user may want to monitor every LSA deletion
1248 * from the LSDB, regardless with target LSA type.
1250 funclist
= ospf_opaque_wildcard_funclist
;
1251 if (del_lsa_callback(funclist
, lsa
) != 0)
1254 funclist
= ospf_opaque_type9_funclist
;
1255 if (del_lsa_callback(funclist
, lsa
) != 0)
1258 funclist
= ospf_opaque_type10_funclist
;
1259 if (del_lsa_callback(funclist
, lsa
) != 0)
1262 funclist
= ospf_opaque_type11_funclist
;
1263 if (del_lsa_callback(funclist
, lsa
) != 0)
1271 /*------------------------------------------------------------------------*
1272 * Followings are Opaque-LSA origination/refresh management functions.
1273 *------------------------------------------------------------------------*/
1275 static int ospf_opaque_type9_lsa_originate(struct thread
*t
);
1276 static int ospf_opaque_type10_lsa_originate(struct thread
*t
);
1277 static int ospf_opaque_type11_lsa_originate(struct thread
*t
);
1278 static void ospf_opaque_lsa_reoriginate_resume(struct list
*listtop
, void *arg
);
1280 void ospf_opaque_lsa_originate_schedule(struct ospf_interface
*oi
, int *delay0
)
1283 struct ospf_area
*area
;
1284 struct listnode
*node
, *nnode
;
1285 struct opaque_info_per_type
*oipt
;
1288 if ((top
= oi_to_top(oi
)) == NULL
|| (area
= oi
->area
) == NULL
) {
1290 "ospf_opaque_lsa_originate_schedule: Invalid argument?");
1294 /* It may not a right time to schedule origination now. */
1295 if (!CHECK_FLAG(top
->opaque
, OPAQUE_OPERATION_READY_BIT
)) {
1296 if (IS_DEBUG_OSPF_EVENT
)
1298 "ospf_opaque_lsa_originate_schedule: Not operational.");
1299 goto out
; /* This is not an error. */
1306 * There might be some entries that have been waiting for triggering
1307 * of per opaque-type re-origination get resumed.
1309 ospf_opaque_lsa_reoriginate_resume(oi
->opaque_lsa_self
, (void *)oi
);
1310 ospf_opaque_lsa_reoriginate_resume(area
->opaque_lsa_self
, (void *)area
);
1311 ospf_opaque_lsa_reoriginate_resume(top
->opaque_lsa_self
, (void *)top
);
1314 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1316 if (!list_isempty(ospf_opaque_type9_funclist
)
1317 && list_isempty(oi
->opaque_lsa_self
)
1318 && oi
->t_opaque_lsa_self
== NULL
) {
1319 if (IS_DEBUG_OSPF_EVENT
)
1321 "Schedule Type-9 Opaque-LSA origination in %d ms later.",
1323 oi
->t_opaque_lsa_self
= NULL
;
1324 thread_add_timer_msec(master
, ospf_opaque_type9_lsa_originate
,
1325 oi
, delay
, &oi
->t_opaque_lsa_self
);
1326 delay
+= top
->min_ls_interval
;
1329 if (!list_isempty(ospf_opaque_type10_funclist
)
1330 && list_isempty(area
->opaque_lsa_self
)
1331 && area
->t_opaque_lsa_self
== NULL
) {
1333 * One AREA may contain multiple OIs, but above 2nd and 3rd
1334 * conditions prevent from scheduling the originate function
1337 if (IS_DEBUG_OSPF_EVENT
)
1339 "Schedule Type-10 Opaque-LSA origination in %d ms later.",
1341 area
->t_opaque_lsa_self
= NULL
;
1342 thread_add_timer_msec(master
, ospf_opaque_type10_lsa_originate
,
1343 area
, delay
, &area
->t_opaque_lsa_self
);
1344 delay
+= top
->min_ls_interval
;
1347 if (!list_isempty(ospf_opaque_type11_funclist
)
1348 && list_isempty(top
->opaque_lsa_self
)
1349 && top
->t_opaque_lsa_self
== NULL
) {
1351 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1352 * conditions prevent from scheduling the originate function
1355 if (IS_DEBUG_OSPF_EVENT
)
1357 "Schedule Type-11 Opaque-LSA origination in %d ms later.",
1359 top
->t_opaque_lsa_self
= NULL
;
1360 thread_add_timer_msec(master
, ospf_opaque_type11_lsa_originate
,
1361 top
, delay
, &top
->t_opaque_lsa_self
);
1362 delay
+= top
->min_ls_interval
;
1366 * Following section treats a special situation that this node's
1367 * opaque capability has changed as "ON -> OFF -> ON".
1369 if (!list_isempty(ospf_opaque_type9_funclist
)
1370 && !list_isempty(oi
->opaque_lsa_self
)) {
1371 for (ALL_LIST_ELEMENTS(oi
->opaque_lsa_self
, node
, nnode
,
1374 * removed the test for
1375 * (! list_isempty (oipt->id_list)) * Handler is
1377 * because opaque cababilities ON -> OFF -> ON result in
1378 * list_isempty (oipt->id_list)
1381 if (oipt
->t_opaque_lsa_self
1382 != NULL
/* Waiting for a thread call. */
1383 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1388 ospf_opaque_lsa_reoriginate_schedule(
1389 (void *)oi
, OSPF_OPAQUE_LINK_LSA
,
1394 if (!list_isempty(ospf_opaque_type10_funclist
)
1395 && !list_isempty(area
->opaque_lsa_self
)) {
1396 for (ALL_LIST_ELEMENTS(area
->opaque_lsa_self
, node
, nnode
,
1399 * removed the test for
1400 * (! list_isempty (oipt->id_list)) * Handler is
1402 * because opaque cababilities ON -> OFF -> ON result in
1403 * list_isempty (oipt->id_list)
1406 if (oipt
->t_opaque_lsa_self
1407 != NULL
/* Waiting for a thread call. */
1408 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1413 ospf_opaque_lsa_reoriginate_schedule(
1414 (void *)area
, OSPF_OPAQUE_AREA_LSA
,
1419 if (!list_isempty(ospf_opaque_type11_funclist
)
1420 && !list_isempty(top
->opaque_lsa_self
)) {
1421 for (ALL_LIST_ELEMENTS(top
->opaque_lsa_self
, node
, nnode
,
1424 * removed the test for
1425 * (! list_isempty (oipt->id_list)) * Handler is
1427 * because opaque cababilities ON -> OFF -> ON result in
1428 * list_isempty (oipt->id_list)
1431 if (oipt
->t_opaque_lsa_self
1432 != NULL
/* Waiting for a thread call. */
1433 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1438 ospf_opaque_lsa_reoriginate_schedule((void *)top
,
1451 static int ospf_opaque_type9_lsa_originate(struct thread
*t
)
1453 struct ospf_interface
*oi
;
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
);
1468 static int ospf_opaque_type10_lsa_originate(struct thread
*t
)
1470 struct ospf_area
*area
;
1473 area
= THREAD_ARG(t
);
1474 area
->t_opaque_lsa_self
= NULL
;
1476 if (IS_DEBUG_OSPF_EVENT
)
1478 "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
);
1486 static int ospf_opaque_type11_lsa_originate(struct thread
*t
)
1491 top
= THREAD_ARG(t
);
1492 top
->t_opaque_lsa_self
= NULL
;
1494 if (IS_DEBUG_OSPF_EVENT
)
1496 "Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
1498 rc
= opaque_lsa_originate_callback(ospf_opaque_type11_funclist
, top
);
1503 static void ospf_opaque_lsa_reoriginate_resume(struct list
*listtop
, void *arg
)
1505 struct listnode
*node
, *nnode
;
1506 struct opaque_info_per_type
*oipt
;
1507 struct ospf_opaque_functab
*functab
;
1509 if (listtop
== NULL
)
1513 * Pickup oipt entries those which in SUSPEND status, and give
1514 * them a chance to start re-origination now.
1516 for (ALL_LIST_ELEMENTS(listtop
, node
, nnode
, oipt
)) {
1517 if (oipt
->status
!= PROC_SUSPEND
)
1520 oipt
->status
= PROC_NORMAL
;
1522 if ((functab
= oipt
->functab
) == NULL
1523 || functab
->lsa_originator
== NULL
)
1526 if ((*functab
->lsa_originator
)(arg
) != 0) {
1528 "ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)",
1538 struct ospf_lsa
*ospf_opaque_lsa_install(struct ospf_lsa
*lsa
, int rt_recalc
)
1540 struct ospf_lsa
*new = NULL
;
1541 struct opaque_info_per_type
*oipt
;
1542 struct opaque_info_per_id
*oipi
;
1545 /* Don't take "rt_recalc" into consideration for now. */ /* XXX */
1547 if (!IS_LSA_SELF(lsa
)) {
1548 new = lsa
; /* Don't touch this LSA. */
1552 if (IS_DEBUG_OSPF(lsa
, LSA_INSTALL
))
1554 "Install Type-%u Opaque-LSA: [opaque-type=%u, opaque-id=%x]",
1556 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
1557 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
1559 /* Replace the existing lsa with the new one. */
1560 if ((oipt
= lookup_opaque_info_by_type(lsa
)) != NULL
1561 && (oipi
= lookup_opaque_info_by_id(oipt
, lsa
)) != NULL
) {
1562 ospf_lsa_unlock(&oipi
->lsa
);
1563 oipi
->lsa
= ospf_lsa_lock(lsa
);
1565 /* Register the new lsa entry and get its control info. */
1566 else if ((oipi
= register_opaque_lsa(lsa
)) == NULL
) {
1567 zlog_warn("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1572 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1573 * for periodic refresh of self-originated Opaque-LSAs.
1575 switch (lsa
->data
->type
) {
1576 case OSPF_OPAQUE_LINK_LSA
:
1577 if ((top
= oi_to_top(lsa
->oi
)) == NULL
) {
1578 /* Above conditions must have passed. */
1579 zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?");
1583 case OSPF_OPAQUE_AREA_LSA
:
1584 if (lsa
->area
== NULL
|| (top
= lsa
->area
->ospf
) == NULL
) {
1585 /* Above conditions must have passed. */
1586 zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?");
1590 case OSPF_OPAQUE_AS_LSA
:
1591 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
1592 if (lsa
->area
!= NULL
&& (top
= lsa
->area
->ospf
) == NULL
) {
1593 /* Above conditions must have passed. */
1594 zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?");
1599 zlog_warn("ospf_opaque_lsa_install: Unexpected LSA-type(%u)",
1604 ospf_refresher_register_lsa(top
, lsa
);
1611 struct ospf_lsa
*ospf_opaque_lsa_refresh(struct ospf_lsa
*lsa
)
1614 struct ospf_opaque_functab
*functab
;
1615 struct ospf_lsa
*new = NULL
;
1617 ospf
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
1619 if ((functab
= ospf_opaque_functab_lookup(lsa
)) == NULL
1620 || functab
->lsa_refresher
== NULL
) {
1622 * Though this LSA seems to have originated on this node, the
1623 * handling module for this "lsa-type and opaque-type" was
1624 * already deleted sometime ago.
1625 * Anyway, this node still has a responsibility to flush this
1626 * LSA from the routing domain.
1628 if (IS_DEBUG_OSPF_EVENT
)
1629 zlog_debug("LSA[Type%d:%s]: Flush stray Opaque-LSA",
1630 lsa
->data
->type
, inet_ntoa(lsa
->data
->id
));
1632 lsa
->data
->ls_age
= htons(OSPF_LSA_MAXAGE
);
1633 ospf_lsa_flush(ospf
, lsa
);
1635 new = (*functab
->lsa_refresher
)(lsa
);
1640 /*------------------------------------------------------------------------*
1641 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1642 * triggered by external interventions (vty session, signaling, etc).
1643 *------------------------------------------------------------------------*/
1645 #define OSPF_OPAQUE_TIMER_ON(T,F,L,V) thread_add_timer_msec (master, (F), (L), (V), &(T))
1647 static struct ospf_lsa
*pseudo_lsa(struct ospf_interface
*oi
,
1648 struct ospf_area
*area
, uint8_t lsa_type
,
1649 uint8_t opaque_type
);
1650 static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread
*t
);
1651 static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread
*t
);
1652 static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread
*t
);
1653 static int ospf_opaque_lsa_refresh_timer(struct thread
*t
);
1655 void ospf_opaque_lsa_reoriginate_schedule(void *lsa_type_dependent
,
1656 uint8_t lsa_type
, uint8_t opaque_type
)
1658 struct ospf
*top
= NULL
;
1659 struct ospf_area dummy
, *area
= NULL
;
1660 struct ospf_interface
*oi
= NULL
;
1662 struct ospf_lsa
*lsa
;
1663 struct opaque_info_per_type
*oipt
;
1664 int (*func
)(struct thread
* t
) = NULL
;
1668 case OSPF_OPAQUE_LINK_LSA
:
1669 if ((oi
= (struct ospf_interface
*)lsa_type_dependent
)
1672 "ospf_opaque_lsa_reoriginate_schedule:"
1673 " Type-9 Opaque-LSA: Invalid parameter?");
1676 if ((top
= oi_to_top(oi
)) == NULL
) {
1678 "ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1682 if (!list_isempty(ospf_opaque_type9_funclist
)
1683 && list_isempty(oi
->opaque_lsa_self
)
1684 && oi
->t_opaque_lsa_self
!= NULL
) {
1686 "Type-9 Opaque-LSA (opaque_type=%u):"
1687 " Common origination for OI(%s) has already started",
1688 opaque_type
, IF_NAME(oi
));
1691 func
= ospf_opaque_type9_lsa_reoriginate_timer
;
1693 case OSPF_OPAQUE_AREA_LSA
:
1694 if ((area
= (struct ospf_area
*)lsa_type_dependent
) == NULL
) {
1696 "ospf_opaque_lsa_reoriginate_schedule:"
1697 " Type-10 Opaque-LSA: Invalid parameter?");
1700 if ((top
= area
->ospf
) == NULL
) {
1702 "ospf_opaque_lsa_reoriginate_schedule:"
1703 " AREA(%s) -> TOP?",
1704 inet_ntoa(area
->area_id
));
1707 if (!list_isempty(ospf_opaque_type10_funclist
)
1708 && list_isempty(area
->opaque_lsa_self
)
1709 && area
->t_opaque_lsa_self
!= NULL
) {
1711 "Type-10 Opaque-LSA (opaque_type=%u):"
1712 " Common origination for AREA(%s) has already started",
1713 opaque_type
, inet_ntoa(area
->area_id
));
1716 func
= ospf_opaque_type10_lsa_reoriginate_timer
;
1718 case OSPF_OPAQUE_AS_LSA
:
1719 if ((top
= (struct ospf
*)lsa_type_dependent
) == NULL
) {
1721 "ospf_opaque_lsa_reoriginate_schedule:"
1722 " Type-11 Opaque-LSA: Invalid parameter?");
1725 if (!list_isempty(ospf_opaque_type11_funclist
)
1726 && list_isempty(top
->opaque_lsa_self
)
1727 && top
->t_opaque_lsa_self
!= NULL
) {
1729 "Type-11 Opaque-LSA (opaque_type=%u):"
1730 " Common origination has already started",
1735 /* Fake "area" to pass "ospf" to a lookup function later. */
1739 func
= ospf_opaque_type11_lsa_reoriginate_timer
;
1743 "ospf_opaque_lsa_reoriginate_schedule:"
1744 " Unexpected LSA-type(%u)",
1749 /* It may not a right time to schedule reorigination now. */
1750 if (!CHECK_FLAG(top
->opaque
, OPAQUE_OPERATION_READY_BIT
)) {
1751 if (IS_DEBUG_OSPF_EVENT
)
1753 "ospf_opaque_lsa_reoriginate_schedule: Not operational.");
1754 goto out
; /* This is not an error. */
1757 /* Generate a dummy lsa to be passed for a lookup function. */
1758 lsa
= pseudo_lsa(oi
, area
, lsa_type
, opaque_type
);
1759 lsa
->vrf_id
= top
->vrf_id
;
1761 if ((oipt
= lookup_opaque_info_by_type(lsa
)) == NULL
) {
1762 struct ospf_opaque_functab
*functab
;
1763 if ((functab
= ospf_opaque_functab_lookup(lsa
)) == NULL
) {
1765 "ospf_opaque_lsa_reoriginate_schedule:"
1766 " No associated function?: lsa_type(%u),"
1768 lsa_type
, opaque_type
);
1771 if ((oipt
= register_opaque_info_per_type(functab
, lsa
))
1774 "ospf_opaque_lsa_reoriginate_schedule:"
1775 " Cannot get a control info?: lsa_type(%u),"
1777 lsa_type
, opaque_type
);
1782 if (oipt
->t_opaque_lsa_self
!= NULL
) {
1783 if (IS_DEBUG_OSPF_EVENT
)
1785 "Type-%u Opaque-LSA has already scheduled to"
1786 " RE-ORIGINATE: [opaque-type=%u]",
1788 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)));
1793 * Different from initial origination time, in which various conditions
1794 * (opaque capability, neighbor status etc) are assured by caller of
1795 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1796 * it is highly possible that these conditions might not be satisfied
1797 * at the time of re-origination function is to be called.
1799 delay
= top
->min_ls_interval
; /* XXX */
1801 if (IS_DEBUG_OSPF_EVENT
)
1803 "Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
1804 " ms later: [opaque-type=%u]",
1806 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)));
1808 OSPF_OPAQUE_TIMER_ON(oipt
->t_opaque_lsa_self
, func
, oipt
, delay
);
1814 static struct ospf_lsa
*pseudo_lsa(struct ospf_interface
*oi
,
1815 struct ospf_area
*area
, uint8_t lsa_type
,
1816 uint8_t opaque_type
)
1818 static struct ospf_lsa lsa
= {0};
1819 static struct lsa_header lsah
= {0};
1825 lsa
.vrf_id
= VRF_DEFAULT
;
1827 lsah
.type
= lsa_type
;
1828 tmp
= SET_OPAQUE_LSID(opaque_type
, 0); /* Opaque-ID is unused here. */
1829 lsah
.id
.s_addr
= htonl(tmp
);
1834 static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread
*t
)
1836 struct opaque_info_per_type
*oipt
;
1837 struct ospf_opaque_functab
*functab
;
1839 struct ospf_interface
*oi
;
1842 oipt
= THREAD_ARG(t
);
1843 oipt
->t_opaque_lsa_self
= NULL
;
1845 if ((functab
= oipt
->functab
) == NULL
1846 || functab
->lsa_originator
== NULL
) {
1848 "ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1852 oi
= (struct ospf_interface
*)oipt
->owner
;
1853 if ((top
= oi_to_top(oi
)) == NULL
) {
1855 "ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1859 if (!CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)
1860 || !ospf_if_is_enable(oi
)
1861 || ospf_nbr_count_opaque_capable(oi
) == 0) {
1862 if (IS_DEBUG_OSPF_EVENT
)
1864 "Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...",
1867 oipt
->status
= PROC_SUSPEND
;
1872 if (IS_DEBUG_OSPF_EVENT
)
1874 "Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)",
1875 oipt
->opaque_type
, IF_NAME(oi
));
1877 rc
= (*functab
->lsa_originator
)(oi
);
1882 static int 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 "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 "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
)) {
1912 if ((n
= ospf_nbr_count_opaque_capable(oi
)) > 0)
1916 if (n
== 0 || !CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)) {
1917 if (IS_DEBUG_OSPF_EVENT
)
1919 "Suspend re-origination of Type-10 Opaque-LSAs"
1920 " (opaque-type=%u) for a while...",
1923 oipt
->status
= PROC_SUSPEND
;
1928 if (IS_DEBUG_OSPF_EVENT
)
1930 "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
);
1939 static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread
*t
)
1941 struct opaque_info_per_type
*oipt
;
1942 struct ospf_opaque_functab
*functab
;
1946 oipt
= THREAD_ARG(t
);
1947 oipt
->t_opaque_lsa_self
= NULL
;
1949 if ((functab
= oipt
->functab
) == NULL
1950 || functab
->lsa_originator
== NULL
) {
1952 "ospf_opaque_type11_lsa_reoriginate_timer:"
1953 " No associated function?");
1957 if ((top
= (struct ospf
*)oipt
->owner
) == NULL
) {
1959 "ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1963 if (!CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)) {
1964 if (IS_DEBUG_OSPF_EVENT
)
1966 "Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...",
1969 oipt
->status
= PROC_SUSPEND
;
1974 if (IS_DEBUG_OSPF_EVENT
)
1976 "Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).",
1979 rc
= (*functab
->lsa_originator
)(top
);
1984 void ospf_opaque_lsa_refresh_schedule(struct ospf_lsa
*lsa0
)
1986 struct opaque_info_per_type
*oipt
;
1987 struct opaque_info_per_id
*oipi
;
1988 struct ospf_lsa
*lsa
;
1992 if ((oipt
= lookup_opaque_info_by_type(lsa0
)) == NULL
1993 || (oipi
= lookup_opaque_info_by_id(oipt
, lsa0
)) == NULL
) {
1995 "ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
1999 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2000 if ((lsa
= oipi
->lsa
) == NULL
) {
2001 zlog_warn("ospf_opaque_lsa_refresh_schedule: Something wrong?");
2005 if (oipi
->t_opaque_lsa_self
!= NULL
) {
2006 if (IS_DEBUG_OSPF_EVENT
)
2008 "Type-%u Opaque-LSA has already scheduled to REFRESH: [opaque-type=%u, opaque-id=%x]",
2010 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
2011 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
2015 /* Delete this lsa from neighbor retransmit-list. */
2016 switch (lsa
->data
->type
) {
2017 case OSPF_OPAQUE_LINK_LSA
:
2018 case OSPF_OPAQUE_AREA_LSA
:
2019 ospf_ls_retransmit_delete_nbr_area(lsa
->area
, lsa
);
2021 case OSPF_OPAQUE_AS_LSA
:
2022 top
= ospf_lookup_by_vrf_id(lsa0
->vrf_id
);
2023 if ((lsa0
->area
!= NULL
) && (lsa0
->area
->ospf
!= NULL
))
2024 top
= lsa0
->area
->ospf
;
2025 ospf_ls_retransmit_delete_nbr_as(top
, lsa
);
2029 "ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)",
2034 delay
= ospf_lsa_refresh_delay(lsa
);
2036 if (IS_DEBUG_OSPF_EVENT
)
2038 "Schedule Type-%u Opaque-LSA to REFRESH in %d sec later: [opaque-type=%u, opaque-id=%x]",
2039 lsa
->data
->type
, delay
,
2040 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
2041 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
2043 OSPF_OPAQUE_TIMER_ON(oipi
->t_opaque_lsa_self
,
2044 ospf_opaque_lsa_refresh_timer
, oipi
, delay
* 1000);
2049 static int ospf_opaque_lsa_refresh_timer(struct thread
*t
)
2051 struct opaque_info_per_id
*oipi
;
2052 struct ospf_opaque_functab
*functab
;
2053 struct ospf_lsa
*lsa
;
2055 if (IS_DEBUG_OSPF_EVENT
)
2056 zlog_debug("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
2058 oipi
= THREAD_ARG(t
);
2059 oipi
->t_opaque_lsa_self
= NULL
;
2061 if ((lsa
= oipi
->lsa
) != NULL
)
2062 if ((functab
= oipi
->opqctl_type
->functab
) != NULL
)
2063 if (functab
->lsa_refresher
!= NULL
)
2064 (*functab
->lsa_refresher
)(lsa
);
2069 void ospf_opaque_lsa_flush_schedule(struct ospf_lsa
*lsa0
)
2071 struct opaque_info_per_type
*oipt
;
2072 struct opaque_info_per_id
*oipi
;
2073 struct ospf_lsa
*lsa
;
2076 top
= ospf_lookup_by_vrf_id(lsa0
->vrf_id
);
2078 if ((oipt
= lookup_opaque_info_by_type(lsa0
)) == NULL
2079 || (oipi
= lookup_opaque_info_by_id(oipt
, lsa0
)) == NULL
) {
2080 zlog_warn("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2084 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2085 if ((lsa
= oipi
->lsa
) == NULL
) {
2086 zlog_warn("ospf_opaque_lsa_flush_schedule: Something wrong?");
2090 /* Delete this lsa from neighbor retransmit-list. */
2091 switch (lsa
->data
->type
) {
2092 case OSPF_OPAQUE_LINK_LSA
:
2093 case OSPF_OPAQUE_AREA_LSA
:
2094 ospf_ls_retransmit_delete_nbr_area(lsa
->area
, lsa
);
2096 case OSPF_OPAQUE_AS_LSA
:
2097 if ((lsa0
->area
!= NULL
) && (lsa0
->area
->ospf
!= NULL
))
2098 top
= lsa0
->area
->ospf
;
2099 ospf_ls_retransmit_delete_nbr_as(top
, lsa
);
2103 "ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)",
2108 /* Dequeue listnode entry from the list. */
2109 listnode_delete(oipt
->id_list
, oipi
);
2111 /* Avoid misjudgement in the next lookup. */
2112 if (listcount(oipt
->id_list
) == 0)
2113 oipt
->id_list
->head
= oipt
->id_list
->tail
= NULL
;
2115 /* Disassociate internal control information with the given lsa. */
2116 free_opaque_info_per_id((void *)oipi
);
2118 /* Force given lsa's age to MaxAge. */
2119 lsa
->data
->ls_age
= htons(OSPF_LSA_MAXAGE
);
2121 if (IS_DEBUG_OSPF_EVENT
)
2123 "Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]",
2125 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
2126 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
2128 /* This lsa will be flushed and removed eventually. */
2129 ospf_lsa_flush(top
, lsa
);
2135 void ospf_opaque_self_originated_lsa_received(struct ospf_neighbor
*nbr
,
2136 struct ospf_lsa
*lsa
)
2140 if ((top
= oi_to_top(nbr
->oi
)) == NULL
)
2144 * Since these LSA entries are not yet installed into corresponding
2145 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2147 lsa
->data
->ls_age
= htons(OSPF_LSA_MAXAGE
);
2148 switch (lsa
->data
->type
) {
2149 case OSPF_OPAQUE_LINK_LSA
:
2150 ospf_flood_through_area(nbr
->oi
->area
, NULL
/*inbr*/, lsa
);
2152 case OSPF_OPAQUE_AREA_LSA
:
2153 ospf_flood_through_area(nbr
->oi
->area
, NULL
/*inbr*/, lsa
);
2155 case OSPF_OPAQUE_AS_LSA
:
2156 ospf_flood_through_as(top
, NULL
/*inbr*/, lsa
);
2160 "ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)",
2164 ospf_lsa_discard(lsa
); /* List "lsas" will be deleted by caller. */
2167 /*------------------------------------------------------------------------*
2168 * Followings are util functions; probably be used by Opaque-LSAs only...
2169 *------------------------------------------------------------------------*/
2171 struct ospf
*oi_to_top(struct ospf_interface
*oi
)
2173 struct ospf
*top
= NULL
;
2174 struct ospf_area
*area
;
2176 if (oi
== NULL
|| (area
= oi
->area
) == NULL
2177 || (top
= area
->ospf
) == NULL
)
2178 zlog_warn("Broken relationship for \"OI -> AREA -> OSPF\"?");