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(u_char 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 u_int32_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(u_char 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 u_char lsa_type
, u_char 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(u_char lsa_type
, u_char 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 u_char 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
);
618 listnode_delete(oi
->opaque_lsa_self
, oipt
);
621 case OSPF_OPAQUE_AREA_LSA
: {
622 struct ospf_area
*area
= (struct ospf_area
*)(oipt
->owner
);
624 listnode_delete(area
->opaque_lsa_self
, oipt
);
627 case OSPF_OPAQUE_AS_LSA
: {
628 struct ospf
*top
= (struct ospf
*)(oipt
->owner
);
630 listnode_delete(top
->opaque_lsa_self
, oipt
);
634 zlog_warn("%s: Unexpected LSA-type(%u)", __func__
,
636 break; /* This case may not exist. */
640 static void free_opaque_info_per_type(void *val
)
642 struct opaque_info_per_type
*oipt
= (struct opaque_info_per_type
*)val
;
643 struct opaque_info_per_id
*oipi
;
644 struct ospf_lsa
*lsa
;
645 struct listnode
*node
, *nnode
;
647 /* Control information per opaque-id may still exist. */
648 for (ALL_LIST_ELEMENTS(oipt
->id_list
, node
, nnode
, oipi
)) {
649 if ((lsa
= oipi
->lsa
) == NULL
)
651 if (IS_LSA_MAXAGE(lsa
))
653 ospf_opaque_lsa_flush_schedule(lsa
);
656 OSPF_TIMER_OFF(oipt
->t_opaque_lsa_self
);
657 list_delete_and_null(&oipt
->id_list
);
658 XFREE(MTYPE_OPAQUE_INFO_PER_TYPE
, oipt
);
662 static struct opaque_info_per_type
*
663 lookup_opaque_info_by_type(struct ospf_lsa
*lsa
)
666 struct ospf_area
*area
;
667 struct ospf_interface
*oi
;
668 struct list
*listtop
= NULL
;
669 struct listnode
*node
, *nnode
;
670 struct opaque_info_per_type
*oipt
= NULL
;
671 u_char key
= GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
));
673 switch (lsa
->data
->type
) {
674 case OSPF_OPAQUE_LINK_LSA
:
675 if ((oi
= lsa
->oi
) != NULL
)
676 listtop
= oi
->opaque_lsa_self
;
679 "Type-9 Opaque-LSA: Reference to OI is missing?");
681 case OSPF_OPAQUE_AREA_LSA
:
682 if ((area
= lsa
->area
) != NULL
)
683 listtop
= area
->opaque_lsa_self
;
686 "Type-10 Opaque-LSA: Reference to AREA is missing?");
688 case OSPF_OPAQUE_AS_LSA
:
689 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
690 if ((area
= lsa
->area
) != NULL
&& (top
= area
->ospf
) == NULL
) {
692 "Type-11 Opaque-LSA: Reference to OSPF is missing?");
693 break; /* Unlikely to happen. */
695 listtop
= top
->opaque_lsa_self
;
698 zlog_warn("lookup_opaque_info_by_type: Unexpected LSA-type(%u)",
704 for (ALL_LIST_ELEMENTS(listtop
, node
, nnode
, oipt
))
705 if (oipt
->opaque_type
== key
)
711 static struct opaque_info_per_id
*
712 register_opaque_info_per_id(struct opaque_info_per_type
*oipt
,
713 struct ospf_lsa
*new)
715 struct opaque_info_per_id
*oipi
;
717 if ((oipi
= XCALLOC(MTYPE_OPAQUE_INFO_PER_ID
,
718 sizeof(struct opaque_info_per_id
)))
720 zlog_warn("register_opaque_info_per_id: XMALLOC: %s",
721 safe_strerror(errno
));
724 oipi
->opaque_id
= GET_OPAQUE_ID(ntohl(new->data
->id
.s_addr
));
725 oipi
->t_opaque_lsa_self
= NULL
;
726 oipi
->opqctl_type
= oipt
;
727 oipi
->lsa
= ospf_lsa_lock(new);
729 listnode_add(oipt
->id_list
, oipi
);
735 static void free_opaque_info_per_id(void *val
)
737 struct opaque_info_per_id
*oipi
= (struct opaque_info_per_id
*)val
;
739 OSPF_TIMER_OFF(oipi
->t_opaque_lsa_self
);
740 if (oipi
->lsa
!= NULL
)
741 ospf_lsa_unlock(&oipi
->lsa
);
742 XFREE(MTYPE_OPAQUE_INFO_PER_ID
, oipi
);
746 static struct opaque_info_per_id
*
747 lookup_opaque_info_by_id(struct opaque_info_per_type
*oipt
,
748 struct ospf_lsa
*lsa
)
750 struct listnode
*node
, *nnode
;
751 struct opaque_info_per_id
*oipi
;
752 u_int32_t key
= GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
));
754 for (ALL_LIST_ELEMENTS(oipt
->id_list
, node
, nnode
, oipi
))
755 if (oipi
->opaque_id
== key
)
761 static struct opaque_info_per_id
*register_opaque_lsa(struct ospf_lsa
*new)
763 struct ospf_opaque_functab
*functab
;
764 struct opaque_info_per_type
*oipt
;
765 struct opaque_info_per_id
*oipi
= NULL
;
767 if ((functab
= ospf_opaque_functab_lookup(new)) == NULL
)
770 if ((oipt
= lookup_opaque_info_by_type(new)) == NULL
771 && (oipt
= register_opaque_info_per_type(functab
, new)) == NULL
)
774 if ((oipi
= register_opaque_info_per_id(oipt
, new)) == NULL
)
781 /*------------------------------------------------------------------------*
782 * Followings are (vty) configuration functions for Opaque-LSAs handling.
783 *------------------------------------------------------------------------*/
785 DEFUN (capability_opaque
,
786 capability_opaque_cmd
,
788 "Enable specific OSPF feature\n"
791 VTY_DECLVAR_INSTANCE_CONTEXT(ospf
, ospf
);
793 /* Turn on the "master switch" of opaque-lsa capability. */
794 if (!CHECK_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
)) {
795 if (IS_DEBUG_OSPF_EVENT
)
796 zlog_debug("Opaque capability: OFF -> ON");
798 SET_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
);
799 ospf_renegotiate_optional_capabilities(ospf
);
807 "OSPF specific commands\n"
808 "Enable the Opaque-LSA capability (rfc2370)\n")
810 return capability_opaque(self
, vty
, argc
, argv
);
813 DEFUN (no_capability_opaque
,
814 no_capability_opaque_cmd
,
815 "no capability opaque",
817 "Enable specific OSPF feature\n"
820 VTY_DECLVAR_INSTANCE_CONTEXT(ospf
, ospf
);
822 /* Turn off the "master switch" of opaque-lsa capability. */
823 if (CHECK_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
)) {
824 if (IS_DEBUG_OSPF_EVENT
)
825 zlog_debug("Opaque capability: ON -> OFF");
827 UNSET_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
);
828 ospf_renegotiate_optional_capabilities(ospf
);
833 DEFUN (no_ospf_opaque
,
835 "no ospf opaque-lsa",
837 "OSPF specific commands\n"
838 "Enable the Opaque-LSA capability (rfc2370)\n")
840 return no_capability_opaque(self
, vty
, argc
, argv
);
843 static void ospf_opaque_register_vty(void)
845 install_element(OSPF_NODE
, &capability_opaque_cmd
);
846 install_element(OSPF_NODE
, &no_capability_opaque_cmd
);
847 install_element(OSPF_NODE
, &ospf_opaque_cmd
);
848 install_element(OSPF_NODE
, &no_ospf_opaque_cmd
);
852 /*------------------------------------------------------------------------*
853 * Followings are collection of user-registered function callers.
854 *------------------------------------------------------------------------*/
856 static int opaque_lsa_new_if_callback(struct list
*funclist
,
857 struct interface
*ifp
)
859 struct listnode
*node
, *nnode
;
860 struct ospf_opaque_functab
*functab
;
863 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
864 if (functab
->new_if_hook
!= NULL
)
865 if ((*functab
->new_if_hook
)(ifp
) != 0)
872 static int opaque_lsa_del_if_callback(struct list
*funclist
,
873 struct interface
*ifp
)
875 struct listnode
*node
, *nnode
;
876 struct ospf_opaque_functab
*functab
;
879 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
880 if (functab
->del_if_hook
!= NULL
)
881 if ((*functab
->del_if_hook
)(ifp
) != 0)
888 static void opaque_lsa_ism_change_callback(struct list
*funclist
,
889 struct ospf_interface
*oi
,
892 struct listnode
*node
, *nnode
;
893 struct ospf_opaque_functab
*functab
;
895 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
896 if (functab
->ism_change_hook
!= NULL
)
897 (*functab
->ism_change_hook
)(oi
, old_status
);
902 static void opaque_lsa_nsm_change_callback(struct list
*funclist
,
903 struct ospf_neighbor
*nbr
,
906 struct listnode
*node
, *nnode
;
907 struct ospf_opaque_functab
*functab
;
909 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
910 if (functab
->nsm_change_hook
!= NULL
)
911 (*functab
->nsm_change_hook
)(nbr
, old_status
);
915 static void opaque_lsa_config_write_router_callback(struct list
*funclist
,
918 struct listnode
*node
, *nnode
;
919 struct ospf_opaque_functab
*functab
;
921 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
922 if (functab
->config_write_router
!= NULL
)
923 (*functab
->config_write_router
)(vty
);
927 static void opaque_lsa_config_write_if_callback(struct list
*funclist
,
929 struct interface
*ifp
)
931 struct listnode
*node
, *nnode
;
932 struct ospf_opaque_functab
*functab
;
934 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
935 if (functab
->config_write_if
!= NULL
)
936 (*functab
->config_write_if
)(vty
, ifp
);
940 static void opaque_lsa_config_write_debug_callback(struct list
*funclist
,
943 struct listnode
*node
, *nnode
;
944 struct ospf_opaque_functab
*functab
;
946 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
947 if (functab
->config_write_debug
!= NULL
)
948 (*functab
->config_write_debug
)(vty
);
952 static int opaque_lsa_originate_callback(struct list
*funclist
,
953 void *lsa_type_dependent
)
955 struct listnode
*node
, *nnode
;
956 struct ospf_opaque_functab
*functab
;
959 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
960 if (functab
->lsa_originator
!= NULL
)
961 if ((*functab
->lsa_originator
)(lsa_type_dependent
) != 0)
968 static int new_lsa_callback(struct list
*funclist
, struct ospf_lsa
*lsa
)
970 struct listnode
*node
, *nnode
;
971 struct ospf_opaque_functab
*functab
;
974 /* This function handles ALL types of LSAs, not only opaque ones. */
975 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
976 if (functab
->new_lsa_hook
!= NULL
)
977 if ((*functab
->new_lsa_hook
)(lsa
) != 0)
984 static int del_lsa_callback(struct list
*funclist
, struct ospf_lsa
*lsa
)
986 struct listnode
*node
, *nnode
;
987 struct ospf_opaque_functab
*functab
;
990 /* This function handles ALL types of LSAs, not only opaque ones. */
991 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
992 if (functab
->del_lsa_hook
!= NULL
)
993 if ((*functab
->del_lsa_hook
)(lsa
) != 0)
1000 /*------------------------------------------------------------------------*
1001 * Followings are glue functions to call Opaque-LSA specific processing.
1002 *------------------------------------------------------------------------*/
1004 int ospf_opaque_new_if(struct interface
*ifp
)
1006 struct list
*funclist
;
1009 funclist
= ospf_opaque_wildcard_funclist
;
1010 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
1013 funclist
= ospf_opaque_type9_funclist
;
1014 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
1017 funclist
= ospf_opaque_type10_funclist
;
1018 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
1021 funclist
= ospf_opaque_type11_funclist
;
1022 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
1030 int ospf_opaque_del_if(struct interface
*ifp
)
1032 struct list
*funclist
;
1035 funclist
= ospf_opaque_wildcard_funclist
;
1036 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1039 funclist
= ospf_opaque_type9_funclist
;
1040 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1043 funclist
= ospf_opaque_type10_funclist
;
1044 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1047 funclist
= ospf_opaque_type11_funclist
;
1048 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1056 void ospf_opaque_ism_change(struct ospf_interface
*oi
, int old_status
)
1058 struct list
*funclist
;
1060 funclist
= ospf_opaque_wildcard_funclist
;
1061 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1063 funclist
= ospf_opaque_type9_funclist
;
1064 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1066 funclist
= ospf_opaque_type10_funclist
;
1067 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1069 funclist
= ospf_opaque_type11_funclist
;
1070 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1075 void ospf_opaque_nsm_change(struct ospf_neighbor
*nbr
, int old_state
)
1078 struct list
*funclist
;
1080 if ((top
= oi_to_top(nbr
->oi
)) == NULL
)
1083 if (old_state
!= NSM_Full
&& nbr
->state
== NSM_Full
) {
1084 if (CHECK_FLAG(nbr
->options
, OSPF_OPTION_O
)) {
1085 if (!CHECK_FLAG(top
->opaque
,
1086 OPAQUE_OPERATION_READY_BIT
)) {
1087 if (IS_DEBUG_OSPF_EVENT
)
1089 "Opaque-LSA: Now get operational!");
1091 SET_FLAG(top
->opaque
,
1092 OPAQUE_OPERATION_READY_BIT
);
1095 ospf_opaque_lsa_originate_schedule(nbr
->oi
, NULL
);
1097 } else if (old_state
== NSM_Full
&& nbr
->state
!= NSM_Full
) {
1100 * If no more opaque-capable full-state neighbor remains in the
1101 * flooding scope which corresponds to Opaque-LSA type, periodic
1102 * LS flooding should be stopped.
1108 funclist
= ospf_opaque_wildcard_funclist
;
1109 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1111 funclist
= ospf_opaque_type9_funclist
;
1112 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1114 funclist
= ospf_opaque_type10_funclist
;
1115 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1117 funclist
= ospf_opaque_type11_funclist
;
1118 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1124 void ospf_opaque_config_write_router(struct vty
*vty
, struct ospf
*ospf
)
1126 struct list
*funclist
;
1128 if (CHECK_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
))
1129 vty_out(vty
, " capability opaque\n");
1131 funclist
= ospf_opaque_wildcard_funclist
;
1132 opaque_lsa_config_write_router_callback(funclist
, vty
);
1134 funclist
= ospf_opaque_type9_funclist
;
1135 opaque_lsa_config_write_router_callback(funclist
, vty
);
1137 funclist
= ospf_opaque_type10_funclist
;
1138 opaque_lsa_config_write_router_callback(funclist
, vty
);
1140 funclist
= ospf_opaque_type11_funclist
;
1141 opaque_lsa_config_write_router_callback(funclist
, vty
);
1146 void ospf_opaque_config_write_if(struct vty
*vty
, struct interface
*ifp
)
1148 struct list
*funclist
;
1150 funclist
= ospf_opaque_wildcard_funclist
;
1151 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1153 funclist
= ospf_opaque_type9_funclist
;
1154 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1156 funclist
= ospf_opaque_type10_funclist
;
1157 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1159 funclist
= ospf_opaque_type11_funclist
;
1160 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1165 void ospf_opaque_config_write_debug(struct vty
*vty
)
1167 struct list
*funclist
;
1169 funclist
= ospf_opaque_wildcard_funclist
;
1170 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1172 funclist
= ospf_opaque_type9_funclist
;
1173 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1175 funclist
= ospf_opaque_type10_funclist
;
1176 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1178 funclist
= ospf_opaque_type11_funclist
;
1179 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1184 void show_opaque_info_detail(struct vty
*vty
, struct ospf_lsa
*lsa
)
1186 struct lsa_header
*lsah
= (struct lsa_header
*)lsa
->data
;
1187 u_int32_t lsid
= ntohl(lsah
->id
.s_addr
);
1188 u_char opaque_type
= GET_OPAQUE_TYPE(lsid
);
1189 u_int32_t opaque_id
= GET_OPAQUE_ID(lsid
);
1190 struct ospf_opaque_functab
*functab
;
1192 /* Switch output functionality by vty address. */
1194 vty_out(vty
, " Opaque-Type %u (%s)\n", opaque_type
,
1195 ospf_opaque_type_name(opaque_type
));
1196 vty_out(vty
, " Opaque-ID 0x%x\n", opaque_id
);
1198 vty_out(vty
, " Opaque-Info: %u octets of data%s\n",
1199 ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
,
1200 VALID_OPAQUE_INFO_LEN(lsah
) ? "" : "(Invalid length?)");
1202 zlog_debug(" Opaque-Type %u (%s)", opaque_type
,
1203 ospf_opaque_type_name(opaque_type
));
1204 zlog_debug(" Opaque-ID 0x%x", opaque_id
);
1206 zlog_debug(" Opaque-Info: %u octets of data%s",
1207 ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
,
1208 VALID_OPAQUE_INFO_LEN(lsah
) ? ""
1209 : "(Invalid length?)");
1212 /* Call individual output functions. */
1213 if ((functab
= ospf_opaque_functab_lookup(lsa
)) != NULL
)
1214 if (functab
->show_opaque_info
!= NULL
)
1215 (*functab
->show_opaque_info
)(vty
, lsa
);
1220 void ospf_opaque_lsa_dump(struct stream
*s
, u_int16_t length
)
1222 struct ospf_lsa lsa
;
1224 lsa
.data
= (struct lsa_header
*)stream_pnt(s
);
1225 show_opaque_info_detail(NULL
, &lsa
);
1229 static int ospf_opaque_lsa_install_hook(struct ospf_lsa
*lsa
)
1231 struct list
*funclist
;
1235 * Some Opaque-LSA user may want to monitor every LSA installation
1236 * into the LSDB, regardless with target LSA type.
1238 funclist
= ospf_opaque_wildcard_funclist
;
1239 if (new_lsa_callback(funclist
, lsa
) != 0)
1242 funclist
= ospf_opaque_type9_funclist
;
1243 if (new_lsa_callback(funclist
, lsa
) != 0)
1246 funclist
= ospf_opaque_type10_funclist
;
1247 if (new_lsa_callback(funclist
, lsa
) != 0)
1250 funclist
= ospf_opaque_type11_funclist
;
1251 if (new_lsa_callback(funclist
, lsa
) != 0)
1259 static int ospf_opaque_lsa_delete_hook(struct ospf_lsa
*lsa
)
1261 struct list
*funclist
;
1265 * Some Opaque-LSA user may want to monitor every LSA deletion
1266 * from the LSDB, regardless with target LSA type.
1268 funclist
= ospf_opaque_wildcard_funclist
;
1269 if (del_lsa_callback(funclist
, lsa
) != 0)
1272 funclist
= ospf_opaque_type9_funclist
;
1273 if (del_lsa_callback(funclist
, lsa
) != 0)
1276 funclist
= ospf_opaque_type10_funclist
;
1277 if (del_lsa_callback(funclist
, lsa
) != 0)
1280 funclist
= ospf_opaque_type11_funclist
;
1281 if (del_lsa_callback(funclist
, lsa
) != 0)
1289 /*------------------------------------------------------------------------*
1290 * Followings are Opaque-LSA origination/refresh management functions.
1291 *------------------------------------------------------------------------*/
1293 static int ospf_opaque_type9_lsa_originate(struct thread
*t
);
1294 static int ospf_opaque_type10_lsa_originate(struct thread
*t
);
1295 static int ospf_opaque_type11_lsa_originate(struct thread
*t
);
1296 static void ospf_opaque_lsa_reoriginate_resume(struct list
*listtop
, void *arg
);
1298 void ospf_opaque_lsa_originate_schedule(struct ospf_interface
*oi
, int *delay0
)
1301 struct ospf_area
*area
;
1302 struct listnode
*node
, *nnode
;
1303 struct opaque_info_per_type
*oipt
;
1306 if ((top
= oi_to_top(oi
)) == NULL
|| (area
= oi
->area
) == NULL
) {
1308 "ospf_opaque_lsa_originate_schedule: Invalid argument?");
1312 /* It may not a right time to schedule origination now. */
1313 if (!CHECK_FLAG(top
->opaque
, OPAQUE_OPERATION_READY_BIT
)) {
1314 if (IS_DEBUG_OSPF_EVENT
)
1316 "ospf_opaque_lsa_originate_schedule: Not operational.");
1317 goto out
; /* This is not an error. */
1324 * There might be some entries that have been waiting for triggering
1325 * of per opaque-type re-origination get resumed.
1327 ospf_opaque_lsa_reoriginate_resume(oi
->opaque_lsa_self
, (void *)oi
);
1328 ospf_opaque_lsa_reoriginate_resume(area
->opaque_lsa_self
, (void *)area
);
1329 ospf_opaque_lsa_reoriginate_resume(top
->opaque_lsa_self
, (void *)top
);
1332 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1334 if (!list_isempty(ospf_opaque_type9_funclist
)
1335 && list_isempty(oi
->opaque_lsa_self
)
1336 && oi
->t_opaque_lsa_self
== NULL
) {
1337 if (IS_DEBUG_OSPF_EVENT
)
1339 "Schedule Type-9 Opaque-LSA origination in %d ms later.",
1341 oi
->t_opaque_lsa_self
= NULL
;
1342 thread_add_timer_msec(master
, ospf_opaque_type9_lsa_originate
,
1343 oi
, delay
, &oi
->t_opaque_lsa_self
);
1344 delay
+= top
->min_ls_interval
;
1347 if (!list_isempty(ospf_opaque_type10_funclist
)
1348 && list_isempty(area
->opaque_lsa_self
)
1349 && area
->t_opaque_lsa_self
== NULL
) {
1351 * One AREA may contain multiple OIs, but above 2nd and 3rd
1352 * conditions prevent from scheduling the originate function
1355 if (IS_DEBUG_OSPF_EVENT
)
1357 "Schedule Type-10 Opaque-LSA origination in %d ms later.",
1359 area
->t_opaque_lsa_self
= NULL
;
1360 thread_add_timer_msec(master
, ospf_opaque_type10_lsa_originate
,
1361 area
, delay
, &area
->t_opaque_lsa_self
);
1362 delay
+= top
->min_ls_interval
;
1365 if (!list_isempty(ospf_opaque_type11_funclist
)
1366 && list_isempty(top
->opaque_lsa_self
)
1367 && top
->t_opaque_lsa_self
== NULL
) {
1369 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1370 * conditions prevent from scheduling the originate function
1373 if (IS_DEBUG_OSPF_EVENT
)
1375 "Schedule Type-11 Opaque-LSA origination in %d ms later.",
1377 top
->t_opaque_lsa_self
= NULL
;
1378 thread_add_timer_msec(master
, ospf_opaque_type11_lsa_originate
,
1379 top
, delay
, &top
->t_opaque_lsa_self
);
1380 delay
+= top
->min_ls_interval
;
1384 * Following section treats a special situation that this node's
1385 * opaque capability has changed as "ON -> OFF -> ON".
1387 if (!list_isempty(ospf_opaque_type9_funclist
)
1388 && !list_isempty(oi
->opaque_lsa_self
)) {
1389 for (ALL_LIST_ELEMENTS(oi
->opaque_lsa_self
, node
, nnode
,
1392 * removed the test for
1393 * (! list_isempty (oipt->id_list)) * Handler is
1395 * because opaque cababilities ON -> OFF -> ON result in
1396 * list_isempty (oipt->id_list)
1400 oipt
->t_opaque_lsa_self
1401 != NULL
/* Waiting for a thread call. */
1402 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1407 ospf_opaque_lsa_reoriginate_schedule(
1408 (void *)oi
, OSPF_OPAQUE_LINK_LSA
,
1413 if (!list_isempty(ospf_opaque_type10_funclist
)
1414 && !list_isempty(area
->opaque_lsa_self
)) {
1415 for (ALL_LIST_ELEMENTS(area
->opaque_lsa_self
, node
, nnode
,
1418 * removed the test for
1419 * (! list_isempty (oipt->id_list)) * Handler is
1421 * because opaque cababilities ON -> OFF -> ON result in
1422 * list_isempty (oipt->id_list)
1426 oipt
->t_opaque_lsa_self
1427 != NULL
/* Waiting for a thread call. */
1428 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1433 ospf_opaque_lsa_reoriginate_schedule(
1434 (void *)area
, OSPF_OPAQUE_AREA_LSA
,
1439 if (!list_isempty(ospf_opaque_type11_funclist
)
1440 && !list_isempty(top
->opaque_lsa_self
)) {
1441 for (ALL_LIST_ELEMENTS(top
->opaque_lsa_self
, node
, nnode
,
1444 * removed the test for
1445 * (! list_isempty (oipt->id_list)) * Handler is
1447 * because opaque cababilities ON -> OFF -> ON result in
1448 * list_isempty (oipt->id_list)
1452 oipt
->t_opaque_lsa_self
1453 != NULL
/* Waiting for a thread call. */
1454 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1459 ospf_opaque_lsa_reoriginate_schedule((void *)top
,
1472 static int ospf_opaque_type9_lsa_originate(struct thread
*t
)
1474 struct ospf_interface
*oi
;
1478 oi
->t_opaque_lsa_self
= NULL
;
1480 if (IS_DEBUG_OSPF_EVENT
)
1481 zlog_debug("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
1484 rc
= opaque_lsa_originate_callback(ospf_opaque_type9_funclist
, oi
);
1489 static int ospf_opaque_type10_lsa_originate(struct thread
*t
)
1491 struct ospf_area
*area
;
1494 area
= THREAD_ARG(t
);
1495 area
->t_opaque_lsa_self
= NULL
;
1497 if (IS_DEBUG_OSPF_EVENT
)
1499 "Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
1500 inet_ntoa(area
->area_id
));
1502 rc
= opaque_lsa_originate_callback(ospf_opaque_type10_funclist
, area
);
1507 static int ospf_opaque_type11_lsa_originate(struct thread
*t
)
1512 top
= THREAD_ARG(t
);
1513 top
->t_opaque_lsa_self
= NULL
;
1515 if (IS_DEBUG_OSPF_EVENT
)
1517 "Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
1519 rc
= opaque_lsa_originate_callback(ospf_opaque_type11_funclist
, top
);
1524 static void ospf_opaque_lsa_reoriginate_resume(struct list
*listtop
, void *arg
)
1526 struct listnode
*node
, *nnode
;
1527 struct opaque_info_per_type
*oipt
;
1528 struct ospf_opaque_functab
*functab
;
1530 if (listtop
== NULL
)
1534 * Pickup oipt entries those which in SUSPEND status, and give
1535 * them a chance to start re-origination now.
1537 for (ALL_LIST_ELEMENTS(listtop
, node
, nnode
, oipt
)) {
1538 if (oipt
->status
!= PROC_SUSPEND
)
1541 oipt
->status
= PROC_NORMAL
;
1543 if ((functab
= oipt
->functab
) == NULL
1544 || functab
->lsa_originator
== NULL
)
1547 if ((*functab
->lsa_originator
)(arg
) != 0) {
1549 "ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)",
1559 struct ospf_lsa
*ospf_opaque_lsa_install(struct ospf_lsa
*lsa
, int rt_recalc
)
1561 struct ospf_lsa
*new = NULL
;
1562 struct opaque_info_per_type
*oipt
;
1563 struct opaque_info_per_id
*oipi
;
1566 /* Don't take "rt_recalc" into consideration for now. */ /* XXX */
1568 if (!IS_LSA_SELF(lsa
)) {
1569 new = lsa
; /* Don't touch this LSA. */
1573 if (IS_DEBUG_OSPF(lsa
, LSA_INSTALL
))
1575 "Install Type-%u Opaque-LSA: [opaque-type=%u, opaque-id=%x]",
1577 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
1578 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
1580 /* Replace the existing lsa with the new one. */
1581 if ((oipt
= lookup_opaque_info_by_type(lsa
)) != NULL
1582 && (oipi
= lookup_opaque_info_by_id(oipt
, lsa
)) != NULL
) {
1583 ospf_lsa_unlock(&oipi
->lsa
);
1584 oipi
->lsa
= ospf_lsa_lock(lsa
);
1586 /* Register the new lsa entry and get its control info. */
1587 else if ((oipi
= register_opaque_lsa(lsa
)) == NULL
) {
1588 zlog_warn("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1593 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1594 * for periodic refresh of self-originated Opaque-LSAs.
1596 switch (lsa
->data
->type
) {
1597 case OSPF_OPAQUE_LINK_LSA
:
1598 if ((top
= oi_to_top(lsa
->oi
)) == NULL
) {
1599 /* Above conditions must have passed. */
1600 zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?");
1604 case OSPF_OPAQUE_AREA_LSA
:
1605 if (lsa
->area
== NULL
|| (top
= lsa
->area
->ospf
) == NULL
) {
1606 /* Above conditions must have passed. */
1607 zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?");
1611 case OSPF_OPAQUE_AS_LSA
:
1612 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
1613 if (lsa
->area
!= NULL
&& (top
= lsa
->area
->ospf
) == NULL
) {
1614 /* Above conditions must have passed. */
1615 zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?");
1620 zlog_warn("ospf_opaque_lsa_install: Unexpected LSA-type(%u)",
1625 ospf_refresher_register_lsa(top
, lsa
);
1632 struct ospf_lsa
*ospf_opaque_lsa_refresh(struct ospf_lsa
*lsa
)
1635 struct ospf_opaque_functab
*functab
;
1636 struct ospf_lsa
*new = NULL
;
1638 ospf
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
1640 if ((functab
= ospf_opaque_functab_lookup(lsa
)) == NULL
1641 || functab
->lsa_refresher
== NULL
) {
1643 * Though this LSA seems to have originated on this node, the
1644 * handling module for this "lsa-type and opaque-type" was
1645 * already deleted sometime ago.
1646 * Anyway, this node still has a responsibility to flush this
1647 * LSA from the routing domain.
1649 if (IS_DEBUG_OSPF_EVENT
)
1650 zlog_debug("LSA[Type%d:%s]: Flush stray Opaque-LSA",
1651 lsa
->data
->type
, inet_ntoa(lsa
->data
->id
));
1653 lsa
->data
->ls_age
= htons(OSPF_LSA_MAXAGE
);
1654 ospf_lsa_flush(ospf
, lsa
);
1656 new = (*functab
->lsa_refresher
)(lsa
);
1661 /*------------------------------------------------------------------------*
1662 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1663 * triggered by external interventions (vty session, signaling, etc).
1664 *------------------------------------------------------------------------*/
1666 #define OSPF_OPAQUE_TIMER_ON(T,F,L,V) thread_add_timer_msec (master, (F), (L), (V), &(T))
1668 static struct ospf_lsa
*pseudo_lsa(struct ospf_interface
*oi
,
1669 struct ospf_area
*area
, u_char lsa_type
,
1670 u_char opaque_type
);
1671 static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread
*t
);
1672 static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread
*t
);
1673 static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread
*t
);
1674 static int ospf_opaque_lsa_refresh_timer(struct thread
*t
);
1676 void ospf_opaque_lsa_reoriginate_schedule(void *lsa_type_dependent
,
1677 u_char lsa_type
, u_char opaque_type
)
1679 struct ospf
*top
= NULL
;
1680 struct ospf_area dummy
, *area
= NULL
;
1681 struct ospf_interface
*oi
= NULL
;
1683 struct ospf_lsa
*lsa
;
1684 struct opaque_info_per_type
*oipt
;
1685 int (*func
)(struct thread
* t
) = NULL
;
1689 case OSPF_OPAQUE_LINK_LSA
:
1690 if ((oi
= (struct ospf_interface
*)lsa_type_dependent
)
1693 "ospf_opaque_lsa_reoriginate_schedule:"
1694 " Type-9 Opaque-LSA: Invalid parameter?");
1697 if ((top
= oi_to_top(oi
)) == NULL
) {
1699 "ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1703 if (!list_isempty(ospf_opaque_type9_funclist
)
1704 && list_isempty(oi
->opaque_lsa_self
)
1705 && oi
->t_opaque_lsa_self
!= NULL
) {
1707 "Type-9 Opaque-LSA (opaque_type=%u):"
1708 " Common origination for OI(%s) has already started",
1709 opaque_type
, IF_NAME(oi
));
1712 func
= ospf_opaque_type9_lsa_reoriginate_timer
;
1714 case OSPF_OPAQUE_AREA_LSA
:
1715 if ((area
= (struct ospf_area
*)lsa_type_dependent
) == NULL
) {
1717 "ospf_opaque_lsa_reoriginate_schedule:"
1718 " Type-10 Opaque-LSA: Invalid parameter?");
1721 if ((top
= area
->ospf
) == NULL
) {
1723 "ospf_opaque_lsa_reoriginate_schedule:"
1724 " AREA(%s) -> TOP?",
1725 inet_ntoa(area
->area_id
));
1728 if (!list_isempty(ospf_opaque_type10_funclist
)
1729 && list_isempty(area
->opaque_lsa_self
)
1730 && area
->t_opaque_lsa_self
!= NULL
) {
1732 "Type-10 Opaque-LSA (opaque_type=%u):"
1733 " Common origination for AREA(%s) has already started",
1734 opaque_type
, inet_ntoa(area
->area_id
));
1737 func
= ospf_opaque_type10_lsa_reoriginate_timer
;
1739 case OSPF_OPAQUE_AS_LSA
:
1740 if ((top
= (struct ospf
*)lsa_type_dependent
) == NULL
) {
1742 "ospf_opaque_lsa_reoriginate_schedule:"
1743 " Type-11 Opaque-LSA: Invalid parameter?");
1746 if (!list_isempty(ospf_opaque_type11_funclist
)
1747 && list_isempty(top
->opaque_lsa_self
)
1748 && top
->t_opaque_lsa_self
!= NULL
) {
1750 "Type-11 Opaque-LSA (opaque_type=%u):"
1751 " Common origination has already started",
1756 /* Fake "area" to pass "ospf" to a lookup function later. */
1760 func
= ospf_opaque_type11_lsa_reoriginate_timer
;
1764 "ospf_opaque_lsa_reoriginate_schedule:"
1765 " Unexpected LSA-type(%u)",
1770 /* It may not a right time to schedule reorigination now. */
1771 if (!CHECK_FLAG(top
->opaque
, OPAQUE_OPERATION_READY_BIT
)) {
1772 if (IS_DEBUG_OSPF_EVENT
)
1774 "ospf_opaque_lsa_reoriginate_schedule: Not operational.");
1775 goto out
; /* This is not an error. */
1778 /* Generate a dummy lsa to be passed for a lookup function. */
1779 lsa
= pseudo_lsa(oi
, area
, lsa_type
, opaque_type
);
1780 lsa
->vrf_id
= top
->vrf_id
;
1782 if ((oipt
= lookup_opaque_info_by_type(lsa
)) == NULL
) {
1783 struct ospf_opaque_functab
*functab
;
1784 if ((functab
= ospf_opaque_functab_lookup(lsa
)) == NULL
) {
1786 "ospf_opaque_lsa_reoriginate_schedule:"
1787 " No associated function?: lsa_type(%u),"
1789 lsa_type
, opaque_type
);
1792 if ((oipt
= register_opaque_info_per_type(functab
, lsa
))
1795 "ospf_opaque_lsa_reoriginate_schedule:"
1796 " Cannot get a control info?: lsa_type(%u),"
1798 lsa_type
, opaque_type
);
1803 if (oipt
->t_opaque_lsa_self
!= NULL
) {
1804 if (IS_DEBUG_OSPF_EVENT
)
1806 "Type-%u Opaque-LSA has already scheduled to"
1807 " RE-ORIGINATE: [opaque-type=%u]",
1809 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)));
1814 * Different from initial origination time, in which various conditions
1815 * (opaque capability, neighbor status etc) are assured by caller of
1816 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1817 * it is highly possible that these conditions might not be satisfied
1818 * at the time of re-origination function is to be called.
1820 delay
= top
->min_ls_interval
; /* XXX */
1822 if (IS_DEBUG_OSPF_EVENT
)
1824 "Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
1825 " ms later: [opaque-type=%u]",
1827 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)));
1829 OSPF_OPAQUE_TIMER_ON(oipt
->t_opaque_lsa_self
, func
, oipt
, delay
);
1835 static struct ospf_lsa
*pseudo_lsa(struct ospf_interface
*oi
,
1836 struct ospf_area
*area
, u_char lsa_type
,
1839 static struct ospf_lsa lsa
= {0};
1840 static struct lsa_header lsah
= {0};
1846 lsa
.vrf_id
= VRF_DEFAULT
;
1848 lsah
.type
= lsa_type
;
1849 tmp
= SET_OPAQUE_LSID(opaque_type
, 0); /* Opaque-ID is unused here. */
1850 lsah
.id
.s_addr
= htonl(tmp
);
1855 static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread
*t
)
1857 struct opaque_info_per_type
*oipt
;
1858 struct ospf_opaque_functab
*functab
;
1860 struct ospf_interface
*oi
;
1863 oipt
= THREAD_ARG(t
);
1864 oipt
->t_opaque_lsa_self
= NULL
;
1866 if ((functab
= oipt
->functab
) == NULL
1867 || functab
->lsa_originator
== NULL
) {
1869 "ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1873 oi
= (struct ospf_interface
*)oipt
->owner
;
1874 if ((top
= oi_to_top(oi
)) == NULL
) {
1876 "ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1880 if (!CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)
1881 || !ospf_if_is_enable(oi
)
1882 || ospf_nbr_count_opaque_capable(oi
) == 0) {
1883 if (IS_DEBUG_OSPF_EVENT
)
1885 "Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...",
1888 oipt
->status
= PROC_SUSPEND
;
1893 if (IS_DEBUG_OSPF_EVENT
)
1895 "Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)",
1896 oipt
->opaque_type
, IF_NAME(oi
));
1898 rc
= (*functab
->lsa_originator
)(oi
);
1903 static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread
*t
)
1905 struct opaque_info_per_type
*oipt
;
1906 struct ospf_opaque_functab
*functab
;
1907 struct listnode
*node
, *nnode
;
1909 struct ospf_area
*area
;
1910 struct ospf_interface
*oi
;
1913 oipt
= THREAD_ARG(t
);
1914 oipt
->t_opaque_lsa_self
= NULL
;
1916 if ((functab
= oipt
->functab
) == NULL
1917 || functab
->lsa_originator
== NULL
) {
1919 "ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1923 area
= (struct ospf_area
*)oipt
->owner
;
1924 if (area
== NULL
|| (top
= area
->ospf
) == NULL
) {
1926 "ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1930 /* There must be at least one "opaque-capable, full-state" neighbor. */
1932 for (ALL_LIST_ELEMENTS(area
->oiflist
, node
, nnode
, oi
)) {
1933 if ((n
= ospf_nbr_count_opaque_capable(oi
)) > 0)
1937 if (n
== 0 || !CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)) {
1938 if (IS_DEBUG_OSPF_EVENT
)
1940 "Suspend re-origination of Type-10 Opaque-LSAs"
1941 " (opaque-type=%u) for a while...",
1944 oipt
->status
= PROC_SUSPEND
;
1949 if (IS_DEBUG_OSPF_EVENT
)
1951 "Timer[Type10-LSA]: Re-originate Opaque-LSAs"
1952 " (opaque-type=%u) for Area %s",
1953 oipt
->opaque_type
, inet_ntoa(area
->area_id
));
1955 rc
= (*functab
->lsa_originator
)(area
);
1960 static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread
*t
)
1962 struct opaque_info_per_type
*oipt
;
1963 struct ospf_opaque_functab
*functab
;
1967 oipt
= THREAD_ARG(t
);
1968 oipt
->t_opaque_lsa_self
= NULL
;
1970 if ((functab
= oipt
->functab
) == NULL
1971 || functab
->lsa_originator
== NULL
) {
1973 "ospf_opaque_type11_lsa_reoriginate_timer:"
1974 " No associated function?");
1978 if ((top
= (struct ospf
*)oipt
->owner
) == NULL
) {
1980 "ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1984 if (!CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)) {
1985 if (IS_DEBUG_OSPF_EVENT
)
1987 "Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...",
1990 oipt
->status
= PROC_SUSPEND
;
1995 if (IS_DEBUG_OSPF_EVENT
)
1997 "Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).",
2000 rc
= (*functab
->lsa_originator
)(top
);
2005 void ospf_opaque_lsa_refresh_schedule(struct ospf_lsa
*lsa0
)
2007 struct opaque_info_per_type
*oipt
;
2008 struct opaque_info_per_id
*oipi
;
2009 struct ospf_lsa
*lsa
;
2013 if ((oipt
= lookup_opaque_info_by_type(lsa0
)) == NULL
2014 || (oipi
= lookup_opaque_info_by_id(oipt
, lsa0
)) == NULL
) {
2016 "ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
2020 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2021 if ((lsa
= oipi
->lsa
) == NULL
) {
2022 zlog_warn("ospf_opaque_lsa_refresh_schedule: Something wrong?");
2026 if (oipi
->t_opaque_lsa_self
!= NULL
) {
2027 if (IS_DEBUG_OSPF_EVENT
)
2029 "Type-%u Opaque-LSA has already scheduled to REFRESH: [opaque-type=%u, opaque-id=%x]",
2031 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
2032 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
2036 /* Delete this lsa from neighbor retransmit-list. */
2037 switch (lsa
->data
->type
) {
2038 case OSPF_OPAQUE_LINK_LSA
:
2039 case OSPF_OPAQUE_AREA_LSA
:
2040 ospf_ls_retransmit_delete_nbr_area(lsa
->area
, lsa
);
2042 case OSPF_OPAQUE_AS_LSA
:
2043 top
= ospf_lookup_by_vrf_id(lsa0
->vrf_id
);
2044 if ((lsa0
->area
!= NULL
) && (lsa0
->area
->ospf
!= NULL
))
2045 top
= lsa0
->area
->ospf
;
2046 ospf_ls_retransmit_delete_nbr_as(top
, lsa
);
2050 "ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)",
2055 delay
= ospf_lsa_refresh_delay(lsa
);
2057 if (IS_DEBUG_OSPF_EVENT
)
2059 "Schedule Type-%u Opaque-LSA to REFRESH in %d sec later: [opaque-type=%u, opaque-id=%x]",
2060 lsa
->data
->type
, delay
,
2061 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
2062 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
2064 OSPF_OPAQUE_TIMER_ON(oipi
->t_opaque_lsa_self
,
2065 ospf_opaque_lsa_refresh_timer
, oipi
, delay
* 1000);
2070 static int ospf_opaque_lsa_refresh_timer(struct thread
*t
)
2072 struct opaque_info_per_id
*oipi
;
2073 struct ospf_opaque_functab
*functab
;
2074 struct ospf_lsa
*lsa
;
2076 if (IS_DEBUG_OSPF_EVENT
)
2077 zlog_debug("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
2079 oipi
= THREAD_ARG(t
);
2080 oipi
->t_opaque_lsa_self
= NULL
;
2082 if ((lsa
= oipi
->lsa
) != NULL
)
2083 if ((functab
= oipi
->opqctl_type
->functab
) != NULL
)
2084 if (functab
->lsa_refresher
!= NULL
)
2085 (*functab
->lsa_refresher
)(lsa
);
2090 void ospf_opaque_lsa_flush_schedule(struct ospf_lsa
*lsa0
)
2092 struct opaque_info_per_type
*oipt
;
2093 struct opaque_info_per_id
*oipi
;
2094 struct ospf_lsa
*lsa
;
2097 top
= ospf_lookup_by_vrf_id(lsa0
->vrf_id
);
2099 if ((oipt
= lookup_opaque_info_by_type(lsa0
)) == NULL
2100 || (oipi
= lookup_opaque_info_by_id(oipt
, lsa0
)) == NULL
) {
2101 zlog_warn("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2105 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2106 if ((lsa
= oipi
->lsa
) == NULL
) {
2107 zlog_warn("ospf_opaque_lsa_flush_schedule: Something wrong?");
2111 /* Delete this lsa from neighbor retransmit-list. */
2112 switch (lsa
->data
->type
) {
2113 case OSPF_OPAQUE_LINK_LSA
:
2114 case OSPF_OPAQUE_AREA_LSA
:
2115 ospf_ls_retransmit_delete_nbr_area(lsa
->area
, lsa
);
2117 case OSPF_OPAQUE_AS_LSA
:
2118 if ((lsa0
->area
!= NULL
) && (lsa0
->area
->ospf
!= NULL
))
2119 top
= lsa0
->area
->ospf
;
2120 ospf_ls_retransmit_delete_nbr_as(top
, lsa
);
2124 "ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)",
2129 /* Dequeue listnode entry from the list. */
2130 listnode_delete(oipt
->id_list
, oipi
);
2132 /* Avoid misjudgement in the next lookup. */
2133 if (listcount(oipt
->id_list
) == 0)
2134 oipt
->id_list
->head
= oipt
->id_list
->tail
= NULL
;
2136 /* Disassociate internal control information with the given lsa. */
2137 free_opaque_info_per_id((void *)oipi
);
2139 /* Force given lsa's age to MaxAge. */
2140 lsa
->data
->ls_age
= htons(OSPF_LSA_MAXAGE
);
2142 if (IS_DEBUG_OSPF_EVENT
)
2144 "Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]",
2146 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
2147 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
2149 /* This lsa will be flushed and removed eventually. */
2150 ospf_lsa_flush(top
, lsa
);
2156 void ospf_opaque_self_originated_lsa_received(struct ospf_neighbor
*nbr
,
2157 struct ospf_lsa
*lsa
)
2161 if ((top
= oi_to_top(nbr
->oi
)) == NULL
)
2165 * Since these LSA entries are not yet installed into corresponding
2166 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2168 lsa
->data
->ls_age
= htons(OSPF_LSA_MAXAGE
);
2169 switch (lsa
->data
->type
) {
2170 case OSPF_OPAQUE_LINK_LSA
:
2171 ospf_flood_through_area(nbr
->oi
->area
, NULL
/*inbr*/, lsa
);
2173 case OSPF_OPAQUE_AREA_LSA
:
2174 ospf_flood_through_area(nbr
->oi
->area
, NULL
/*inbr*/, lsa
);
2176 case OSPF_OPAQUE_AS_LSA
:
2177 ospf_flood_through_as(top
, NULL
/*inbr*/, lsa
);
2181 "ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)",
2185 ospf_lsa_discard(lsa
); /* List "lsas" will be deleted by caller. */
2188 /*------------------------------------------------------------------------*
2189 * Followings are util functions; probably be used by Opaque-LSAs only...
2190 *------------------------------------------------------------------------*/
2192 struct ospf
*oi_to_top(struct ospf_interface
*oi
)
2194 struct ospf
*top
= NULL
;
2195 struct ospf_area
*area
;
2197 if (oi
== NULL
|| (area
= oi
->area
) == NULL
2198 || (top
= area
->ospf
) == NULL
)
2199 zlog_warn("Broken relationship for \"OI -> AREA -> OSPF\"?");