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 if ((new = XCALLOC(MTYPE_OSPF_OPAQUE_FUNCTAB
,
403 sizeof(struct ospf_opaque_functab
)))
405 zlog_warn("ospf_register_opaque_functab: XMALLOC: %s",
406 safe_strerror(errno
));
410 new->opaque_type
= opaque_type
;
412 new->new_if_hook
= new_if_hook
;
413 new->del_if_hook
= del_if_hook
;
414 new->ism_change_hook
= ism_change_hook
;
415 new->nsm_change_hook
= nsm_change_hook
;
416 new->config_write_router
= config_write_router
;
417 new->config_write_if
= config_write_if
;
418 new->config_write_debug
= config_write_debug
;
419 new->show_opaque_info
= show_opaque_info
;
420 new->lsa_originator
= lsa_originator
;
421 new->lsa_refresher
= lsa_refresher
;
422 new->new_lsa_hook
= new_lsa_hook
;
423 new->del_lsa_hook
= del_lsa_hook
;
425 listnode_add(funclist
, new);
432 void ospf_delete_opaque_functab(uint8_t lsa_type
, uint8_t opaque_type
)
434 struct list
*funclist
;
435 struct listnode
*node
, *nnode
;
436 struct ospf_opaque_functab
*functab
;
438 if ((funclist
= ospf_get_opaque_funclist(lsa_type
)) != NULL
)
439 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
)) {
440 if (functab
->opaque_type
== opaque_type
) {
441 /* Cleanup internal control information, if it
443 if (functab
->oipt
!= NULL
) {
444 free_opaque_info_per_type(
446 free_opaque_info_owner(functab
->oipt
);
449 /* Dequeue listnode entry from the list. */
450 listnode_delete(funclist
, functab
);
452 /* Avoid misjudgement in the next lookup. */
453 if (listcount(funclist
) == 0)
454 funclist
->head
= funclist
->tail
= NULL
;
456 XFREE(MTYPE_OSPF_OPAQUE_FUNCTAB
, functab
);
464 static struct ospf_opaque_functab
*
465 ospf_opaque_functab_lookup(struct ospf_lsa
*lsa
)
467 struct list
*funclist
;
468 struct listnode
*node
;
469 struct ospf_opaque_functab
*functab
;
470 uint8_t key
= GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
));
472 if ((funclist
= ospf_get_opaque_funclist(lsa
->data
->type
)) != NULL
)
473 for (ALL_LIST_ELEMENTS_RO(funclist
, node
, functab
))
474 if (functab
->opaque_type
== key
)
480 /*------------------------------------------------------------------------*
481 * Followings are management functions for self-originated LSA entries.
482 *------------------------------------------------------------------------*/
485 * Opaque-LSA control information per opaque-type.
486 * Single Opaque-Type may have multiple instances; each of them will be
487 * identified by their opaque-id.
489 struct opaque_info_per_type
{
493 enum { PROC_NORMAL
, PROC_SUSPEND
} status
;
496 * Thread for (re-)origination scheduling for this opaque-type.
498 * Initial origination of Opaque-LSAs is controlled by generic
499 * Opaque-LSA handling module so that same opaque-type entries are
500 * called all at once when certain conditions are met.
501 * However, there might be cases that some Opaque-LSA clients need
502 * to (re-)originate their own Opaque-LSAs out-of-sync with others.
503 * This thread is prepared for that specific purpose.
505 struct thread
*t_opaque_lsa_self
;
508 * Backpointer to an "owner" which is LSA-type dependent.
509 * type-9: struct ospf_interface
510 * type-10: struct ospf_area
511 * type-11: struct ospf
515 /* Collection of callback functions for this opaque-type. */
516 struct ospf_opaque_functab
*functab
;
518 /* List of Opaque-LSA control informations per opaque-id. */
519 struct list
*id_list
;
522 /* Opaque-LSA control information per opaque-id. */
523 struct opaque_info_per_id
{
526 /* Thread for refresh/flush scheduling for this opaque-type/id. */
527 struct thread
*t_opaque_lsa_self
;
529 /* Backpointer to Opaque-LSA control information per opaque-type. */
530 struct opaque_info_per_type
*opqctl_type
;
532 /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
533 struct ospf_lsa
*lsa
;
536 static struct opaque_info_per_type
*
537 register_opaque_info_per_type(struct ospf_opaque_functab
*functab
,
538 struct ospf_lsa
*new);
539 static struct opaque_info_per_type
*
540 lookup_opaque_info_by_type(struct ospf_lsa
*lsa
);
541 static struct opaque_info_per_id
*
542 register_opaque_info_per_id(struct opaque_info_per_type
*oipt
,
543 struct ospf_lsa
*new);
544 static struct opaque_info_per_id
*
545 lookup_opaque_info_by_id(struct opaque_info_per_type
*oipt
,
546 struct ospf_lsa
*lsa
);
547 static struct opaque_info_per_id
*register_opaque_lsa(struct ospf_lsa
*new);
550 static struct opaque_info_per_type
*
551 register_opaque_info_per_type(struct ospf_opaque_functab
*functab
,
552 struct ospf_lsa
*new)
555 struct opaque_info_per_type
*oipt
;
557 if ((oipt
= XCALLOC(MTYPE_OPAQUE_INFO_PER_TYPE
,
558 sizeof(struct opaque_info_per_type
)))
560 zlog_warn("register_opaque_info_per_type: XMALLOC: %s",
561 safe_strerror(errno
));
565 switch (new->data
->type
) {
566 case OSPF_OPAQUE_LINK_LSA
:
567 oipt
->owner
= new->oi
;
568 listnode_add(new->oi
->opaque_lsa_self
, oipt
);
570 case OSPF_OPAQUE_AREA_LSA
:
571 oipt
->owner
= new->area
;
572 listnode_add(new->area
->opaque_lsa_self
, oipt
);
574 case OSPF_OPAQUE_AS_LSA
:
575 top
= ospf_lookup_by_vrf_id(new->vrf_id
);
576 if (new->area
!= NULL
&& (top
= new->area
->ospf
) == NULL
) {
577 free_opaque_info_per_type((void *)oipt
);
578 free_opaque_info_owner(oipt
);
580 goto out
; /* This case may not exist. */
583 listnode_add(top
->opaque_lsa_self
, oipt
);
587 "register_opaque_info_per_type: Unexpected LSA-type(%u)",
589 free_opaque_info_per_type((void *)oipt
);
590 free_opaque_info_owner(oipt
);
592 goto out
; /* This case may not exist. */
595 oipt
->lsa_type
= new->data
->type
;
596 oipt
->opaque_type
= GET_OPAQUE_TYPE(ntohl(new->data
->id
.s_addr
));
597 oipt
->status
= PROC_NORMAL
;
598 oipt
->t_opaque_lsa_self
= NULL
;
599 oipt
->functab
= functab
;
600 functab
->oipt
= oipt
;
601 oipt
->id_list
= list_new();
602 oipt
->id_list
->del
= free_opaque_info_per_id
;
608 /* Remove "oipt" from its owner's self-originated LSA list. */
609 static void free_opaque_info_owner(void *val
)
611 struct opaque_info_per_type
*oipt
= (struct opaque_info_per_type
*)val
;
613 switch (oipt
->lsa_type
) {
614 case OSPF_OPAQUE_LINK_LSA
: {
615 struct ospf_interface
*oi
=
616 (struct ospf_interface
*)(oipt
->owner
);
617 listnode_delete(oi
->opaque_lsa_self
, oipt
);
620 case OSPF_OPAQUE_AREA_LSA
: {
621 struct ospf_area
*area
= (struct ospf_area
*)(oipt
->owner
);
622 listnode_delete(area
->opaque_lsa_self
, oipt
);
625 case OSPF_OPAQUE_AS_LSA
: {
626 struct ospf
*top
= (struct ospf
*)(oipt
->owner
);
627 listnode_delete(top
->opaque_lsa_self
, oipt
);
631 zlog_warn("free_opaque_info_owner: Unexpected LSA-type(%u)",
633 break; /* This case may not exist. */
637 static void free_opaque_info_per_type(void *val
)
639 struct opaque_info_per_type
*oipt
= (struct opaque_info_per_type
*)val
;
640 struct opaque_info_per_id
*oipi
;
641 struct ospf_lsa
*lsa
;
642 struct listnode
*node
, *nnode
;
644 /* Control information per opaque-id may still exist. */
645 for (ALL_LIST_ELEMENTS(oipt
->id_list
, node
, nnode
, oipi
)) {
646 if ((lsa
= oipi
->lsa
) == NULL
)
648 if (IS_LSA_MAXAGE(lsa
))
650 ospf_opaque_lsa_flush_schedule(lsa
);
653 OSPF_TIMER_OFF(oipt
->t_opaque_lsa_self
);
654 list_delete_and_null(&oipt
->id_list
);
655 XFREE(MTYPE_OPAQUE_INFO_PER_TYPE
, oipt
);
659 static struct opaque_info_per_type
*
660 lookup_opaque_info_by_type(struct ospf_lsa
*lsa
)
663 struct ospf_area
*area
;
664 struct ospf_interface
*oi
;
665 struct list
*listtop
= NULL
;
666 struct listnode
*node
, *nnode
;
667 struct opaque_info_per_type
*oipt
= NULL
;
668 uint8_t key
= GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
));
670 switch (lsa
->data
->type
) {
671 case OSPF_OPAQUE_LINK_LSA
:
672 if ((oi
= lsa
->oi
) != NULL
)
673 listtop
= oi
->opaque_lsa_self
;
676 "Type-9 Opaque-LSA: Reference to OI is missing?");
678 case OSPF_OPAQUE_AREA_LSA
:
679 if ((area
= lsa
->area
) != NULL
)
680 listtop
= area
->opaque_lsa_self
;
683 "Type-10 Opaque-LSA: Reference to AREA is missing?");
685 case OSPF_OPAQUE_AS_LSA
:
686 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
687 if ((area
= lsa
->area
) != NULL
&& (top
= area
->ospf
) == NULL
) {
689 "Type-11 Opaque-LSA: Reference to OSPF is missing?");
690 break; /* Unlikely to happen. */
692 listtop
= top
->opaque_lsa_self
;
695 zlog_warn("lookup_opaque_info_by_type: Unexpected LSA-type(%u)",
701 for (ALL_LIST_ELEMENTS(listtop
, node
, nnode
, oipt
))
702 if (oipt
->opaque_type
== key
)
708 static struct opaque_info_per_id
*
709 register_opaque_info_per_id(struct opaque_info_per_type
*oipt
,
710 struct ospf_lsa
*new)
712 struct opaque_info_per_id
*oipi
;
714 if ((oipi
= XCALLOC(MTYPE_OPAQUE_INFO_PER_ID
,
715 sizeof(struct opaque_info_per_id
)))
717 zlog_warn("register_opaque_info_per_id: XMALLOC: %s",
718 safe_strerror(errno
));
721 oipi
->opaque_id
= GET_OPAQUE_ID(ntohl(new->data
->id
.s_addr
));
722 oipi
->t_opaque_lsa_self
= NULL
;
723 oipi
->opqctl_type
= oipt
;
724 oipi
->lsa
= ospf_lsa_lock(new);
726 listnode_add(oipt
->id_list
, oipi
);
732 static void free_opaque_info_per_id(void *val
)
734 struct opaque_info_per_id
*oipi
= (struct opaque_info_per_id
*)val
;
736 OSPF_TIMER_OFF(oipi
->t_opaque_lsa_self
);
737 if (oipi
->lsa
!= NULL
)
738 ospf_lsa_unlock(&oipi
->lsa
);
739 XFREE(MTYPE_OPAQUE_INFO_PER_ID
, oipi
);
743 static struct opaque_info_per_id
*
744 lookup_opaque_info_by_id(struct opaque_info_per_type
*oipt
,
745 struct ospf_lsa
*lsa
)
747 struct listnode
*node
, *nnode
;
748 struct opaque_info_per_id
*oipi
;
749 uint32_t key
= GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
));
751 for (ALL_LIST_ELEMENTS(oipt
->id_list
, node
, nnode
, oipi
))
752 if (oipi
->opaque_id
== key
)
758 static struct opaque_info_per_id
*register_opaque_lsa(struct ospf_lsa
*new)
760 struct ospf_opaque_functab
*functab
;
761 struct opaque_info_per_type
*oipt
;
762 struct opaque_info_per_id
*oipi
= NULL
;
764 if ((functab
= ospf_opaque_functab_lookup(new)) == NULL
)
767 if ((oipt
= lookup_opaque_info_by_type(new)) == NULL
768 && (oipt
= register_opaque_info_per_type(functab
, new)) == NULL
)
771 if ((oipi
= register_opaque_info_per_id(oipt
, new)) == NULL
)
778 /*------------------------------------------------------------------------*
779 * Followings are (vty) configuration functions for Opaque-LSAs handling.
780 *------------------------------------------------------------------------*/
782 DEFUN (capability_opaque
,
783 capability_opaque_cmd
,
785 "Enable specific OSPF feature\n"
788 VTY_DECLVAR_INSTANCE_CONTEXT(ospf
, ospf
);
790 /* Turn on the "master switch" of opaque-lsa capability. */
791 if (!CHECK_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
)) {
792 if (IS_DEBUG_OSPF_EVENT
)
793 zlog_debug("Opaque capability: OFF -> ON");
795 SET_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
);
796 ospf_renegotiate_optional_capabilities(ospf
);
804 "OSPF specific commands\n"
805 "Enable the Opaque-LSA capability (rfc2370)\n")
807 return capability_opaque(self
, vty
, argc
, argv
);
810 DEFUN (no_capability_opaque
,
811 no_capability_opaque_cmd
,
812 "no capability opaque",
814 "Enable specific OSPF feature\n"
817 VTY_DECLVAR_INSTANCE_CONTEXT(ospf
, ospf
);
819 /* Turn off the "master switch" of opaque-lsa capability. */
820 if (CHECK_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
)) {
821 if (IS_DEBUG_OSPF_EVENT
)
822 zlog_debug("Opaque capability: ON -> OFF");
824 UNSET_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
);
825 ospf_renegotiate_optional_capabilities(ospf
);
830 DEFUN (no_ospf_opaque
,
832 "no ospf opaque-lsa",
834 "OSPF specific commands\n"
835 "Enable the Opaque-LSA capability (rfc2370)\n")
837 return no_capability_opaque(self
, vty
, argc
, argv
);
840 static void ospf_opaque_register_vty(void)
842 install_element(OSPF_NODE
, &capability_opaque_cmd
);
843 install_element(OSPF_NODE
, &no_capability_opaque_cmd
);
844 install_element(OSPF_NODE
, &ospf_opaque_cmd
);
845 install_element(OSPF_NODE
, &no_ospf_opaque_cmd
);
849 /*------------------------------------------------------------------------*
850 * Followings are collection of user-registered function callers.
851 *------------------------------------------------------------------------*/
853 static int opaque_lsa_new_if_callback(struct list
*funclist
,
854 struct interface
*ifp
)
856 struct listnode
*node
, *nnode
;
857 struct ospf_opaque_functab
*functab
;
860 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
861 if (functab
->new_if_hook
!= NULL
)
862 if ((*functab
->new_if_hook
)(ifp
) != 0)
869 static int opaque_lsa_del_if_callback(struct list
*funclist
,
870 struct interface
*ifp
)
872 struct listnode
*node
, *nnode
;
873 struct ospf_opaque_functab
*functab
;
876 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
877 if (functab
->del_if_hook
!= NULL
)
878 if ((*functab
->del_if_hook
)(ifp
) != 0)
885 static void opaque_lsa_ism_change_callback(struct list
*funclist
,
886 struct ospf_interface
*oi
,
889 struct listnode
*node
, *nnode
;
890 struct ospf_opaque_functab
*functab
;
892 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
893 if (functab
->ism_change_hook
!= NULL
)
894 (*functab
->ism_change_hook
)(oi
, old_status
);
899 static void opaque_lsa_nsm_change_callback(struct list
*funclist
,
900 struct ospf_neighbor
*nbr
,
903 struct listnode
*node
, *nnode
;
904 struct ospf_opaque_functab
*functab
;
906 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
907 if (functab
->nsm_change_hook
!= NULL
)
908 (*functab
->nsm_change_hook
)(nbr
, old_status
);
912 static void opaque_lsa_config_write_router_callback(struct list
*funclist
,
915 struct listnode
*node
, *nnode
;
916 struct ospf_opaque_functab
*functab
;
918 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
919 if (functab
->config_write_router
!= NULL
)
920 (*functab
->config_write_router
)(vty
);
924 static void opaque_lsa_config_write_if_callback(struct list
*funclist
,
926 struct interface
*ifp
)
928 struct listnode
*node
, *nnode
;
929 struct ospf_opaque_functab
*functab
;
931 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
932 if (functab
->config_write_if
!= NULL
)
933 (*functab
->config_write_if
)(vty
, ifp
);
937 static void opaque_lsa_config_write_debug_callback(struct list
*funclist
,
940 struct listnode
*node
, *nnode
;
941 struct ospf_opaque_functab
*functab
;
943 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
944 if (functab
->config_write_debug
!= NULL
)
945 (*functab
->config_write_debug
)(vty
);
949 static int opaque_lsa_originate_callback(struct list
*funclist
,
950 void *lsa_type_dependent
)
952 struct listnode
*node
, *nnode
;
953 struct ospf_opaque_functab
*functab
;
956 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
957 if (functab
->lsa_originator
!= NULL
)
958 if ((*functab
->lsa_originator
)(lsa_type_dependent
) != 0)
965 static int new_lsa_callback(struct list
*funclist
, struct ospf_lsa
*lsa
)
967 struct listnode
*node
, *nnode
;
968 struct ospf_opaque_functab
*functab
;
971 /* This function handles ALL types of LSAs, not only opaque ones. */
972 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
973 if (functab
->new_lsa_hook
!= NULL
)
974 if ((*functab
->new_lsa_hook
)(lsa
) != 0)
981 static int del_lsa_callback(struct list
*funclist
, struct ospf_lsa
*lsa
)
983 struct listnode
*node
, *nnode
;
984 struct ospf_opaque_functab
*functab
;
987 /* This function handles ALL types of LSAs, not only opaque ones. */
988 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
989 if (functab
->del_lsa_hook
!= NULL
)
990 if ((*functab
->del_lsa_hook
)(lsa
) != 0)
997 /*------------------------------------------------------------------------*
998 * Followings are glue functions to call Opaque-LSA specific processing.
999 *------------------------------------------------------------------------*/
1001 int ospf_opaque_new_if(struct interface
*ifp
)
1003 struct list
*funclist
;
1006 funclist
= ospf_opaque_wildcard_funclist
;
1007 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
1010 funclist
= ospf_opaque_type9_funclist
;
1011 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
1014 funclist
= ospf_opaque_type10_funclist
;
1015 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
1018 funclist
= ospf_opaque_type11_funclist
;
1019 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
1027 int ospf_opaque_del_if(struct interface
*ifp
)
1029 struct list
*funclist
;
1032 funclist
= ospf_opaque_wildcard_funclist
;
1033 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1036 funclist
= ospf_opaque_type9_funclist
;
1037 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1040 funclist
= ospf_opaque_type10_funclist
;
1041 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1044 funclist
= ospf_opaque_type11_funclist
;
1045 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1053 void ospf_opaque_ism_change(struct ospf_interface
*oi
, int old_status
)
1055 struct list
*funclist
;
1057 funclist
= ospf_opaque_wildcard_funclist
;
1058 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1060 funclist
= ospf_opaque_type9_funclist
;
1061 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1063 funclist
= ospf_opaque_type10_funclist
;
1064 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1066 funclist
= ospf_opaque_type11_funclist
;
1067 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1072 void ospf_opaque_nsm_change(struct ospf_neighbor
*nbr
, int old_state
)
1075 struct list
*funclist
;
1077 if ((top
= oi_to_top(nbr
->oi
)) == NULL
)
1080 if (old_state
!= NSM_Full
&& nbr
->state
== NSM_Full
) {
1081 if (CHECK_FLAG(nbr
->options
, OSPF_OPTION_O
)) {
1082 if (!CHECK_FLAG(top
->opaque
,
1083 OPAQUE_OPERATION_READY_BIT
)) {
1084 if (IS_DEBUG_OSPF_EVENT
)
1086 "Opaque-LSA: Now get operational!");
1088 SET_FLAG(top
->opaque
,
1089 OPAQUE_OPERATION_READY_BIT
);
1092 ospf_opaque_lsa_originate_schedule(nbr
->oi
, NULL
);
1094 } else if (old_state
== NSM_Full
&& nbr
->state
!= NSM_Full
) {
1097 * If no more opaque-capable full-state neighbor remains in the
1098 * flooding scope which corresponds to Opaque-LSA type, periodic
1099 * LS flooding should be stopped.
1105 funclist
= ospf_opaque_wildcard_funclist
;
1106 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1108 funclist
= ospf_opaque_type9_funclist
;
1109 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1111 funclist
= ospf_opaque_type10_funclist
;
1112 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1114 funclist
= ospf_opaque_type11_funclist
;
1115 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1121 void ospf_opaque_config_write_router(struct vty
*vty
, struct ospf
*ospf
)
1123 struct list
*funclist
;
1125 if (CHECK_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
))
1126 vty_out(vty
, " capability opaque\n");
1128 funclist
= ospf_opaque_wildcard_funclist
;
1129 opaque_lsa_config_write_router_callback(funclist
, vty
);
1131 funclist
= ospf_opaque_type9_funclist
;
1132 opaque_lsa_config_write_router_callback(funclist
, vty
);
1134 funclist
= ospf_opaque_type10_funclist
;
1135 opaque_lsa_config_write_router_callback(funclist
, vty
);
1137 funclist
= ospf_opaque_type11_funclist
;
1138 opaque_lsa_config_write_router_callback(funclist
, vty
);
1143 void ospf_opaque_config_write_if(struct vty
*vty
, struct interface
*ifp
)
1145 struct list
*funclist
;
1147 funclist
= ospf_opaque_wildcard_funclist
;
1148 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1150 funclist
= ospf_opaque_type9_funclist
;
1151 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1153 funclist
= ospf_opaque_type10_funclist
;
1154 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1156 funclist
= ospf_opaque_type11_funclist
;
1157 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1162 void ospf_opaque_config_write_debug(struct vty
*vty
)
1164 struct list
*funclist
;
1166 funclist
= ospf_opaque_wildcard_funclist
;
1167 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1169 funclist
= ospf_opaque_type9_funclist
;
1170 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1172 funclist
= ospf_opaque_type10_funclist
;
1173 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1175 funclist
= ospf_opaque_type11_funclist
;
1176 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1181 void show_opaque_info_detail(struct vty
*vty
, struct ospf_lsa
*lsa
)
1183 struct lsa_header
*lsah
= (struct lsa_header
*)lsa
->data
;
1184 uint32_t lsid
= ntohl(lsah
->id
.s_addr
);
1185 uint8_t opaque_type
= GET_OPAQUE_TYPE(lsid
);
1186 uint32_t opaque_id
= GET_OPAQUE_ID(lsid
);
1187 struct ospf_opaque_functab
*functab
;
1189 /* Switch output functionality by vty address. */
1191 vty_out(vty
, " Opaque-Type %u (%s)\n", opaque_type
,
1192 ospf_opaque_type_name(opaque_type
));
1193 vty_out(vty
, " Opaque-ID 0x%x\n", opaque_id
);
1195 vty_out(vty
, " Opaque-Info: %u octets of data%s\n",
1196 ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
,
1197 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
) ? ""
1206 : "(Invalid length?)");
1209 /* Call individual output functions. */
1210 if ((functab
= ospf_opaque_functab_lookup(lsa
)) != NULL
)
1211 if (functab
->show_opaque_info
!= NULL
)
1212 (*functab
->show_opaque_info
)(vty
, lsa
);
1217 void ospf_opaque_lsa_dump(struct stream
*s
, uint16_t length
)
1219 struct ospf_lsa lsa
;
1221 lsa
.data
= (struct lsa_header
*)stream_pnt(s
);
1222 show_opaque_info_detail(NULL
, &lsa
);
1226 static int ospf_opaque_lsa_install_hook(struct ospf_lsa
*lsa
)
1228 struct list
*funclist
;
1232 * Some Opaque-LSA user may want to monitor every LSA installation
1233 * into the LSDB, regardless with target LSA type.
1235 funclist
= ospf_opaque_wildcard_funclist
;
1236 if (new_lsa_callback(funclist
, lsa
) != 0)
1239 funclist
= ospf_opaque_type9_funclist
;
1240 if (new_lsa_callback(funclist
, lsa
) != 0)
1243 funclist
= ospf_opaque_type10_funclist
;
1244 if (new_lsa_callback(funclist
, lsa
) != 0)
1247 funclist
= ospf_opaque_type11_funclist
;
1248 if (new_lsa_callback(funclist
, lsa
) != 0)
1256 static int ospf_opaque_lsa_delete_hook(struct ospf_lsa
*lsa
)
1258 struct list
*funclist
;
1262 * Some Opaque-LSA user may want to monitor every LSA deletion
1263 * from the LSDB, regardless with target LSA type.
1265 funclist
= ospf_opaque_wildcard_funclist
;
1266 if (del_lsa_callback(funclist
, lsa
) != 0)
1269 funclist
= ospf_opaque_type9_funclist
;
1270 if (del_lsa_callback(funclist
, lsa
) != 0)
1273 funclist
= ospf_opaque_type10_funclist
;
1274 if (del_lsa_callback(funclist
, lsa
) != 0)
1277 funclist
= ospf_opaque_type11_funclist
;
1278 if (del_lsa_callback(funclist
, lsa
) != 0)
1286 /*------------------------------------------------------------------------*
1287 * Followings are Opaque-LSA origination/refresh management functions.
1288 *------------------------------------------------------------------------*/
1290 static int ospf_opaque_type9_lsa_originate(struct thread
*t
);
1291 static int ospf_opaque_type10_lsa_originate(struct thread
*t
);
1292 static int ospf_opaque_type11_lsa_originate(struct thread
*t
);
1293 static void ospf_opaque_lsa_reoriginate_resume(struct list
*listtop
, void *arg
);
1295 void ospf_opaque_lsa_originate_schedule(struct ospf_interface
*oi
, int *delay0
)
1298 struct ospf_area
*area
;
1299 struct listnode
*node
, *nnode
;
1300 struct opaque_info_per_type
*oipt
;
1303 if ((top
= oi_to_top(oi
)) == NULL
|| (area
= oi
->area
) == NULL
) {
1305 "ospf_opaque_lsa_originate_schedule: Invalid argument?");
1309 /* It may not a right time to schedule origination now. */
1310 if (!CHECK_FLAG(top
->opaque
, OPAQUE_OPERATION_READY_BIT
)) {
1311 if (IS_DEBUG_OSPF_EVENT
)
1313 "ospf_opaque_lsa_originate_schedule: Not operational.");
1314 goto out
; /* This is not an error. */
1321 * There might be some entries that have been waiting for triggering
1322 * of per opaque-type re-origination get resumed.
1324 ospf_opaque_lsa_reoriginate_resume(oi
->opaque_lsa_self
, (void *)oi
);
1325 ospf_opaque_lsa_reoriginate_resume(area
->opaque_lsa_self
, (void *)area
);
1326 ospf_opaque_lsa_reoriginate_resume(top
->opaque_lsa_self
, (void *)top
);
1329 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1331 if (!list_isempty(ospf_opaque_type9_funclist
)
1332 && list_isempty(oi
->opaque_lsa_self
)
1333 && oi
->t_opaque_lsa_self
== NULL
) {
1334 if (IS_DEBUG_OSPF_EVENT
)
1336 "Schedule Type-9 Opaque-LSA origination in %d ms later.",
1338 oi
->t_opaque_lsa_self
= NULL
;
1339 thread_add_timer_msec(master
, ospf_opaque_type9_lsa_originate
,
1340 oi
, delay
, &oi
->t_opaque_lsa_self
);
1341 delay
+= top
->min_ls_interval
;
1344 if (!list_isempty(ospf_opaque_type10_funclist
)
1345 && list_isempty(area
->opaque_lsa_self
)
1346 && area
->t_opaque_lsa_self
== NULL
) {
1348 * One AREA may contain multiple OIs, but above 2nd and 3rd
1349 * conditions prevent from scheduling the originate function
1352 if (IS_DEBUG_OSPF_EVENT
)
1354 "Schedule Type-10 Opaque-LSA origination in %d ms later.",
1356 area
->t_opaque_lsa_self
= NULL
;
1357 thread_add_timer_msec(master
, ospf_opaque_type10_lsa_originate
,
1358 area
, delay
, &area
->t_opaque_lsa_self
);
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
) {
1366 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1367 * conditions prevent from scheduling the originate function
1370 if (IS_DEBUG_OSPF_EVENT
)
1372 "Schedule Type-11 Opaque-LSA origination in %d ms later.",
1374 top
->t_opaque_lsa_self
= NULL
;
1375 thread_add_timer_msec(master
, ospf_opaque_type11_lsa_originate
,
1376 top
, delay
, &top
->t_opaque_lsa_self
);
1377 delay
+= top
->min_ls_interval
;
1381 * Following section treats a special situation that this node's
1382 * opaque capability has changed as "ON -> OFF -> ON".
1384 if (!list_isempty(ospf_opaque_type9_funclist
)
1385 && !list_isempty(oi
->opaque_lsa_self
)) {
1386 for (ALL_LIST_ELEMENTS(oi
->opaque_lsa_self
, node
, nnode
,
1389 * removed the test for
1390 * (! list_isempty (oipt->id_list)) * Handler is
1392 * because opaque cababilities ON -> OFF -> ON result in
1393 * list_isempty (oipt->id_list)
1396 if (oipt
->t_opaque_lsa_self
1397 != NULL
/* Waiting for a thread call. */
1398 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1403 ospf_opaque_lsa_reoriginate_schedule(
1404 (void *)oi
, OSPF_OPAQUE_LINK_LSA
,
1409 if (!list_isempty(ospf_opaque_type10_funclist
)
1410 && !list_isempty(area
->opaque_lsa_self
)) {
1411 for (ALL_LIST_ELEMENTS(area
->opaque_lsa_self
, node
, nnode
,
1414 * removed the test for
1415 * (! list_isempty (oipt->id_list)) * Handler is
1417 * because opaque cababilities ON -> OFF -> ON result in
1418 * list_isempty (oipt->id_list)
1421 if (oipt
->t_opaque_lsa_self
1422 != NULL
/* Waiting for a thread call. */
1423 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1428 ospf_opaque_lsa_reoriginate_schedule(
1429 (void *)area
, OSPF_OPAQUE_AREA_LSA
,
1434 if (!list_isempty(ospf_opaque_type11_funclist
)
1435 && !list_isempty(top
->opaque_lsa_self
)) {
1436 for (ALL_LIST_ELEMENTS(top
->opaque_lsa_self
, node
, nnode
,
1439 * removed the test for
1440 * (! list_isempty (oipt->id_list)) * Handler is
1442 * because opaque cababilities ON -> OFF -> ON result in
1443 * list_isempty (oipt->id_list)
1446 if (oipt
->t_opaque_lsa_self
1447 != NULL
/* Waiting for a thread call. */
1448 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1453 ospf_opaque_lsa_reoriginate_schedule((void *)top
,
1466 static int ospf_opaque_type9_lsa_originate(struct thread
*t
)
1468 struct ospf_interface
*oi
;
1472 oi
->t_opaque_lsa_self
= NULL
;
1474 if (IS_DEBUG_OSPF_EVENT
)
1475 zlog_debug("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
1478 rc
= opaque_lsa_originate_callback(ospf_opaque_type9_funclist
, oi
);
1483 static int ospf_opaque_type10_lsa_originate(struct thread
*t
)
1485 struct ospf_area
*area
;
1488 area
= THREAD_ARG(t
);
1489 area
->t_opaque_lsa_self
= NULL
;
1491 if (IS_DEBUG_OSPF_EVENT
)
1493 "Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
1494 inet_ntoa(area
->area_id
));
1496 rc
= opaque_lsa_originate_callback(ospf_opaque_type10_funclist
, area
);
1501 static int ospf_opaque_type11_lsa_originate(struct thread
*t
)
1506 top
= THREAD_ARG(t
);
1507 top
->t_opaque_lsa_self
= NULL
;
1509 if (IS_DEBUG_OSPF_EVENT
)
1511 "Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
1513 rc
= opaque_lsa_originate_callback(ospf_opaque_type11_funclist
, top
);
1518 static void ospf_opaque_lsa_reoriginate_resume(struct list
*listtop
, void *arg
)
1520 struct listnode
*node
, *nnode
;
1521 struct opaque_info_per_type
*oipt
;
1522 struct ospf_opaque_functab
*functab
;
1524 if (listtop
== NULL
)
1528 * Pickup oipt entries those which in SUSPEND status, and give
1529 * them a chance to start re-origination now.
1531 for (ALL_LIST_ELEMENTS(listtop
, node
, nnode
, oipt
)) {
1532 if (oipt
->status
!= PROC_SUSPEND
)
1535 oipt
->status
= PROC_NORMAL
;
1537 if ((functab
= oipt
->functab
) == NULL
1538 || functab
->lsa_originator
== NULL
)
1541 if ((*functab
->lsa_originator
)(arg
) != 0) {
1543 "ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)",
1553 struct ospf_lsa
*ospf_opaque_lsa_install(struct ospf_lsa
*lsa
, int rt_recalc
)
1555 struct ospf_lsa
*new = NULL
;
1556 struct opaque_info_per_type
*oipt
;
1557 struct opaque_info_per_id
*oipi
;
1560 /* Don't take "rt_recalc" into consideration for now. */ /* XXX */
1562 if (!IS_LSA_SELF(lsa
)) {
1563 new = lsa
; /* Don't touch this LSA. */
1567 if (IS_DEBUG_OSPF(lsa
, LSA_INSTALL
))
1569 "Install Type-%u Opaque-LSA: [opaque-type=%u, opaque-id=%x]",
1571 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
1572 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
1574 /* Replace the existing lsa with the new one. */
1575 if ((oipt
= lookup_opaque_info_by_type(lsa
)) != NULL
1576 && (oipi
= lookup_opaque_info_by_id(oipt
, lsa
)) != NULL
) {
1577 ospf_lsa_unlock(&oipi
->lsa
);
1578 oipi
->lsa
= ospf_lsa_lock(lsa
);
1580 /* Register the new lsa entry and get its control info. */
1581 else if ((oipi
= register_opaque_lsa(lsa
)) == NULL
) {
1582 zlog_warn("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1587 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1588 * for periodic refresh of self-originated Opaque-LSAs.
1590 switch (lsa
->data
->type
) {
1591 case OSPF_OPAQUE_LINK_LSA
:
1592 if ((top
= oi_to_top(lsa
->oi
)) == NULL
) {
1593 /* Above conditions must have passed. */
1594 zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?");
1598 case OSPF_OPAQUE_AREA_LSA
:
1599 if (lsa
->area
== NULL
|| (top
= lsa
->area
->ospf
) == NULL
) {
1600 /* Above conditions must have passed. */
1601 zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?");
1605 case OSPF_OPAQUE_AS_LSA
:
1606 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
1607 if (lsa
->area
!= NULL
&& (top
= lsa
->area
->ospf
) == NULL
) {
1608 /* Above conditions must have passed. */
1609 zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?");
1614 zlog_warn("ospf_opaque_lsa_install: Unexpected LSA-type(%u)",
1619 ospf_refresher_register_lsa(top
, lsa
);
1626 struct ospf_lsa
*ospf_opaque_lsa_refresh(struct ospf_lsa
*lsa
)
1629 struct ospf_opaque_functab
*functab
;
1630 struct ospf_lsa
*new = NULL
;
1632 ospf
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
1634 if ((functab
= ospf_opaque_functab_lookup(lsa
)) == NULL
1635 || functab
->lsa_refresher
== NULL
) {
1637 * Though this LSA seems to have originated on this node, the
1638 * handling module for this "lsa-type and opaque-type" was
1639 * already deleted sometime ago.
1640 * Anyway, this node still has a responsibility to flush this
1641 * LSA from the routing domain.
1643 if (IS_DEBUG_OSPF_EVENT
)
1644 zlog_debug("LSA[Type%d:%s]: Flush stray Opaque-LSA",
1645 lsa
->data
->type
, inet_ntoa(lsa
->data
->id
));
1647 lsa
->data
->ls_age
= htons(OSPF_LSA_MAXAGE
);
1648 ospf_lsa_flush(ospf
, lsa
);
1650 new = (*functab
->lsa_refresher
)(lsa
);
1655 /*------------------------------------------------------------------------*
1656 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1657 * triggered by external interventions (vty session, signaling, etc).
1658 *------------------------------------------------------------------------*/
1660 #define OSPF_OPAQUE_TIMER_ON(T,F,L,V) thread_add_timer_msec (master, (F), (L), (V), &(T))
1662 static struct ospf_lsa
*pseudo_lsa(struct ospf_interface
*oi
,
1663 struct ospf_area
*area
, uint8_t lsa_type
,
1664 uint8_t opaque_type
);
1665 static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread
*t
);
1666 static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread
*t
);
1667 static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread
*t
);
1668 static int ospf_opaque_lsa_refresh_timer(struct thread
*t
);
1670 void ospf_opaque_lsa_reoriginate_schedule(void *lsa_type_dependent
,
1671 uint8_t lsa_type
, uint8_t opaque_type
)
1673 struct ospf
*top
= NULL
;
1674 struct ospf_area dummy
, *area
= NULL
;
1675 struct ospf_interface
*oi
= NULL
;
1677 struct ospf_lsa
*lsa
;
1678 struct opaque_info_per_type
*oipt
;
1679 int (*func
)(struct thread
* t
) = NULL
;
1683 case OSPF_OPAQUE_LINK_LSA
:
1684 if ((oi
= (struct ospf_interface
*)lsa_type_dependent
)
1687 "ospf_opaque_lsa_reoriginate_schedule:"
1688 " Type-9 Opaque-LSA: Invalid parameter?");
1691 if ((top
= oi_to_top(oi
)) == NULL
) {
1693 "ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1697 if (!list_isempty(ospf_opaque_type9_funclist
)
1698 && list_isempty(oi
->opaque_lsa_self
)
1699 && oi
->t_opaque_lsa_self
!= NULL
) {
1701 "Type-9 Opaque-LSA (opaque_type=%u):"
1702 " Common origination for OI(%s) has already started",
1703 opaque_type
, IF_NAME(oi
));
1706 func
= ospf_opaque_type9_lsa_reoriginate_timer
;
1708 case OSPF_OPAQUE_AREA_LSA
:
1709 if ((area
= (struct ospf_area
*)lsa_type_dependent
) == NULL
) {
1711 "ospf_opaque_lsa_reoriginate_schedule:"
1712 " Type-10 Opaque-LSA: Invalid parameter?");
1715 if ((top
= area
->ospf
) == NULL
) {
1717 "ospf_opaque_lsa_reoriginate_schedule:"
1718 " AREA(%s) -> TOP?",
1719 inet_ntoa(area
->area_id
));
1722 if (!list_isempty(ospf_opaque_type10_funclist
)
1723 && list_isempty(area
->opaque_lsa_self
)
1724 && area
->t_opaque_lsa_self
!= NULL
) {
1726 "Type-10 Opaque-LSA (opaque_type=%u):"
1727 " Common origination for AREA(%s) has already started",
1728 opaque_type
, inet_ntoa(area
->area_id
));
1731 func
= ospf_opaque_type10_lsa_reoriginate_timer
;
1733 case OSPF_OPAQUE_AS_LSA
:
1734 if ((top
= (struct ospf
*)lsa_type_dependent
) == NULL
) {
1736 "ospf_opaque_lsa_reoriginate_schedule:"
1737 " Type-11 Opaque-LSA: Invalid parameter?");
1740 if (!list_isempty(ospf_opaque_type11_funclist
)
1741 && list_isempty(top
->opaque_lsa_self
)
1742 && top
->t_opaque_lsa_self
!= NULL
) {
1744 "Type-11 Opaque-LSA (opaque_type=%u):"
1745 " Common origination has already started",
1750 /* Fake "area" to pass "ospf" to a lookup function later. */
1754 func
= ospf_opaque_type11_lsa_reoriginate_timer
;
1758 "ospf_opaque_lsa_reoriginate_schedule:"
1759 " Unexpected LSA-type(%u)",
1764 /* It may not a right time to schedule reorigination now. */
1765 if (!CHECK_FLAG(top
->opaque
, OPAQUE_OPERATION_READY_BIT
)) {
1766 if (IS_DEBUG_OSPF_EVENT
)
1768 "ospf_opaque_lsa_reoriginate_schedule: Not operational.");
1769 goto out
; /* This is not an error. */
1772 /* Generate a dummy lsa to be passed for a lookup function. */
1773 lsa
= pseudo_lsa(oi
, area
, lsa_type
, opaque_type
);
1774 lsa
->vrf_id
= top
->vrf_id
;
1776 if ((oipt
= lookup_opaque_info_by_type(lsa
)) == NULL
) {
1777 struct ospf_opaque_functab
*functab
;
1778 if ((functab
= ospf_opaque_functab_lookup(lsa
)) == NULL
) {
1780 "ospf_opaque_lsa_reoriginate_schedule:"
1781 " No associated function?: lsa_type(%u),"
1783 lsa_type
, opaque_type
);
1786 if ((oipt
= register_opaque_info_per_type(functab
, lsa
))
1789 "ospf_opaque_lsa_reoriginate_schedule:"
1790 " Cannot get a control info?: lsa_type(%u),"
1792 lsa_type
, opaque_type
);
1797 if (oipt
->t_opaque_lsa_self
!= NULL
) {
1798 if (IS_DEBUG_OSPF_EVENT
)
1800 "Type-%u Opaque-LSA has already scheduled to"
1801 " RE-ORIGINATE: [opaque-type=%u]",
1803 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)));
1808 * Different from initial origination time, in which various conditions
1809 * (opaque capability, neighbor status etc) are assured by caller of
1810 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1811 * it is highly possible that these conditions might not be satisfied
1812 * at the time of re-origination function is to be called.
1814 delay
= top
->min_ls_interval
; /* XXX */
1816 if (IS_DEBUG_OSPF_EVENT
)
1818 "Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
1819 " ms later: [opaque-type=%u]",
1821 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)));
1823 OSPF_OPAQUE_TIMER_ON(oipt
->t_opaque_lsa_self
, func
, oipt
, delay
);
1829 static struct ospf_lsa
*pseudo_lsa(struct ospf_interface
*oi
,
1830 struct ospf_area
*area
, uint8_t lsa_type
,
1831 uint8_t opaque_type
)
1833 static struct ospf_lsa lsa
= {0};
1834 static struct lsa_header lsah
= {0};
1840 lsa
.vrf_id
= VRF_DEFAULT
;
1842 lsah
.type
= lsa_type
;
1843 tmp
= SET_OPAQUE_LSID(opaque_type
, 0); /* Opaque-ID is unused here. */
1844 lsah
.id
.s_addr
= htonl(tmp
);
1849 static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread
*t
)
1851 struct opaque_info_per_type
*oipt
;
1852 struct ospf_opaque_functab
*functab
;
1854 struct ospf_interface
*oi
;
1857 oipt
= THREAD_ARG(t
);
1858 oipt
->t_opaque_lsa_self
= NULL
;
1860 if ((functab
= oipt
->functab
) == NULL
1861 || functab
->lsa_originator
== NULL
) {
1863 "ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1867 oi
= (struct ospf_interface
*)oipt
->owner
;
1868 if ((top
= oi_to_top(oi
)) == NULL
) {
1870 "ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1874 if (!CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)
1875 || !ospf_if_is_enable(oi
)
1876 || ospf_nbr_count_opaque_capable(oi
) == 0) {
1877 if (IS_DEBUG_OSPF_EVENT
)
1879 "Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...",
1882 oipt
->status
= PROC_SUSPEND
;
1887 if (IS_DEBUG_OSPF_EVENT
)
1889 "Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)",
1890 oipt
->opaque_type
, IF_NAME(oi
));
1892 rc
= (*functab
->lsa_originator
)(oi
);
1897 static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread
*t
)
1899 struct opaque_info_per_type
*oipt
;
1900 struct ospf_opaque_functab
*functab
;
1901 struct listnode
*node
, *nnode
;
1903 struct ospf_area
*area
;
1904 struct ospf_interface
*oi
;
1907 oipt
= THREAD_ARG(t
);
1908 oipt
->t_opaque_lsa_self
= NULL
;
1910 if ((functab
= oipt
->functab
) == NULL
1911 || functab
->lsa_originator
== NULL
) {
1913 "ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1917 area
= (struct ospf_area
*)oipt
->owner
;
1918 if (area
== NULL
|| (top
= area
->ospf
) == NULL
) {
1920 "ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1924 /* There must be at least one "opaque-capable, full-state" neighbor. */
1926 for (ALL_LIST_ELEMENTS(area
->oiflist
, node
, nnode
, oi
)) {
1927 if ((n
= ospf_nbr_count_opaque_capable(oi
)) > 0)
1931 if (n
== 0 || !CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)) {
1932 if (IS_DEBUG_OSPF_EVENT
)
1934 "Suspend re-origination of Type-10 Opaque-LSAs"
1935 " (opaque-type=%u) for a while...",
1938 oipt
->status
= PROC_SUSPEND
;
1943 if (IS_DEBUG_OSPF_EVENT
)
1945 "Timer[Type10-LSA]: Re-originate Opaque-LSAs"
1946 " (opaque-type=%u) for Area %s",
1947 oipt
->opaque_type
, inet_ntoa(area
->area_id
));
1949 rc
= (*functab
->lsa_originator
)(area
);
1954 static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread
*t
)
1956 struct opaque_info_per_type
*oipt
;
1957 struct ospf_opaque_functab
*functab
;
1961 oipt
= THREAD_ARG(t
);
1962 oipt
->t_opaque_lsa_self
= NULL
;
1964 if ((functab
= oipt
->functab
) == NULL
1965 || functab
->lsa_originator
== NULL
) {
1967 "ospf_opaque_type11_lsa_reoriginate_timer:"
1968 " No associated function?");
1972 if ((top
= (struct ospf
*)oipt
->owner
) == NULL
) {
1974 "ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1978 if (!CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)) {
1979 if (IS_DEBUG_OSPF_EVENT
)
1981 "Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...",
1984 oipt
->status
= PROC_SUSPEND
;
1989 if (IS_DEBUG_OSPF_EVENT
)
1991 "Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).",
1994 rc
= (*functab
->lsa_originator
)(top
);
1999 void ospf_opaque_lsa_refresh_schedule(struct ospf_lsa
*lsa0
)
2001 struct opaque_info_per_type
*oipt
;
2002 struct opaque_info_per_id
*oipi
;
2003 struct ospf_lsa
*lsa
;
2007 if ((oipt
= lookup_opaque_info_by_type(lsa0
)) == NULL
2008 || (oipi
= lookup_opaque_info_by_id(oipt
, lsa0
)) == NULL
) {
2010 "ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
2014 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2015 if ((lsa
= oipi
->lsa
) == NULL
) {
2016 zlog_warn("ospf_opaque_lsa_refresh_schedule: Something wrong?");
2020 if (oipi
->t_opaque_lsa_self
!= NULL
) {
2021 if (IS_DEBUG_OSPF_EVENT
)
2023 "Type-%u Opaque-LSA has already scheduled to REFRESH: [opaque-type=%u, opaque-id=%x]",
2025 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
2026 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
2030 /* Delete this lsa from neighbor retransmit-list. */
2031 switch (lsa
->data
->type
) {
2032 case OSPF_OPAQUE_LINK_LSA
:
2033 case OSPF_OPAQUE_AREA_LSA
:
2034 ospf_ls_retransmit_delete_nbr_area(lsa
->area
, lsa
);
2036 case OSPF_OPAQUE_AS_LSA
:
2037 top
= ospf_lookup_by_vrf_id(lsa0
->vrf_id
);
2038 if ((lsa0
->area
!= NULL
) && (lsa0
->area
->ospf
!= NULL
))
2039 top
= lsa0
->area
->ospf
;
2040 ospf_ls_retransmit_delete_nbr_as(top
, lsa
);
2044 "ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)",
2049 delay
= ospf_lsa_refresh_delay(lsa
);
2051 if (IS_DEBUG_OSPF_EVENT
)
2053 "Schedule Type-%u Opaque-LSA to REFRESH in %d sec later: [opaque-type=%u, opaque-id=%x]",
2054 lsa
->data
->type
, delay
,
2055 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
2056 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
2058 OSPF_OPAQUE_TIMER_ON(oipi
->t_opaque_lsa_self
,
2059 ospf_opaque_lsa_refresh_timer
, oipi
, delay
* 1000);
2064 static int ospf_opaque_lsa_refresh_timer(struct thread
*t
)
2066 struct opaque_info_per_id
*oipi
;
2067 struct ospf_opaque_functab
*functab
;
2068 struct ospf_lsa
*lsa
;
2070 if (IS_DEBUG_OSPF_EVENT
)
2071 zlog_debug("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
2073 oipi
= THREAD_ARG(t
);
2074 oipi
->t_opaque_lsa_self
= NULL
;
2076 if ((lsa
= oipi
->lsa
) != NULL
)
2077 if ((functab
= oipi
->opqctl_type
->functab
) != NULL
)
2078 if (functab
->lsa_refresher
!= NULL
)
2079 (*functab
->lsa_refresher
)(lsa
);
2084 void ospf_opaque_lsa_flush_schedule(struct ospf_lsa
*lsa0
)
2086 struct opaque_info_per_type
*oipt
;
2087 struct opaque_info_per_id
*oipi
;
2088 struct ospf_lsa
*lsa
;
2091 top
= ospf_lookup_by_vrf_id(lsa0
->vrf_id
);
2093 if ((oipt
= lookup_opaque_info_by_type(lsa0
)) == NULL
2094 || (oipi
= lookup_opaque_info_by_id(oipt
, lsa0
)) == NULL
) {
2095 zlog_warn("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2099 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2100 if ((lsa
= oipi
->lsa
) == NULL
) {
2101 zlog_warn("ospf_opaque_lsa_flush_schedule: Something wrong?");
2105 /* Delete this lsa from neighbor retransmit-list. */
2106 switch (lsa
->data
->type
) {
2107 case OSPF_OPAQUE_LINK_LSA
:
2108 case OSPF_OPAQUE_AREA_LSA
:
2109 ospf_ls_retransmit_delete_nbr_area(lsa
->area
, lsa
);
2111 case OSPF_OPAQUE_AS_LSA
:
2112 if ((lsa0
->area
!= NULL
) && (lsa0
->area
->ospf
!= NULL
))
2113 top
= lsa0
->area
->ospf
;
2114 ospf_ls_retransmit_delete_nbr_as(top
, lsa
);
2118 "ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)",
2123 /* Dequeue listnode entry from the list. */
2124 listnode_delete(oipt
->id_list
, oipi
);
2126 /* Avoid misjudgement in the next lookup. */
2127 if (listcount(oipt
->id_list
) == 0)
2128 oipt
->id_list
->head
= oipt
->id_list
->tail
= NULL
;
2130 /* Disassociate internal control information with the given lsa. */
2131 free_opaque_info_per_id((void *)oipi
);
2133 /* Force given lsa's age to MaxAge. */
2134 lsa
->data
->ls_age
= htons(OSPF_LSA_MAXAGE
);
2136 if (IS_DEBUG_OSPF_EVENT
)
2138 "Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]",
2140 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
2141 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
2143 /* This lsa will be flushed and removed eventually. */
2144 ospf_lsa_flush(top
, lsa
);
2150 void ospf_opaque_self_originated_lsa_received(struct ospf_neighbor
*nbr
,
2151 struct ospf_lsa
*lsa
)
2155 if ((top
= oi_to_top(nbr
->oi
)) == NULL
)
2159 * Since these LSA entries are not yet installed into corresponding
2160 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2162 lsa
->data
->ls_age
= htons(OSPF_LSA_MAXAGE
);
2163 switch (lsa
->data
->type
) {
2164 case OSPF_OPAQUE_LINK_LSA
:
2165 ospf_flood_through_area(nbr
->oi
->area
, NULL
/*inbr*/, lsa
);
2167 case OSPF_OPAQUE_AREA_LSA
:
2168 ospf_flood_through_area(nbr
->oi
->area
, NULL
/*inbr*/, lsa
);
2170 case OSPF_OPAQUE_AS_LSA
:
2171 ospf_flood_through_as(top
, NULL
/*inbr*/, lsa
);
2175 "ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)",
2179 ospf_lsa_discard(lsa
); /* List "lsas" will be deleted by caller. */
2182 /*------------------------------------------------------------------------*
2183 * Followings are util functions; probably be used by Opaque-LSAs only...
2184 *------------------------------------------------------------------------*/
2186 struct ospf
*oi_to_top(struct ospf_interface
*oi
)
2188 struct ospf
*top
= NULL
;
2189 struct ospf_area
*area
;
2191 if (oi
== NULL
|| (area
= oi
->area
) == NULL
2192 || (top
= area
->ospf
) == NULL
)
2193 zlog_warn("Broken relationship for \"OI -> AREA -> OSPF\"?");