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"
57 #include "ospfd/ospf_errors.h"
59 DEFINE_MTYPE_STATIC(OSPFD
, OSPF_OPAQUE_FUNCTAB
, "OSPF opaque function table")
60 DEFINE_MTYPE_STATIC(OSPFD
, OPAQUE_INFO_PER_TYPE
, "OSPF opaque per-type info")
61 DEFINE_MTYPE_STATIC(OSPFD
, OPAQUE_INFO_PER_ID
, "OSPF opaque per-ID info")
63 /*------------------------------------------------------------------------*
64 * Followings are initialize/terminate functions for Opaque-LSAs handling.
65 *------------------------------------------------------------------------*/
67 #ifdef SUPPORT_OSPF_API
68 int ospf_apiserver_init(void);
69 void ospf_apiserver_term(void);
70 /* Init apiserver? It's disabled by default. */
71 int ospf_apiserver_enable
;
72 #endif /* SUPPORT_OSPF_API */
74 static void ospf_opaque_register_vty(void);
75 static void ospf_opaque_funclist_init(void);
76 static void ospf_opaque_funclist_term(void);
77 static void free_opaque_info_per_type(void *val
);
78 static void free_opaque_info_per_id(void *val
);
79 static void free_opaque_info_owner(void *val
);
80 static int ospf_opaque_lsa_install_hook(struct ospf_lsa
*lsa
);
81 static int ospf_opaque_lsa_delete_hook(struct ospf_lsa
*lsa
);
83 void ospf_opaque_init(void)
85 ospf_opaque_register_vty();
86 ospf_opaque_funclist_init();
88 if (ospf_mpls_te_init() != 0)
91 /* Segment Routing init */
92 if (ospf_sr_init() != 0)
95 if (ospf_router_info_init() != 0)
98 if (ospf_ext_init() != 0)
101 #ifdef SUPPORT_OSPF_API
102 if ((ospf_apiserver_enable
) && (ospf_apiserver_init() != 0))
104 #endif /* SUPPORT_OSPF_API */
109 void ospf_opaque_term(void)
113 ospf_router_info_term();
119 #ifdef SUPPORT_OSPF_API
120 ospf_apiserver_term();
121 #endif /* SUPPORT_OSPF_API */
123 ospf_opaque_funclist_term();
127 void ospf_opaque_finish(void)
129 ospf_router_info_finish();
136 int ospf_opaque_type9_lsa_init(struct ospf_interface
*oi
)
138 if (oi
->opaque_lsa_self
!= NULL
)
139 list_delete_and_null(&oi
->opaque_lsa_self
);
141 oi
->opaque_lsa_self
= list_new();
142 oi
->opaque_lsa_self
->del
= free_opaque_info_per_type
;
143 oi
->t_opaque_lsa_self
= NULL
;
147 void ospf_opaque_type9_lsa_term(struct ospf_interface
*oi
)
149 OSPF_TIMER_OFF(oi
->t_opaque_lsa_self
);
150 if (oi
->opaque_lsa_self
!= NULL
)
151 list_delete_and_null(&oi
->opaque_lsa_self
);
152 oi
->opaque_lsa_self
= NULL
;
156 int ospf_opaque_type10_lsa_init(struct ospf_area
*area
)
158 if (area
->opaque_lsa_self
!= NULL
)
159 list_delete_and_null(&area
->opaque_lsa_self
);
161 area
->opaque_lsa_self
= list_new();
162 area
->opaque_lsa_self
->del
= free_opaque_info_per_type
;
163 area
->t_opaque_lsa_self
= NULL
;
165 #ifdef MONITOR_LSDB_CHANGE
166 area
->lsdb
->new_lsa_hook
= ospf_opaque_lsa_install_hook
;
167 area
->lsdb
->del_lsa_hook
= ospf_opaque_lsa_delete_hook
;
168 #endif /* MONITOR_LSDB_CHANGE */
172 void ospf_opaque_type10_lsa_term(struct ospf_area
*area
)
174 #ifdef MONITOR_LSDB_CHANGE
175 area
->lsdb
->new_lsa_hook
= area
->lsdb
->del_lsa_hook
= NULL
;
176 #endif /* MONITOR_LSDB_CHANGE */
178 OSPF_TIMER_OFF(area
->t_opaque_lsa_self
);
179 if (area
->opaque_lsa_self
!= NULL
)
180 list_delete_and_null(&area
->opaque_lsa_self
);
184 int ospf_opaque_type11_lsa_init(struct ospf
*top
)
186 if (top
->opaque_lsa_self
!= NULL
)
187 list_delete_and_null(&top
->opaque_lsa_self
);
189 top
->opaque_lsa_self
= list_new();
190 top
->opaque_lsa_self
->del
= free_opaque_info_per_type
;
191 top
->t_opaque_lsa_self
= NULL
;
193 #ifdef MONITOR_LSDB_CHANGE
194 top
->lsdb
->new_lsa_hook
= ospf_opaque_lsa_install_hook
;
195 top
->lsdb
->del_lsa_hook
= ospf_opaque_lsa_delete_hook
;
196 #endif /* MONITOR_LSDB_CHANGE */
200 void ospf_opaque_type11_lsa_term(struct ospf
*top
)
202 #ifdef MONITOR_LSDB_CHANGE
203 top
->lsdb
->new_lsa_hook
= top
->lsdb
->del_lsa_hook
= NULL
;
204 #endif /* MONITOR_LSDB_CHANGE */
206 OSPF_TIMER_OFF(top
->t_opaque_lsa_self
);
207 if (top
->opaque_lsa_self
!= NULL
)
208 list_delete_and_null(&top
->opaque_lsa_self
);
212 static const char *ospf_opaque_type_name(uint8_t opaque_type
)
214 const char *name
= "Unknown";
216 switch (opaque_type
) {
217 case OPAQUE_TYPE_WILDCARD
: /* This is a special assignment! */
220 case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA
:
221 name
= "Traffic Engineering LSA";
223 case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC
:
224 name
= "Sycamore optical topology description";
226 case OPAQUE_TYPE_GRACE_LSA
:
229 case OPAQUE_TYPE_INTER_AS_LSA
:
230 name
= "Inter-AS TE-v2 LSA";
232 case OPAQUE_TYPE_ROUTER_INFORMATION_LSA
:
233 name
= "Router Information LSA";
235 case OPAQUE_TYPE_EXTENDED_PREFIX_LSA
:
236 name
= "Extended Prefix Opaque LSA";
238 case OPAQUE_TYPE_EXTENDED_LINK_LSA
:
239 name
= "Extended Link Opaque LSA";
242 if (OPAQUE_TYPE_RANGE_UNASSIGNED(opaque_type
))
245 uint32_t bigger_range
= opaque_type
;
247 * Get around type-limits warning: comparison is always
248 * true due to limited range of data type
250 if (OPAQUE_TYPE_RANGE_RESERVED(bigger_range
))
251 name
= "Private/Experimental";
258 /*------------------------------------------------------------------------*
259 * Followings are management functions to store user specified callbacks.
260 *------------------------------------------------------------------------*/
262 struct opaque_info_per_type
; /* Forward declaration. */
264 struct ospf_opaque_functab
{
266 struct opaque_info_per_type
*oipt
;
268 int (*new_if_hook
)(struct interface
*ifp
);
269 int (*del_if_hook
)(struct interface
*ifp
);
270 void (*ism_change_hook
)(struct ospf_interface
*oi
, int old_status
);
271 void (*nsm_change_hook
)(struct ospf_neighbor
*nbr
, int old_status
);
272 void (*config_write_router
)(struct vty
*vty
);
273 void (*config_write_if
)(struct vty
*vty
, struct interface
*ifp
);
274 void (*config_write_debug
)(struct vty
*vty
);
275 void (*show_opaque_info
)(struct vty
*vty
, struct ospf_lsa
*lsa
);
276 int (*lsa_originator
)(void *arg
);
277 struct ospf_lsa
*(*lsa_refresher
)(struct ospf_lsa
*lsa
);
278 int (*new_lsa_hook
)(struct ospf_lsa
*lsa
);
279 int (*del_lsa_hook
)(struct ospf_lsa
*lsa
);
282 /* Handle LSA-9/10/11 altogether. */
283 static struct list
*ospf_opaque_wildcard_funclist
;
284 static struct list
*ospf_opaque_type9_funclist
;
285 static struct list
*ospf_opaque_type10_funclist
;
286 static struct list
*ospf_opaque_type11_funclist
;
288 static void ospf_opaque_del_functab(void *val
)
290 XFREE(MTYPE_OSPF_OPAQUE_FUNCTAB
, val
);
294 static void ospf_opaque_funclist_init(void)
296 struct list
*funclist
;
298 funclist
= ospf_opaque_wildcard_funclist
= list_new();
299 funclist
->del
= ospf_opaque_del_functab
;
301 funclist
= ospf_opaque_type9_funclist
= list_new();
302 funclist
->del
= ospf_opaque_del_functab
;
304 funclist
= ospf_opaque_type10_funclist
= list_new();
305 funclist
->del
= ospf_opaque_del_functab
;
307 funclist
= ospf_opaque_type11_funclist
= list_new();
308 funclist
->del
= ospf_opaque_del_functab
;
312 static void ospf_opaque_funclist_term(void)
314 struct list
*funclist
;
316 funclist
= ospf_opaque_wildcard_funclist
;
317 list_delete_and_null(&funclist
);
319 funclist
= ospf_opaque_type9_funclist
;
320 list_delete_and_null(&funclist
);
322 funclist
= ospf_opaque_type10_funclist
;
323 list_delete_and_null(&funclist
);
325 funclist
= ospf_opaque_type11_funclist
;
326 list_delete_and_null(&funclist
);
330 static struct list
*ospf_get_opaque_funclist(uint8_t lsa_type
)
332 struct list
*funclist
= NULL
;
335 case OPAQUE_TYPE_WILDCARD
:
337 * This is an ugly trick to handle type-9/10/11 LSA altogether.
338 * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor
339 * an officially assigned opaque-type.
340 * Though it is possible that the value might be officially used
341 * in the future, we use it internally as a special label, for
344 funclist
= ospf_opaque_wildcard_funclist
;
346 case OSPF_OPAQUE_LINK_LSA
:
347 funclist
= ospf_opaque_type9_funclist
;
349 case OSPF_OPAQUE_AREA_LSA
:
350 funclist
= ospf_opaque_type10_funclist
;
352 case OSPF_OPAQUE_AS_LSA
:
353 funclist
= ospf_opaque_type11_funclist
;
356 flog_warn(OSPF_WARN_LSA_UNEXPECTED
,
357 "ospf_get_opaque_funclist: Unexpected LSA-type(%u)",
364 /* XXX: such a huge argument list can /not/ be healthy... */
365 int ospf_register_opaque_functab(
366 uint8_t lsa_type
, uint8_t opaque_type
,
367 int (*new_if_hook
)(struct interface
*ifp
),
368 int (*del_if_hook
)(struct interface
*ifp
),
369 void (*ism_change_hook
)(struct ospf_interface
*oi
, int old_status
),
370 void (*nsm_change_hook
)(struct ospf_neighbor
*nbr
, int old_status
),
371 void (*config_write_router
)(struct vty
*vty
),
372 void (*config_write_if
)(struct vty
*vty
, struct interface
*ifp
),
373 void (*config_write_debug
)(struct vty
*vty
),
374 void (*show_opaque_info
)(struct vty
*vty
, struct ospf_lsa
*lsa
),
375 int (*lsa_originator
)(void *arg
),
376 struct ospf_lsa
*(*lsa_refresher
)(struct ospf_lsa
*lsa
),
377 int (*new_lsa_hook
)(struct ospf_lsa
*lsa
),
378 int (*del_lsa_hook
)(struct ospf_lsa
*lsa
))
380 struct list
*funclist
;
381 struct ospf_opaque_functab
*new;
383 if ((funclist
= ospf_get_opaque_funclist(lsa_type
)) == NULL
)
386 struct listnode
*node
, *nnode
;
387 struct ospf_opaque_functab
*functab
;
389 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
390 if (functab
->opaque_type
== opaque_type
) {
393 "ospf_register_opaque_functab: Duplicated entry?: lsa_type(%u), opaque_type(%u)",
394 lsa_type
, opaque_type
);
398 new = XCALLOC(MTYPE_OSPF_OPAQUE_FUNCTAB
,
399 sizeof(struct ospf_opaque_functab
));
401 new->opaque_type
= opaque_type
;
403 new->new_if_hook
= new_if_hook
;
404 new->del_if_hook
= del_if_hook
;
405 new->ism_change_hook
= ism_change_hook
;
406 new->nsm_change_hook
= nsm_change_hook
;
407 new->config_write_router
= config_write_router
;
408 new->config_write_if
= config_write_if
;
409 new->config_write_debug
= config_write_debug
;
410 new->show_opaque_info
= show_opaque_info
;
411 new->lsa_originator
= lsa_originator
;
412 new->lsa_refresher
= lsa_refresher
;
413 new->new_lsa_hook
= new_lsa_hook
;
414 new->del_lsa_hook
= del_lsa_hook
;
416 listnode_add(funclist
, new);
421 void ospf_delete_opaque_functab(uint8_t lsa_type
, uint8_t opaque_type
)
423 struct list
*funclist
;
424 struct listnode
*node
, *nnode
;
425 struct ospf_opaque_functab
*functab
;
427 if ((funclist
= ospf_get_opaque_funclist(lsa_type
)) != NULL
)
428 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
)) {
429 if (functab
->opaque_type
== opaque_type
) {
430 /* Cleanup internal control information, if it
432 if (functab
->oipt
!= NULL
) {
433 free_opaque_info_per_type(
435 free_opaque_info_owner(functab
->oipt
);
438 /* Dequeue listnode entry from the list. */
439 listnode_delete(funclist
, functab
);
441 /* Avoid misjudgement in the next lookup. */
442 if (listcount(funclist
) == 0)
443 funclist
->head
= funclist
->tail
= NULL
;
445 XFREE(MTYPE_OSPF_OPAQUE_FUNCTAB
, functab
);
453 static struct ospf_opaque_functab
*
454 ospf_opaque_functab_lookup(struct ospf_lsa
*lsa
)
456 struct list
*funclist
;
457 struct listnode
*node
;
458 struct ospf_opaque_functab
*functab
;
459 uint8_t key
= GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
));
461 if ((funclist
= ospf_get_opaque_funclist(lsa
->data
->type
)) != NULL
)
462 for (ALL_LIST_ELEMENTS_RO(funclist
, node
, functab
))
463 if (functab
->opaque_type
== key
)
469 /*------------------------------------------------------------------------*
470 * Followings are management functions for self-originated LSA entries.
471 *------------------------------------------------------------------------*/
474 * Opaque-LSA control information per opaque-type.
475 * Single Opaque-Type may have multiple instances; each of them will be
476 * identified by their opaque-id.
478 struct opaque_info_per_type
{
482 enum { PROC_NORMAL
, PROC_SUSPEND
} status
;
485 * Thread for (re-)origination scheduling for this opaque-type.
487 * Initial origination of Opaque-LSAs is controlled by generic
488 * Opaque-LSA handling module so that same opaque-type entries are
489 * called all at once when certain conditions are met.
490 * However, there might be cases that some Opaque-LSA clients need
491 * to (re-)originate their own Opaque-LSAs out-of-sync with others.
492 * This thread is prepared for that specific purpose.
494 struct thread
*t_opaque_lsa_self
;
497 * Backpointer to an "owner" which is LSA-type dependent.
498 * type-9: struct ospf_interface
499 * type-10: struct ospf_area
500 * type-11: struct ospf
504 /* Collection of callback functions for this opaque-type. */
505 struct ospf_opaque_functab
*functab
;
507 /* List of Opaque-LSA control informations per opaque-id. */
508 struct list
*id_list
;
511 /* Opaque-LSA control information per opaque-id. */
512 struct opaque_info_per_id
{
515 /* Thread for refresh/flush scheduling for this opaque-type/id. */
516 struct thread
*t_opaque_lsa_self
;
518 /* Backpointer to Opaque-LSA control information per opaque-type. */
519 struct opaque_info_per_type
*opqctl_type
;
521 /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
522 struct ospf_lsa
*lsa
;
525 static struct opaque_info_per_type
*
526 register_opaque_info_per_type(struct ospf_opaque_functab
*functab
,
527 struct ospf_lsa
*new);
528 static struct opaque_info_per_type
*
529 lookup_opaque_info_by_type(struct ospf_lsa
*lsa
);
530 static struct opaque_info_per_id
*
531 register_opaque_info_per_id(struct opaque_info_per_type
*oipt
,
532 struct ospf_lsa
*new);
533 static struct opaque_info_per_id
*
534 lookup_opaque_info_by_id(struct opaque_info_per_type
*oipt
,
535 struct ospf_lsa
*lsa
);
536 static struct opaque_info_per_id
*register_opaque_lsa(struct ospf_lsa
*new);
539 static struct opaque_info_per_type
*
540 register_opaque_info_per_type(struct ospf_opaque_functab
*functab
,
541 struct ospf_lsa
*new)
544 struct opaque_info_per_type
*oipt
;
546 oipt
= XCALLOC(MTYPE_OPAQUE_INFO_PER_TYPE
,
547 sizeof(struct opaque_info_per_type
));
549 switch (new->data
->type
) {
550 case OSPF_OPAQUE_LINK_LSA
:
551 oipt
->owner
= new->oi
;
552 listnode_add(new->oi
->opaque_lsa_self
, oipt
);
554 case OSPF_OPAQUE_AREA_LSA
:
555 oipt
->owner
= new->area
;
556 listnode_add(new->area
->opaque_lsa_self
, oipt
);
558 case OSPF_OPAQUE_AS_LSA
:
559 top
= ospf_lookup_by_vrf_id(new->vrf_id
);
560 if (new->area
!= NULL
&& (top
= new->area
->ospf
) == NULL
) {
561 free_opaque_info_per_type((void *)oipt
);
562 free_opaque_info_owner(oipt
);
564 goto out
; /* This case may not exist. */
567 listnode_add(top
->opaque_lsa_self
, oipt
);
571 OSPF_WARN_LSA_UNEXPECTED
,
572 "register_opaque_info_per_type: Unexpected LSA-type(%u)",
574 free_opaque_info_per_type((void *)oipt
);
575 free_opaque_info_owner(oipt
);
577 goto out
; /* This case may not exist. */
580 oipt
->lsa_type
= new->data
->type
;
581 oipt
->opaque_type
= GET_OPAQUE_TYPE(ntohl(new->data
->id
.s_addr
));
582 oipt
->status
= PROC_NORMAL
;
583 oipt
->t_opaque_lsa_self
= NULL
;
584 oipt
->functab
= functab
;
585 functab
->oipt
= oipt
;
586 oipt
->id_list
= list_new();
587 oipt
->id_list
->del
= free_opaque_info_per_id
;
593 /* Remove "oipt" from its owner's self-originated LSA list. */
594 static void free_opaque_info_owner(void *val
)
596 struct opaque_info_per_type
*oipt
= (struct opaque_info_per_type
*)val
;
598 switch (oipt
->lsa_type
) {
599 case OSPF_OPAQUE_LINK_LSA
: {
600 struct ospf_interface
*oi
=
601 (struct ospf_interface
*)(oipt
->owner
);
602 listnode_delete(oi
->opaque_lsa_self
, oipt
);
605 case OSPF_OPAQUE_AREA_LSA
: {
606 struct ospf_area
*area
= (struct ospf_area
*)(oipt
->owner
);
607 listnode_delete(area
->opaque_lsa_self
, oipt
);
610 case OSPF_OPAQUE_AS_LSA
: {
611 struct ospf
*top
= (struct ospf
*)(oipt
->owner
);
612 listnode_delete(top
->opaque_lsa_self
, oipt
);
616 flog_warn(OSPF_WARN_LSA_UNEXPECTED
,
617 "free_opaque_info_owner: Unexpected LSA-type(%u)",
619 break; /* This case may not exist. */
623 static void free_opaque_info_per_type(void *val
)
625 struct opaque_info_per_type
*oipt
= (struct opaque_info_per_type
*)val
;
626 struct opaque_info_per_id
*oipi
;
627 struct ospf_lsa
*lsa
;
628 struct listnode
*node
, *nnode
;
630 /* Control information per opaque-id may still exist. */
631 for (ALL_LIST_ELEMENTS(oipt
->id_list
, node
, nnode
, oipi
)) {
632 if ((lsa
= oipi
->lsa
) == NULL
)
634 if (IS_LSA_MAXAGE(lsa
))
636 ospf_opaque_lsa_flush_schedule(lsa
);
639 OSPF_TIMER_OFF(oipt
->t_opaque_lsa_self
);
640 list_delete_and_null(&oipt
->id_list
);
641 XFREE(MTYPE_OPAQUE_INFO_PER_TYPE
, oipt
);
645 static struct opaque_info_per_type
*
646 lookup_opaque_info_by_type(struct ospf_lsa
*lsa
)
649 struct ospf_area
*area
;
650 struct ospf_interface
*oi
;
651 struct list
*listtop
= NULL
;
652 struct listnode
*node
, *nnode
;
653 struct opaque_info_per_type
*oipt
= NULL
;
654 uint8_t key
= GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
));
656 switch (lsa
->data
->type
) {
657 case OSPF_OPAQUE_LINK_LSA
:
658 if ((oi
= lsa
->oi
) != NULL
)
659 listtop
= oi
->opaque_lsa_self
;
663 "Type-9 Opaque-LSA: Reference to OI is missing?");
665 case OSPF_OPAQUE_AREA_LSA
:
666 if ((area
= lsa
->area
) != NULL
)
667 listtop
= area
->opaque_lsa_self
;
671 "Type-10 Opaque-LSA: Reference to AREA is missing?");
673 case OSPF_OPAQUE_AS_LSA
:
674 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
675 if ((area
= lsa
->area
) != NULL
&& (top
= area
->ospf
) == NULL
) {
678 "Type-11 Opaque-LSA: Reference to OSPF is missing?");
679 break; /* Unlikely to happen. */
681 listtop
= top
->opaque_lsa_self
;
684 flog_warn(OSPF_WARN_LSA_UNEXPECTED
,
685 "lookup_opaque_info_by_type: Unexpected LSA-type(%u)",
691 for (ALL_LIST_ELEMENTS(listtop
, node
, nnode
, oipt
))
692 if (oipt
->opaque_type
== key
)
698 static struct opaque_info_per_id
*
699 register_opaque_info_per_id(struct opaque_info_per_type
*oipt
,
700 struct ospf_lsa
*new)
702 struct opaque_info_per_id
*oipi
;
704 oipi
= XCALLOC(MTYPE_OPAQUE_INFO_PER_ID
,
705 sizeof(struct opaque_info_per_id
));
707 oipi
->opaque_id
= GET_OPAQUE_ID(ntohl(new->data
->id
.s_addr
));
708 oipi
->t_opaque_lsa_self
= NULL
;
709 oipi
->opqctl_type
= oipt
;
710 oipi
->lsa
= ospf_lsa_lock(new);
712 listnode_add(oipt
->id_list
, oipi
);
717 static void free_opaque_info_per_id(void *val
)
719 struct opaque_info_per_id
*oipi
= (struct opaque_info_per_id
*)val
;
721 OSPF_TIMER_OFF(oipi
->t_opaque_lsa_self
);
722 if (oipi
->lsa
!= NULL
)
723 ospf_lsa_unlock(&oipi
->lsa
);
724 XFREE(MTYPE_OPAQUE_INFO_PER_ID
, oipi
);
728 static struct opaque_info_per_id
*
729 lookup_opaque_info_by_id(struct opaque_info_per_type
*oipt
,
730 struct ospf_lsa
*lsa
)
732 struct listnode
*node
, *nnode
;
733 struct opaque_info_per_id
*oipi
;
734 uint32_t key
= GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
));
736 for (ALL_LIST_ELEMENTS(oipt
->id_list
, node
, nnode
, oipi
))
737 if (oipi
->opaque_id
== key
)
743 static struct opaque_info_per_id
*register_opaque_lsa(struct ospf_lsa
*new)
745 struct ospf_opaque_functab
*functab
;
746 struct opaque_info_per_type
*oipt
;
747 struct opaque_info_per_id
*oipi
= NULL
;
749 if ((functab
= ospf_opaque_functab_lookup(new)) == NULL
)
752 if ((oipt
= lookup_opaque_info_by_type(new)) == NULL
753 && (oipt
= register_opaque_info_per_type(functab
, new)) == NULL
)
756 if ((oipi
= register_opaque_info_per_id(oipt
, new)) == NULL
)
763 /*------------------------------------------------------------------------*
764 * Followings are (vty) configuration functions for Opaque-LSAs handling.
765 *------------------------------------------------------------------------*/
767 DEFUN (capability_opaque
,
768 capability_opaque_cmd
,
770 "Enable specific OSPF feature\n"
773 VTY_DECLVAR_INSTANCE_CONTEXT(ospf
, ospf
);
775 /* Turn on the "master switch" of opaque-lsa capability. */
776 if (!CHECK_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
)) {
777 if (IS_DEBUG_OSPF_EVENT
)
778 zlog_debug("Opaque capability: OFF -> ON");
780 SET_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
);
781 ospf_renegotiate_optional_capabilities(ospf
);
789 "OSPF specific commands\n"
790 "Enable the Opaque-LSA capability (rfc2370)\n")
792 return capability_opaque(self
, vty
, argc
, argv
);
795 DEFUN (no_capability_opaque
,
796 no_capability_opaque_cmd
,
797 "no capability opaque",
799 "Enable specific OSPF feature\n"
802 VTY_DECLVAR_INSTANCE_CONTEXT(ospf
, ospf
);
804 /* Turn off the "master switch" of opaque-lsa capability. */
805 if (CHECK_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
)) {
806 if (IS_DEBUG_OSPF_EVENT
)
807 zlog_debug("Opaque capability: ON -> OFF");
809 UNSET_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
);
810 ospf_renegotiate_optional_capabilities(ospf
);
815 DEFUN (no_ospf_opaque
,
817 "no ospf opaque-lsa",
819 "OSPF specific commands\n"
820 "Enable the Opaque-LSA capability (rfc2370)\n")
822 return no_capability_opaque(self
, vty
, argc
, argv
);
825 static void ospf_opaque_register_vty(void)
827 install_element(OSPF_NODE
, &capability_opaque_cmd
);
828 install_element(OSPF_NODE
, &no_capability_opaque_cmd
);
829 install_element(OSPF_NODE
, &ospf_opaque_cmd
);
830 install_element(OSPF_NODE
, &no_ospf_opaque_cmd
);
834 /*------------------------------------------------------------------------*
835 * Followings are collection of user-registered function callers.
836 *------------------------------------------------------------------------*/
838 static int opaque_lsa_new_if_callback(struct list
*funclist
,
839 struct interface
*ifp
)
841 struct listnode
*node
, *nnode
;
842 struct ospf_opaque_functab
*functab
;
845 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
846 if (functab
->new_if_hook
!= NULL
)
847 if ((*functab
->new_if_hook
)(ifp
) != 0)
854 static int opaque_lsa_del_if_callback(struct list
*funclist
,
855 struct interface
*ifp
)
857 struct listnode
*node
, *nnode
;
858 struct ospf_opaque_functab
*functab
;
861 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
862 if (functab
->del_if_hook
!= NULL
)
863 if ((*functab
->del_if_hook
)(ifp
) != 0)
870 static void opaque_lsa_ism_change_callback(struct list
*funclist
,
871 struct ospf_interface
*oi
,
874 struct listnode
*node
, *nnode
;
875 struct ospf_opaque_functab
*functab
;
877 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
878 if (functab
->ism_change_hook
!= NULL
)
879 (*functab
->ism_change_hook
)(oi
, old_status
);
884 static void opaque_lsa_nsm_change_callback(struct list
*funclist
,
885 struct ospf_neighbor
*nbr
,
888 struct listnode
*node
, *nnode
;
889 struct ospf_opaque_functab
*functab
;
891 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
892 if (functab
->nsm_change_hook
!= NULL
)
893 (*functab
->nsm_change_hook
)(nbr
, old_status
);
897 static void opaque_lsa_config_write_router_callback(struct list
*funclist
,
900 struct listnode
*node
, *nnode
;
901 struct ospf_opaque_functab
*functab
;
903 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
904 if (functab
->config_write_router
!= NULL
)
905 (*functab
->config_write_router
)(vty
);
909 static void opaque_lsa_config_write_if_callback(struct list
*funclist
,
911 struct interface
*ifp
)
913 struct listnode
*node
, *nnode
;
914 struct ospf_opaque_functab
*functab
;
916 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
917 if (functab
->config_write_if
!= NULL
)
918 (*functab
->config_write_if
)(vty
, ifp
);
922 static void opaque_lsa_config_write_debug_callback(struct list
*funclist
,
925 struct listnode
*node
, *nnode
;
926 struct ospf_opaque_functab
*functab
;
928 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
929 if (functab
->config_write_debug
!= NULL
)
930 (*functab
->config_write_debug
)(vty
);
934 static int opaque_lsa_originate_callback(struct list
*funclist
,
935 void *lsa_type_dependent
)
937 struct listnode
*node
, *nnode
;
938 struct ospf_opaque_functab
*functab
;
941 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
942 if (functab
->lsa_originator
!= NULL
)
943 if ((*functab
->lsa_originator
)(lsa_type_dependent
) != 0)
950 static int new_lsa_callback(struct list
*funclist
, struct ospf_lsa
*lsa
)
952 struct listnode
*node
, *nnode
;
953 struct ospf_opaque_functab
*functab
;
956 /* This function handles ALL types of LSAs, not only opaque ones. */
957 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
958 if (functab
->new_lsa_hook
!= NULL
)
959 if ((*functab
->new_lsa_hook
)(lsa
) != 0)
966 static int del_lsa_callback(struct list
*funclist
, struct ospf_lsa
*lsa
)
968 struct listnode
*node
, *nnode
;
969 struct ospf_opaque_functab
*functab
;
972 /* This function handles ALL types of LSAs, not only opaque ones. */
973 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
974 if (functab
->del_lsa_hook
!= NULL
)
975 if ((*functab
->del_lsa_hook
)(lsa
) != 0)
982 /*------------------------------------------------------------------------*
983 * Followings are glue functions to call Opaque-LSA specific processing.
984 *------------------------------------------------------------------------*/
986 int ospf_opaque_new_if(struct interface
*ifp
)
988 struct list
*funclist
;
991 funclist
= ospf_opaque_wildcard_funclist
;
992 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
995 funclist
= ospf_opaque_type9_funclist
;
996 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
999 funclist
= ospf_opaque_type10_funclist
;
1000 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
1003 funclist
= ospf_opaque_type11_funclist
;
1004 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
1012 int ospf_opaque_del_if(struct interface
*ifp
)
1014 struct list
*funclist
;
1017 funclist
= ospf_opaque_wildcard_funclist
;
1018 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1021 funclist
= ospf_opaque_type9_funclist
;
1022 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1025 funclist
= ospf_opaque_type10_funclist
;
1026 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1029 funclist
= ospf_opaque_type11_funclist
;
1030 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1038 void ospf_opaque_ism_change(struct ospf_interface
*oi
, int old_status
)
1040 struct list
*funclist
;
1042 funclist
= ospf_opaque_wildcard_funclist
;
1043 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1045 funclist
= ospf_opaque_type9_funclist
;
1046 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1048 funclist
= ospf_opaque_type10_funclist
;
1049 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1051 funclist
= ospf_opaque_type11_funclist
;
1052 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1057 void ospf_opaque_nsm_change(struct ospf_neighbor
*nbr
, int old_state
)
1060 struct list
*funclist
;
1062 if ((top
= oi_to_top(nbr
->oi
)) == NULL
)
1065 if (old_state
!= NSM_Full
&& nbr
->state
== NSM_Full
) {
1066 if (CHECK_FLAG(nbr
->options
, OSPF_OPTION_O
)) {
1067 if (!CHECK_FLAG(top
->opaque
,
1068 OPAQUE_OPERATION_READY_BIT
)) {
1069 if (IS_DEBUG_OSPF_EVENT
)
1071 "Opaque-LSA: Now get operational!");
1073 SET_FLAG(top
->opaque
,
1074 OPAQUE_OPERATION_READY_BIT
);
1077 ospf_opaque_lsa_originate_schedule(nbr
->oi
, NULL
);
1079 } else if (old_state
== NSM_Full
&& nbr
->state
!= NSM_Full
) {
1082 * If no more opaque-capable full-state neighbor remains in the
1083 * flooding scope which corresponds to Opaque-LSA type, periodic
1084 * LS flooding should be stopped.
1090 funclist
= ospf_opaque_wildcard_funclist
;
1091 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1093 funclist
= ospf_opaque_type9_funclist
;
1094 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1096 funclist
= ospf_opaque_type10_funclist
;
1097 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1099 funclist
= ospf_opaque_type11_funclist
;
1100 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1106 void ospf_opaque_config_write_router(struct vty
*vty
, struct ospf
*ospf
)
1108 struct list
*funclist
;
1110 if (CHECK_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
))
1111 vty_out(vty
, " capability opaque\n");
1113 funclist
= ospf_opaque_wildcard_funclist
;
1114 opaque_lsa_config_write_router_callback(funclist
, vty
);
1116 funclist
= ospf_opaque_type9_funclist
;
1117 opaque_lsa_config_write_router_callback(funclist
, vty
);
1119 funclist
= ospf_opaque_type10_funclist
;
1120 opaque_lsa_config_write_router_callback(funclist
, vty
);
1122 funclist
= ospf_opaque_type11_funclist
;
1123 opaque_lsa_config_write_router_callback(funclist
, vty
);
1128 void ospf_opaque_config_write_if(struct vty
*vty
, struct interface
*ifp
)
1130 struct list
*funclist
;
1132 funclist
= ospf_opaque_wildcard_funclist
;
1133 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1135 funclist
= ospf_opaque_type9_funclist
;
1136 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1138 funclist
= ospf_opaque_type10_funclist
;
1139 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1141 funclist
= ospf_opaque_type11_funclist
;
1142 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1147 void ospf_opaque_config_write_debug(struct vty
*vty
)
1149 struct list
*funclist
;
1151 funclist
= ospf_opaque_wildcard_funclist
;
1152 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1154 funclist
= ospf_opaque_type9_funclist
;
1155 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1157 funclist
= ospf_opaque_type10_funclist
;
1158 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1160 funclist
= ospf_opaque_type11_funclist
;
1161 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1166 void show_opaque_info_detail(struct vty
*vty
, struct ospf_lsa
*lsa
)
1168 struct lsa_header
*lsah
= (struct lsa_header
*)lsa
->data
;
1169 uint32_t lsid
= ntohl(lsah
->id
.s_addr
);
1170 uint8_t opaque_type
= GET_OPAQUE_TYPE(lsid
);
1171 uint32_t opaque_id
= GET_OPAQUE_ID(lsid
);
1172 struct ospf_opaque_functab
*functab
;
1174 /* Switch output functionality by vty address. */
1176 vty_out(vty
, " Opaque-Type %u (%s)\n", opaque_type
,
1177 ospf_opaque_type_name(opaque_type
));
1178 vty_out(vty
, " Opaque-ID 0x%x\n", opaque_id
);
1180 vty_out(vty
, " Opaque-Info: %u octets of data%s\n",
1181 ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
,
1182 VALID_OPAQUE_INFO_LEN(lsah
) ? "" : "(Invalid length?)");
1184 zlog_debug(" Opaque-Type %u (%s)", opaque_type
,
1185 ospf_opaque_type_name(opaque_type
));
1186 zlog_debug(" Opaque-ID 0x%x", opaque_id
);
1188 zlog_debug(" Opaque-Info: %u octets of data%s",
1189 ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
,
1190 VALID_OPAQUE_INFO_LEN(lsah
) ? ""
1191 : "(Invalid length?)");
1194 /* Call individual output functions. */
1195 if ((functab
= ospf_opaque_functab_lookup(lsa
)) != NULL
)
1196 if (functab
->show_opaque_info
!= NULL
)
1197 (*functab
->show_opaque_info
)(vty
, lsa
);
1202 void ospf_opaque_lsa_dump(struct stream
*s
, uint16_t length
)
1204 struct ospf_lsa lsa
;
1206 lsa
.data
= (struct lsa_header
*)stream_pnt(s
);
1207 show_opaque_info_detail(NULL
, &lsa
);
1211 static int ospf_opaque_lsa_install_hook(struct ospf_lsa
*lsa
)
1213 struct list
*funclist
;
1217 * Some Opaque-LSA user may want to monitor every LSA installation
1218 * into the LSDB, regardless with target LSA type.
1220 funclist
= ospf_opaque_wildcard_funclist
;
1221 if (new_lsa_callback(funclist
, lsa
) != 0)
1224 funclist
= ospf_opaque_type9_funclist
;
1225 if (new_lsa_callback(funclist
, lsa
) != 0)
1228 funclist
= ospf_opaque_type10_funclist
;
1229 if (new_lsa_callback(funclist
, lsa
) != 0)
1232 funclist
= ospf_opaque_type11_funclist
;
1233 if (new_lsa_callback(funclist
, lsa
) != 0)
1241 static int ospf_opaque_lsa_delete_hook(struct ospf_lsa
*lsa
)
1243 struct list
*funclist
;
1247 * Some Opaque-LSA user may want to monitor every LSA deletion
1248 * from the LSDB, regardless with target LSA type.
1250 funclist
= ospf_opaque_wildcard_funclist
;
1251 if (del_lsa_callback(funclist
, lsa
) != 0)
1254 funclist
= ospf_opaque_type9_funclist
;
1255 if (del_lsa_callback(funclist
, lsa
) != 0)
1258 funclist
= ospf_opaque_type10_funclist
;
1259 if (del_lsa_callback(funclist
, lsa
) != 0)
1262 funclist
= ospf_opaque_type11_funclist
;
1263 if (del_lsa_callback(funclist
, lsa
) != 0)
1271 /*------------------------------------------------------------------------*
1272 * Followings are Opaque-LSA origination/refresh management functions.
1273 *------------------------------------------------------------------------*/
1275 static int ospf_opaque_type9_lsa_originate(struct thread
*t
);
1276 static int ospf_opaque_type10_lsa_originate(struct thread
*t
);
1277 static int ospf_opaque_type11_lsa_originate(struct thread
*t
);
1278 static void ospf_opaque_lsa_reoriginate_resume(struct list
*listtop
, void *arg
);
1280 void ospf_opaque_lsa_originate_schedule(struct ospf_interface
*oi
, int *delay0
)
1283 struct ospf_area
*area
;
1284 struct listnode
*node
, *nnode
;
1285 struct opaque_info_per_type
*oipt
;
1288 if ((top
= oi_to_top(oi
)) == NULL
|| (area
= oi
->area
) == NULL
) {
1289 if (IS_DEBUG_OSPF_EVENT
)
1291 "ospf_opaque_lsa_originate_schedule: Invalid argument?");
1295 /* It may not a right time to schedule origination now. */
1296 if (!CHECK_FLAG(top
->opaque
, OPAQUE_OPERATION_READY_BIT
)) {
1297 if (IS_DEBUG_OSPF_EVENT
)
1299 "ospf_opaque_lsa_originate_schedule: Not operational.");
1300 return; /* This is not an error. */
1307 * There might be some entries that have been waiting for triggering
1308 * of per opaque-type re-origination get resumed.
1310 ospf_opaque_lsa_reoriginate_resume(oi
->opaque_lsa_self
, (void *)oi
);
1311 ospf_opaque_lsa_reoriginate_resume(area
->opaque_lsa_self
, (void *)area
);
1312 ospf_opaque_lsa_reoriginate_resume(top
->opaque_lsa_self
, (void *)top
);
1315 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1317 if (!list_isempty(ospf_opaque_type9_funclist
)
1318 && list_isempty(oi
->opaque_lsa_self
)
1319 && oi
->t_opaque_lsa_self
== NULL
) {
1320 if (IS_DEBUG_OSPF_EVENT
)
1322 "Schedule Type-9 Opaque-LSA origination in %d ms later.",
1324 oi
->t_opaque_lsa_self
= NULL
;
1325 thread_add_timer_msec(master
, ospf_opaque_type9_lsa_originate
,
1326 oi
, delay
, &oi
->t_opaque_lsa_self
);
1327 delay
+= top
->min_ls_interval
;
1330 if (!list_isempty(ospf_opaque_type10_funclist
)
1331 && list_isempty(area
->opaque_lsa_self
)
1332 && area
->t_opaque_lsa_self
== NULL
) {
1334 * One AREA may contain multiple OIs, but above 2nd and 3rd
1335 * conditions prevent from scheduling the originate function
1338 if (IS_DEBUG_OSPF_EVENT
)
1340 "Schedule Type-10 Opaque-LSA origination in %d ms later.",
1342 area
->t_opaque_lsa_self
= NULL
;
1343 thread_add_timer_msec(master
, ospf_opaque_type10_lsa_originate
,
1344 area
, delay
, &area
->t_opaque_lsa_self
);
1345 delay
+= top
->min_ls_interval
;
1348 if (!list_isempty(ospf_opaque_type11_funclist
)
1349 && list_isempty(top
->opaque_lsa_self
)
1350 && top
->t_opaque_lsa_self
== NULL
) {
1352 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1353 * conditions prevent from scheduling the originate function
1356 if (IS_DEBUG_OSPF_EVENT
)
1358 "Schedule Type-11 Opaque-LSA origination in %d ms later.",
1360 top
->t_opaque_lsa_self
= NULL
;
1361 thread_add_timer_msec(master
, ospf_opaque_type11_lsa_originate
,
1362 top
, delay
, &top
->t_opaque_lsa_self
);
1363 delay
+= top
->min_ls_interval
;
1367 * Following section treats a special situation that this node's
1368 * opaque capability has changed as "ON -> OFF -> ON".
1370 if (!list_isempty(ospf_opaque_type9_funclist
)
1371 && !list_isempty(oi
->opaque_lsa_self
)) {
1372 for (ALL_LIST_ELEMENTS(oi
->opaque_lsa_self
, node
, nnode
,
1375 * removed the test for
1376 * (! list_isempty (oipt->id_list)) * Handler is
1378 * because opaque cababilities ON -> OFF -> ON result in
1379 * list_isempty (oipt->id_list)
1382 if (oipt
->t_opaque_lsa_self
1383 != NULL
/* Waiting for a thread call. */
1384 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1389 ospf_opaque_lsa_reoriginate_schedule(
1390 (void *)oi
, OSPF_OPAQUE_LINK_LSA
,
1395 if (!list_isempty(ospf_opaque_type10_funclist
)
1396 && !list_isempty(area
->opaque_lsa_self
)) {
1397 for (ALL_LIST_ELEMENTS(area
->opaque_lsa_self
, node
, nnode
,
1400 * removed the test for
1401 * (! list_isempty (oipt->id_list)) * Handler is
1403 * because opaque cababilities ON -> OFF -> ON result in
1404 * list_isempty (oipt->id_list)
1407 if (oipt
->t_opaque_lsa_self
1408 != NULL
/* Waiting for a thread call. */
1409 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1414 ospf_opaque_lsa_reoriginate_schedule(
1415 (void *)area
, OSPF_OPAQUE_AREA_LSA
,
1420 if (!list_isempty(ospf_opaque_type11_funclist
)
1421 && !list_isempty(top
->opaque_lsa_self
)) {
1422 for (ALL_LIST_ELEMENTS(top
->opaque_lsa_self
, node
, nnode
,
1425 * removed the test for
1426 * (! list_isempty (oipt->id_list)) * Handler is
1428 * because opaque cababilities ON -> OFF -> ON result in
1429 * list_isempty (oipt->id_list)
1432 if (oipt
->t_opaque_lsa_self
1433 != NULL
/* Waiting for a thread call. */
1434 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1439 ospf_opaque_lsa_reoriginate_schedule((void *)top
,
1449 static int ospf_opaque_type9_lsa_originate(struct thread
*t
)
1451 struct ospf_interface
*oi
;
1455 oi
->t_opaque_lsa_self
= NULL
;
1457 if (IS_DEBUG_OSPF_EVENT
)
1458 zlog_debug("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
1461 rc
= opaque_lsa_originate_callback(ospf_opaque_type9_funclist
, oi
);
1466 static int ospf_opaque_type10_lsa_originate(struct thread
*t
)
1468 struct ospf_area
*area
;
1471 area
= THREAD_ARG(t
);
1472 area
->t_opaque_lsa_self
= NULL
;
1474 if (IS_DEBUG_OSPF_EVENT
)
1476 "Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
1477 inet_ntoa(area
->area_id
));
1479 rc
= opaque_lsa_originate_callback(ospf_opaque_type10_funclist
, area
);
1484 static int ospf_opaque_type11_lsa_originate(struct thread
*t
)
1489 top
= THREAD_ARG(t
);
1490 top
->t_opaque_lsa_self
= NULL
;
1492 if (IS_DEBUG_OSPF_EVENT
)
1494 "Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
1496 rc
= opaque_lsa_originate_callback(ospf_opaque_type11_funclist
, top
);
1501 static void ospf_opaque_lsa_reoriginate_resume(struct list
*listtop
, void *arg
)
1503 struct listnode
*node
, *nnode
;
1504 struct opaque_info_per_type
*oipt
;
1505 struct ospf_opaque_functab
*functab
;
1507 if (listtop
== NULL
)
1511 * Pickup oipt entries those which in SUSPEND status, and give
1512 * them a chance to start re-origination now.
1514 for (ALL_LIST_ELEMENTS(listtop
, node
, nnode
, oipt
)) {
1515 if (oipt
->status
!= PROC_SUSPEND
)
1518 oipt
->status
= PROC_NORMAL
;
1520 if ((functab
= oipt
->functab
) == NULL
1521 || functab
->lsa_originator
== NULL
)
1524 if ((*functab
->lsa_originator
)(arg
) != 0) {
1527 "ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)",
1537 struct ospf_lsa
*ospf_opaque_lsa_install(struct ospf_lsa
*lsa
, int rt_recalc
)
1539 struct ospf_lsa
*new = NULL
;
1540 struct opaque_info_per_type
*oipt
;
1541 struct opaque_info_per_id
*oipi
;
1544 /* Don't take "rt_recalc" into consideration for now. */ /* XXX */
1546 if (!IS_LSA_SELF(lsa
)) {
1547 new = lsa
; /* Don't touch this LSA. */
1551 if (IS_DEBUG_OSPF(lsa
, LSA_INSTALL
))
1553 "Install Type-%u Opaque-LSA: [opaque-type=%u, opaque-id=%x]",
1555 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
1556 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
1558 /* Replace the existing lsa with the new one. */
1559 if ((oipt
= lookup_opaque_info_by_type(lsa
)) != NULL
1560 && (oipi
= lookup_opaque_info_by_id(oipt
, lsa
)) != NULL
) {
1561 ospf_lsa_unlock(&oipi
->lsa
);
1562 oipi
->lsa
= ospf_lsa_lock(lsa
);
1564 /* Register the new lsa entry and get its control info. */
1565 else if ((oipi
= register_opaque_lsa(lsa
)) == NULL
) {
1566 flog_warn(OSPF_WARN_LSA
,
1567 "ospf_opaque_lsa_install: register_opaque_lsa() ?");
1572 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1573 * for periodic refresh of self-originated Opaque-LSAs.
1575 switch (lsa
->data
->type
) {
1576 case OSPF_OPAQUE_LINK_LSA
:
1577 if ((top
= oi_to_top(lsa
->oi
)) == NULL
) {
1578 /* Above conditions must have passed. */
1579 flog_warn(OSPF_WARN_LSA
,
1580 "ospf_opaque_lsa_install: Something wrong?");
1584 case OSPF_OPAQUE_AREA_LSA
:
1585 if (lsa
->area
== NULL
|| (top
= lsa
->area
->ospf
) == NULL
) {
1586 /* Above conditions must have passed. */
1587 flog_warn(OSPF_WARN_LSA
,
1588 "ospf_opaque_lsa_install: Something wrong?");
1592 case OSPF_OPAQUE_AS_LSA
:
1593 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
1594 if (lsa
->area
!= NULL
&& (top
= lsa
->area
->ospf
) == NULL
) {
1595 /* Above conditions must have passed. */
1596 flog_warn(OSPF_WARN_LSA
,
1597 "ospf_opaque_lsa_install: Something wrong?");
1602 flog_warn(OSPF_WARN_LSA_UNEXPECTED
,
1603 "ospf_opaque_lsa_install: Unexpected LSA-type(%u)",
1608 ospf_refresher_register_lsa(top
, lsa
);
1615 struct ospf_lsa
*ospf_opaque_lsa_refresh(struct ospf_lsa
*lsa
)
1618 struct ospf_opaque_functab
*functab
;
1619 struct ospf_lsa
*new = NULL
;
1621 ospf
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
1623 if ((functab
= ospf_opaque_functab_lookup(lsa
)) == NULL
1624 || functab
->lsa_refresher
== NULL
) {
1626 * Though this LSA seems to have originated on this node, the
1627 * handling module for this "lsa-type and opaque-type" was
1628 * already deleted sometime ago.
1629 * Anyway, this node still has a responsibility to flush this
1630 * LSA from the routing domain.
1632 if (IS_DEBUG_OSPF_EVENT
)
1633 zlog_debug("LSA[Type%d:%s]: Flush stray Opaque-LSA",
1634 lsa
->data
->type
, inet_ntoa(lsa
->data
->id
));
1636 lsa
->data
->ls_age
= htons(OSPF_LSA_MAXAGE
);
1637 ospf_lsa_flush(ospf
, lsa
);
1639 new = (*functab
->lsa_refresher
)(lsa
);
1644 /*------------------------------------------------------------------------*
1645 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1646 * triggered by external interventions (vty session, signaling, etc).
1647 *------------------------------------------------------------------------*/
1649 #define OSPF_OPAQUE_TIMER_ON(T,F,L,V) thread_add_timer_msec (master, (F), (L), (V), &(T))
1651 static struct ospf_lsa
*pseudo_lsa(struct ospf_interface
*oi
,
1652 struct ospf_area
*area
, uint8_t lsa_type
,
1653 uint8_t opaque_type
);
1654 static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread
*t
);
1655 static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread
*t
);
1656 static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread
*t
);
1657 static int ospf_opaque_lsa_refresh_timer(struct thread
*t
);
1659 void ospf_opaque_lsa_reoriginate_schedule(void *lsa_type_dependent
,
1660 uint8_t lsa_type
, uint8_t opaque_type
)
1662 struct ospf
*top
= NULL
;
1663 struct ospf_area dummy
, *area
= NULL
;
1664 struct ospf_interface
*oi
= NULL
;
1666 struct ospf_lsa
*lsa
;
1667 struct opaque_info_per_type
*oipt
;
1668 int (*func
)(struct thread
* t
) = NULL
;
1672 case OSPF_OPAQUE_LINK_LSA
:
1673 if ((oi
= (struct ospf_interface
*)lsa_type_dependent
)
1677 "ospf_opaque_lsa_reoriginate_schedule: Type-9 Opaque-LSA: Invalid parameter?");
1680 if ((top
= oi_to_top(oi
)) == NULL
) {
1683 "ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1687 if (!list_isempty(ospf_opaque_type9_funclist
)
1688 && list_isempty(oi
->opaque_lsa_self
)
1689 && oi
->t_opaque_lsa_self
!= NULL
) {
1692 "Type-9 Opaque-LSA (opaque_type=%u): Common origination for OI(%s) has already started",
1693 opaque_type
, IF_NAME(oi
));
1696 func
= ospf_opaque_type9_lsa_reoriginate_timer
;
1698 case OSPF_OPAQUE_AREA_LSA
:
1699 if ((area
= (struct ospf_area
*)lsa_type_dependent
) == NULL
) {
1702 "ospf_opaque_lsa_reoriginate_schedule: Type-10 Opaque-LSA: Invalid parameter?");
1705 if ((top
= area
->ospf
) == NULL
) {
1708 "ospf_opaque_lsa_reoriginate_schedule: AREA(%s) -> TOP?",
1709 inet_ntoa(area
->area_id
));
1712 if (!list_isempty(ospf_opaque_type10_funclist
)
1713 && list_isempty(area
->opaque_lsa_self
)
1714 && area
->t_opaque_lsa_self
!= NULL
) {
1717 "Type-10 Opaque-LSA (opaque_type=%u): Common origination for AREA(%s) has already started",
1718 opaque_type
, inet_ntoa(area
->area_id
));
1721 func
= ospf_opaque_type10_lsa_reoriginate_timer
;
1723 case OSPF_OPAQUE_AS_LSA
:
1724 if ((top
= (struct ospf
*)lsa_type_dependent
) == NULL
) {
1727 "ospf_opaque_lsa_reoriginate_schedule: Type-11 Opaque-LSA: Invalid parameter?");
1730 if (!list_isempty(ospf_opaque_type11_funclist
)
1731 && list_isempty(top
->opaque_lsa_self
)
1732 && top
->t_opaque_lsa_self
!= NULL
) {
1735 "Type-11 Opaque-LSA (opaque_type=%u): Common origination has already started",
1740 /* Fake "area" to pass "ospf" to a lookup function later. */
1744 func
= ospf_opaque_type11_lsa_reoriginate_timer
;
1748 OSPF_WARN_LSA_UNEXPECTED
,
1749 "ospf_opaque_lsa_reoriginate_schedule: Unexpected LSA-type(%u)",
1754 /* It may not a right time to schedule reorigination now. */
1755 if (!CHECK_FLAG(top
->opaque
, OPAQUE_OPERATION_READY_BIT
)) {
1756 if (IS_DEBUG_OSPF_EVENT
)
1758 "ospf_opaque_lsa_reoriginate_schedule: Not operational.");
1759 goto out
; /* This is not an error. */
1762 /* Generate a dummy lsa to be passed for a lookup function. */
1763 lsa
= pseudo_lsa(oi
, area
, lsa_type
, opaque_type
);
1764 lsa
->vrf_id
= top
->vrf_id
;
1766 if ((oipt
= lookup_opaque_info_by_type(lsa
)) == NULL
) {
1767 struct ospf_opaque_functab
*functab
;
1768 if ((functab
= ospf_opaque_functab_lookup(lsa
)) == NULL
) {
1771 "ospf_opaque_lsa_reoriginate_schedule: No associated function?: lsa_type(%u), opaque_type(%u)",
1772 lsa_type
, opaque_type
);
1775 if ((oipt
= register_opaque_info_per_type(functab
, lsa
))
1779 "ospf_opaque_lsa_reoriginate_schedule: Cannot get a control info?: lsa_type(%u), opaque_type(%u)",
1780 lsa_type
, opaque_type
);
1785 if (oipt
->t_opaque_lsa_self
!= NULL
) {
1786 if (IS_DEBUG_OSPF_EVENT
)
1788 "Type-%u Opaque-LSA has already scheduled to"
1789 " RE-ORIGINATE: [opaque-type=%u]",
1791 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)));
1796 * Different from initial origination time, in which various conditions
1797 * (opaque capability, neighbor status etc) are assured by caller of
1798 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1799 * it is highly possible that these conditions might not be satisfied
1800 * at the time of re-origination function is to be called.
1802 delay
= top
->min_ls_interval
; /* XXX */
1804 if (IS_DEBUG_OSPF_EVENT
)
1806 "Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
1807 " ms later: [opaque-type=%u]",
1809 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)));
1811 OSPF_OPAQUE_TIMER_ON(oipt
->t_opaque_lsa_self
, func
, oipt
, delay
);
1817 static struct ospf_lsa
*pseudo_lsa(struct ospf_interface
*oi
,
1818 struct ospf_area
*area
, uint8_t lsa_type
,
1819 uint8_t opaque_type
)
1821 static struct ospf_lsa lsa
= {0};
1822 static struct lsa_header lsah
= {0};
1828 lsa
.vrf_id
= VRF_DEFAULT
;
1830 lsah
.type
= lsa_type
;
1831 tmp
= SET_OPAQUE_LSID(opaque_type
, 0); /* Opaque-ID is unused here. */
1832 lsah
.id
.s_addr
= htonl(tmp
);
1837 static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread
*t
)
1839 struct opaque_info_per_type
*oipt
;
1840 struct ospf_opaque_functab
*functab
;
1842 struct ospf_interface
*oi
;
1845 oipt
= THREAD_ARG(t
);
1846 oipt
->t_opaque_lsa_self
= NULL
;
1848 if ((functab
= oipt
->functab
) == NULL
1849 || functab
->lsa_originator
== NULL
) {
1852 "ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1856 oi
= (struct ospf_interface
*)oipt
->owner
;
1857 if ((top
= oi_to_top(oi
)) == NULL
) {
1860 "ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1864 if (!CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)
1865 || !ospf_if_is_enable(oi
)
1866 || ospf_nbr_count_opaque_capable(oi
) == 0) {
1867 if (IS_DEBUG_OSPF_EVENT
)
1869 "Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...",
1872 oipt
->status
= PROC_SUSPEND
;
1877 if (IS_DEBUG_OSPF_EVENT
)
1879 "Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)",
1880 oipt
->opaque_type
, IF_NAME(oi
));
1882 rc
= (*functab
->lsa_originator
)(oi
);
1887 static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread
*t
)
1889 struct opaque_info_per_type
*oipt
;
1890 struct ospf_opaque_functab
*functab
;
1891 struct listnode
*node
, *nnode
;
1893 struct ospf_area
*area
;
1894 struct ospf_interface
*oi
;
1897 oipt
= THREAD_ARG(t
);
1898 oipt
->t_opaque_lsa_self
= NULL
;
1900 if ((functab
= oipt
->functab
) == NULL
1901 || functab
->lsa_originator
== NULL
) {
1904 "ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1908 area
= (struct ospf_area
*)oipt
->owner
;
1909 if (area
== NULL
|| (top
= area
->ospf
) == NULL
) {
1912 "ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1916 /* There must be at least one "opaque-capable, full-state" neighbor. */
1918 for (ALL_LIST_ELEMENTS(area
->oiflist
, node
, nnode
, oi
)) {
1919 if ((n
= ospf_nbr_count_opaque_capable(oi
)) > 0)
1923 if (n
== 0 || !CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)) {
1924 if (IS_DEBUG_OSPF_EVENT
)
1926 "Suspend re-origination of Type-10 Opaque-LSAs"
1927 " (opaque-type=%u) for a while...",
1930 oipt
->status
= PROC_SUSPEND
;
1935 if (IS_DEBUG_OSPF_EVENT
)
1937 "Timer[Type10-LSA]: Re-originate Opaque-LSAs"
1938 " (opaque-type=%u) for Area %s",
1939 oipt
->opaque_type
, inet_ntoa(area
->area_id
));
1941 rc
= (*functab
->lsa_originator
)(area
);
1946 static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread
*t
)
1948 struct opaque_info_per_type
*oipt
;
1949 struct ospf_opaque_functab
*functab
;
1953 oipt
= THREAD_ARG(t
);
1954 oipt
->t_opaque_lsa_self
= NULL
;
1956 if ((functab
= oipt
->functab
) == NULL
1957 || functab
->lsa_originator
== NULL
) {
1960 "ospf_opaque_type11_lsa_reoriginate_timer: No associated function?");
1964 if ((top
= (struct ospf
*)oipt
->owner
) == NULL
) {
1967 "ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1971 if (!CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)) {
1972 if (IS_DEBUG_OSPF_EVENT
)
1974 "Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...",
1977 oipt
->status
= PROC_SUSPEND
;
1982 if (IS_DEBUG_OSPF_EVENT
)
1984 "Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).",
1987 rc
= (*functab
->lsa_originator
)(top
);
1992 void ospf_opaque_lsa_refresh_schedule(struct ospf_lsa
*lsa0
)
1994 struct opaque_info_per_type
*oipt
;
1995 struct opaque_info_per_id
*oipi
;
1996 struct ospf_lsa
*lsa
;
2000 if ((oipt
= lookup_opaque_info_by_type(lsa0
)) == NULL
2001 || (oipi
= lookup_opaque_info_by_id(oipt
, lsa0
)) == NULL
) {
2004 "ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
2008 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2009 if ((lsa
= oipi
->lsa
) == NULL
) {
2010 flog_warn(OSPF_WARN_LSA
,
2011 "ospf_opaque_lsa_refresh_schedule: Something wrong?");
2015 if (oipi
->t_opaque_lsa_self
!= NULL
) {
2016 if (IS_DEBUG_OSPF_EVENT
)
2018 "Type-%u Opaque-LSA has already scheduled to REFRESH: [opaque-type=%u, opaque-id=%x]",
2020 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
2021 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
2025 /* Delete this lsa from neighbor retransmit-list. */
2026 switch (lsa
->data
->type
) {
2027 case OSPF_OPAQUE_LINK_LSA
:
2028 case OSPF_OPAQUE_AREA_LSA
:
2029 ospf_ls_retransmit_delete_nbr_area(lsa
->area
, lsa
);
2031 case OSPF_OPAQUE_AS_LSA
:
2032 top
= ospf_lookup_by_vrf_id(lsa0
->vrf_id
);
2033 if ((lsa0
->area
!= NULL
) && (lsa0
->area
->ospf
!= NULL
))
2034 top
= lsa0
->area
->ospf
;
2035 ospf_ls_retransmit_delete_nbr_as(top
, lsa
);
2039 OSPF_WARN_LSA_UNEXPECTED
,
2040 "ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)",
2045 delay
= ospf_lsa_refresh_delay(lsa
);
2047 if (IS_DEBUG_OSPF_EVENT
)
2049 "Schedule Type-%u Opaque-LSA to REFRESH in %d sec later: [opaque-type=%u, opaque-id=%x]",
2050 lsa
->data
->type
, delay
,
2051 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
2052 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
2054 OSPF_OPAQUE_TIMER_ON(oipi
->t_opaque_lsa_self
,
2055 ospf_opaque_lsa_refresh_timer
, oipi
, delay
* 1000);
2060 static int ospf_opaque_lsa_refresh_timer(struct thread
*t
)
2062 struct opaque_info_per_id
*oipi
;
2063 struct ospf_opaque_functab
*functab
;
2064 struct ospf_lsa
*lsa
;
2066 if (IS_DEBUG_OSPF_EVENT
)
2067 zlog_debug("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
2069 oipi
= THREAD_ARG(t
);
2070 oipi
->t_opaque_lsa_self
= NULL
;
2072 if ((lsa
= oipi
->lsa
) != NULL
)
2073 if ((functab
= oipi
->opqctl_type
->functab
) != NULL
)
2074 if (functab
->lsa_refresher
!= NULL
)
2075 (*functab
->lsa_refresher
)(lsa
);
2080 void ospf_opaque_lsa_flush_schedule(struct ospf_lsa
*lsa0
)
2082 struct opaque_info_per_type
*oipt
;
2083 struct opaque_info_per_id
*oipi
;
2084 struct ospf_lsa
*lsa
;
2087 top
= ospf_lookup_by_vrf_id(lsa0
->vrf_id
);
2089 if ((oipt
= lookup_opaque_info_by_type(lsa0
)) == NULL
2090 || (oipi
= lookup_opaque_info_by_id(oipt
, lsa0
)) == NULL
) {
2091 flog_warn(OSPF_WARN_LSA
,
2092 "ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2096 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2097 if ((lsa
= oipi
->lsa
) == NULL
) {
2098 flog_warn(OSPF_WARN_LSA
,
2099 "ospf_opaque_lsa_flush_schedule: Something wrong?");
2103 /* Delete this lsa from neighbor retransmit-list. */
2104 switch (lsa
->data
->type
) {
2105 case OSPF_OPAQUE_LINK_LSA
:
2106 case OSPF_OPAQUE_AREA_LSA
:
2107 ospf_ls_retransmit_delete_nbr_area(lsa
->area
, lsa
);
2109 case OSPF_OPAQUE_AS_LSA
:
2110 if ((lsa0
->area
!= NULL
) && (lsa0
->area
->ospf
!= NULL
))
2111 top
= lsa0
->area
->ospf
;
2112 ospf_ls_retransmit_delete_nbr_as(top
, lsa
);
2116 OSPF_WARN_LSA_UNEXPECTED
,
2117 "ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)",
2122 /* Dequeue listnode entry from the list. */
2123 listnode_delete(oipt
->id_list
, oipi
);
2125 /* Avoid misjudgement in the next lookup. */
2126 if (listcount(oipt
->id_list
) == 0)
2127 oipt
->id_list
->head
= oipt
->id_list
->tail
= NULL
;
2129 /* Disassociate internal control information with the given lsa. */
2130 free_opaque_info_per_id((void *)oipi
);
2132 /* Force given lsa's age to MaxAge. */
2133 lsa
->data
->ls_age
= htons(OSPF_LSA_MAXAGE
);
2135 if (IS_DEBUG_OSPF_EVENT
)
2137 "Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]",
2139 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
2140 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
2142 /* This lsa will be flushed and removed eventually. */
2143 ospf_lsa_flush(top
, lsa
);
2149 void ospf_opaque_self_originated_lsa_received(struct ospf_neighbor
*nbr
,
2150 struct ospf_lsa
*lsa
)
2154 if ((top
= oi_to_top(nbr
->oi
)) == NULL
)
2158 * Since these LSA entries are not yet installed into corresponding
2159 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2161 lsa
->data
->ls_age
= htons(OSPF_LSA_MAXAGE
);
2162 switch (lsa
->data
->type
) {
2163 case OSPF_OPAQUE_LINK_LSA
:
2164 ospf_flood_through_area(nbr
->oi
->area
, NULL
/*inbr*/, lsa
);
2166 case OSPF_OPAQUE_AREA_LSA
:
2167 ospf_flood_through_area(nbr
->oi
->area
, NULL
/*inbr*/, lsa
);
2169 case OSPF_OPAQUE_AS_LSA
:
2170 ospf_flood_through_as(top
, NULL
/*inbr*/, lsa
);
2174 OSPF_WARN_LSA_UNEXPECTED
,
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 flog_warn(OSPF_WARN_LSA
,
2194 "Broken relationship for \"OI -> AREA -> OSPF\"?");