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(&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(&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(&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(&area
->opaque_lsa_self
);
184 int ospf_opaque_type11_lsa_init(struct ospf
*top
)
186 if (top
->opaque_lsa_self
!= NULL
)
187 list_delete(&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(&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(&funclist
);
319 funclist
= ospf_opaque_type9_funclist
;
320 list_delete(&funclist
);
322 funclist
= ospf_opaque_type10_funclist
;
323 list_delete(&funclist
);
325 funclist
= ospf_opaque_type11_funclist
;
326 list_delete(&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(EC_OSPF_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_owner(functab
->oipt
);
434 free_opaque_info_per_type(
438 /* Dequeue listnode entry from the list. */
439 listnode_delete(funclist
, functab
);
441 XFREE(MTYPE_OSPF_OPAQUE_FUNCTAB
, functab
);
449 static struct ospf_opaque_functab
*
450 ospf_opaque_functab_lookup(struct ospf_lsa
*lsa
)
452 struct list
*funclist
;
453 struct listnode
*node
;
454 struct ospf_opaque_functab
*functab
;
455 uint8_t key
= GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
));
457 if ((funclist
= ospf_get_opaque_funclist(lsa
->data
->type
)) != NULL
)
458 for (ALL_LIST_ELEMENTS_RO(funclist
, node
, functab
))
459 if (functab
->opaque_type
== key
)
465 /*------------------------------------------------------------------------*
466 * Followings are management functions for self-originated LSA entries.
467 *------------------------------------------------------------------------*/
470 * Opaque-LSA control information per opaque-type.
471 * Single Opaque-Type may have multiple instances; each of them will be
472 * identified by their opaque-id.
474 struct opaque_info_per_type
{
478 enum { PROC_NORMAL
, PROC_SUSPEND
} status
;
481 * Thread for (re-)origination scheduling for this opaque-type.
483 * Initial origination of Opaque-LSAs is controlled by generic
484 * Opaque-LSA handling module so that same opaque-type entries are
485 * called all at once when certain conditions are met.
486 * However, there might be cases that some Opaque-LSA clients need
487 * to (re-)originate their own Opaque-LSAs out-of-sync with others.
488 * This thread is prepared for that specific purpose.
490 struct thread
*t_opaque_lsa_self
;
493 * Backpointer to an "owner" which is LSA-type dependent.
494 * type-9: struct ospf_interface
495 * type-10: struct ospf_area
496 * type-11: struct ospf
500 /* Collection of callback functions for this opaque-type. */
501 struct ospf_opaque_functab
*functab
;
503 /* List of Opaque-LSA control information per opaque-id. */
504 struct list
*id_list
;
507 /* Opaque-LSA control information per opaque-id. */
508 struct opaque_info_per_id
{
511 /* Thread for refresh/flush scheduling for this opaque-type/id. */
512 struct thread
*t_opaque_lsa_self
;
514 /* Backpointer to Opaque-LSA control information per opaque-type. */
515 struct opaque_info_per_type
*opqctl_type
;
517 /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
518 struct ospf_lsa
*lsa
;
521 static struct opaque_info_per_type
*
522 register_opaque_info_per_type(struct ospf_opaque_functab
*functab
,
523 struct ospf_lsa
*new);
524 static struct opaque_info_per_type
*
525 lookup_opaque_info_by_type(struct ospf_lsa
*lsa
);
526 static struct opaque_info_per_id
*
527 register_opaque_info_per_id(struct opaque_info_per_type
*oipt
,
528 struct ospf_lsa
*new);
529 static struct opaque_info_per_id
*
530 lookup_opaque_info_by_id(struct opaque_info_per_type
*oipt
,
531 struct ospf_lsa
*lsa
);
532 static struct opaque_info_per_id
*register_opaque_lsa(struct ospf_lsa
*new);
535 static struct opaque_info_per_type
*
536 register_opaque_info_per_type(struct ospf_opaque_functab
*functab
,
537 struct ospf_lsa
*new)
540 struct opaque_info_per_type
*oipt
;
542 oipt
= XCALLOC(MTYPE_OPAQUE_INFO_PER_TYPE
,
543 sizeof(struct opaque_info_per_type
));
545 switch (new->data
->type
) {
546 case OSPF_OPAQUE_LINK_LSA
:
547 oipt
->owner
= new->oi
;
548 listnode_add(new->oi
->opaque_lsa_self
, oipt
);
550 case OSPF_OPAQUE_AREA_LSA
:
551 oipt
->owner
= new->area
;
552 listnode_add(new->area
->opaque_lsa_self
, oipt
);
554 case OSPF_OPAQUE_AS_LSA
:
555 top
= ospf_lookup_by_vrf_id(new->vrf_id
);
556 if (new->area
!= NULL
&& (top
= new->area
->ospf
) == NULL
) {
557 free_opaque_info_owner(oipt
);
558 free_opaque_info_per_type(oipt
);
560 goto out
; /* This case may not exist. */
563 listnode_add(top
->opaque_lsa_self
, oipt
);
567 EC_OSPF_LSA_UNEXPECTED
,
568 "register_opaque_info_per_type: Unexpected LSA-type(%u)",
570 free_opaque_info_owner(oipt
);
571 free_opaque_info_per_type(oipt
);
573 goto out
; /* This case may not exist. */
576 oipt
->lsa_type
= new->data
->type
;
577 oipt
->opaque_type
= GET_OPAQUE_TYPE(ntohl(new->data
->id
.s_addr
));
578 oipt
->status
= PROC_NORMAL
;
579 oipt
->t_opaque_lsa_self
= NULL
;
580 oipt
->functab
= functab
;
581 functab
->oipt
= oipt
;
582 oipt
->id_list
= list_new();
583 oipt
->id_list
->del
= free_opaque_info_per_id
;
589 /* Remove "oipt" from its owner's self-originated LSA list. */
590 static void free_opaque_info_owner(void *val
)
592 struct opaque_info_per_type
*oipt
= (struct opaque_info_per_type
*)val
;
594 switch (oipt
->lsa_type
) {
595 case OSPF_OPAQUE_LINK_LSA
: {
596 struct ospf_interface
*oi
=
597 (struct ospf_interface
*)(oipt
->owner
);
598 listnode_delete(oi
->opaque_lsa_self
, oipt
);
601 case OSPF_OPAQUE_AREA_LSA
: {
602 struct ospf_area
*area
= (struct ospf_area
*)(oipt
->owner
);
603 listnode_delete(area
->opaque_lsa_self
, oipt
);
606 case OSPF_OPAQUE_AS_LSA
: {
607 struct ospf
*top
= (struct ospf
*)(oipt
->owner
);
608 listnode_delete(top
->opaque_lsa_self
, oipt
);
612 flog_warn(EC_OSPF_LSA_UNEXPECTED
,
613 "free_opaque_info_owner: Unexpected LSA-type(%u)",
615 break; /* This case may not exist. */
619 static void free_opaque_info_per_type(void *val
)
621 struct opaque_info_per_type
*oipt
= (struct opaque_info_per_type
*)val
;
622 struct opaque_info_per_id
*oipi
;
623 struct ospf_lsa
*lsa
;
624 struct listnode
*node
, *nnode
;
626 /* Control information per opaque-id may still exist. */
627 for (ALL_LIST_ELEMENTS(oipt
->id_list
, node
, nnode
, oipi
)) {
628 if ((lsa
= oipi
->lsa
) == NULL
)
630 if (IS_LSA_MAXAGE(lsa
))
632 ospf_opaque_lsa_flush_schedule(lsa
);
635 OSPF_TIMER_OFF(oipt
->t_opaque_lsa_self
);
636 list_delete(&oipt
->id_list
);
637 XFREE(MTYPE_OPAQUE_INFO_PER_TYPE
, oipt
);
641 static struct opaque_info_per_type
*
642 lookup_opaque_info_by_type(struct ospf_lsa
*lsa
)
645 struct ospf_area
*area
;
646 struct ospf_interface
*oi
;
647 struct list
*listtop
= NULL
;
648 struct listnode
*node
, *nnode
;
649 struct opaque_info_per_type
*oipt
= NULL
;
650 uint8_t key
= GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
));
652 switch (lsa
->data
->type
) {
653 case OSPF_OPAQUE_LINK_LSA
:
654 if ((oi
= lsa
->oi
) != NULL
)
655 listtop
= oi
->opaque_lsa_self
;
659 "Type-9 Opaque-LSA: Reference to OI is missing?");
661 case OSPF_OPAQUE_AREA_LSA
:
662 if ((area
= lsa
->area
) != NULL
)
663 listtop
= area
->opaque_lsa_self
;
667 "Type-10 Opaque-LSA: Reference to AREA is missing?");
669 case OSPF_OPAQUE_AS_LSA
:
670 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
671 if ((area
= lsa
->area
) != NULL
&& (top
= area
->ospf
) == NULL
) {
674 "Type-11 Opaque-LSA: Reference to OSPF is missing?");
675 break; /* Unlikely to happen. */
677 listtop
= top
->opaque_lsa_self
;
680 flog_warn(EC_OSPF_LSA_UNEXPECTED
,
681 "lookup_opaque_info_by_type: Unexpected LSA-type(%u)",
687 for (ALL_LIST_ELEMENTS(listtop
, node
, nnode
, oipt
))
688 if (oipt
->opaque_type
== key
)
694 static struct opaque_info_per_id
*
695 register_opaque_info_per_id(struct opaque_info_per_type
*oipt
,
696 struct ospf_lsa
*new)
698 struct opaque_info_per_id
*oipi
;
700 oipi
= XCALLOC(MTYPE_OPAQUE_INFO_PER_ID
,
701 sizeof(struct opaque_info_per_id
));
703 oipi
->opaque_id
= GET_OPAQUE_ID(ntohl(new->data
->id
.s_addr
));
704 oipi
->t_opaque_lsa_self
= NULL
;
705 oipi
->opqctl_type
= oipt
;
706 oipi
->lsa
= ospf_lsa_lock(new);
708 listnode_add(oipt
->id_list
, oipi
);
713 static void free_opaque_info_per_id(void *val
)
715 struct opaque_info_per_id
*oipi
= (struct opaque_info_per_id
*)val
;
717 OSPF_TIMER_OFF(oipi
->t_opaque_lsa_self
);
718 if (oipi
->lsa
!= NULL
)
719 ospf_lsa_unlock(&oipi
->lsa
);
720 XFREE(MTYPE_OPAQUE_INFO_PER_ID
, oipi
);
724 static struct opaque_info_per_id
*
725 lookup_opaque_info_by_id(struct opaque_info_per_type
*oipt
,
726 struct ospf_lsa
*lsa
)
728 struct listnode
*node
, *nnode
;
729 struct opaque_info_per_id
*oipi
;
730 uint32_t key
= GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
));
732 for (ALL_LIST_ELEMENTS(oipt
->id_list
, node
, nnode
, oipi
))
733 if (oipi
->opaque_id
== key
)
739 static struct opaque_info_per_id
*register_opaque_lsa(struct ospf_lsa
*new)
741 struct ospf_opaque_functab
*functab
;
742 struct opaque_info_per_type
*oipt
;
743 struct opaque_info_per_id
*oipi
= NULL
;
745 if ((functab
= ospf_opaque_functab_lookup(new)) == NULL
)
748 if ((oipt
= lookup_opaque_info_by_type(new)) == NULL
749 && (oipt
= register_opaque_info_per_type(functab
, new)) == NULL
)
752 if ((oipi
= register_opaque_info_per_id(oipt
, new)) == NULL
)
759 /*------------------------------------------------------------------------*
760 * Followings are (vty) configuration functions for Opaque-LSAs handling.
761 *------------------------------------------------------------------------*/
763 DEFUN (capability_opaque
,
764 capability_opaque_cmd
,
766 "Enable specific OSPF feature\n"
769 VTY_DECLVAR_INSTANCE_CONTEXT(ospf
, ospf
);
771 /* Turn on the "master switch" of opaque-lsa capability. */
772 if (!CHECK_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
)) {
773 if (IS_DEBUG_OSPF_EVENT
)
774 zlog_debug("Opaque capability: OFF -> ON");
776 SET_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
);
777 ospf_renegotiate_optional_capabilities(ospf
);
785 "OSPF specific commands\n"
786 "Enable the Opaque-LSA capability (rfc2370)\n")
788 return capability_opaque(self
, vty
, argc
, argv
);
791 DEFUN (no_capability_opaque
,
792 no_capability_opaque_cmd
,
793 "no capability opaque",
795 "Enable specific OSPF feature\n"
798 VTY_DECLVAR_INSTANCE_CONTEXT(ospf
, ospf
);
800 /* Turn off the "master switch" of opaque-lsa capability. */
801 if (CHECK_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
)) {
802 if (IS_DEBUG_OSPF_EVENT
)
803 zlog_debug("Opaque capability: ON -> OFF");
805 UNSET_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
);
806 ospf_renegotiate_optional_capabilities(ospf
);
811 DEFUN (no_ospf_opaque
,
813 "no ospf opaque-lsa",
815 "OSPF specific commands\n"
816 "Enable the Opaque-LSA capability (rfc2370)\n")
818 return no_capability_opaque(self
, vty
, argc
, argv
);
821 static void ospf_opaque_register_vty(void)
823 install_element(OSPF_NODE
, &capability_opaque_cmd
);
824 install_element(OSPF_NODE
, &no_capability_opaque_cmd
);
825 install_element(OSPF_NODE
, &ospf_opaque_cmd
);
826 install_element(OSPF_NODE
, &no_ospf_opaque_cmd
);
830 /*------------------------------------------------------------------------*
831 * Followings are collection of user-registered function callers.
832 *------------------------------------------------------------------------*/
834 static int opaque_lsa_new_if_callback(struct list
*funclist
,
835 struct interface
*ifp
)
837 struct listnode
*node
, *nnode
;
838 struct ospf_opaque_functab
*functab
;
841 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
842 if (functab
->new_if_hook
!= NULL
)
843 if ((*functab
->new_if_hook
)(ifp
) != 0)
850 static int opaque_lsa_del_if_callback(struct list
*funclist
,
851 struct interface
*ifp
)
853 struct listnode
*node
, *nnode
;
854 struct ospf_opaque_functab
*functab
;
857 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
858 if (functab
->del_if_hook
!= NULL
)
859 if ((*functab
->del_if_hook
)(ifp
) != 0)
866 static void opaque_lsa_ism_change_callback(struct list
*funclist
,
867 struct ospf_interface
*oi
,
870 struct listnode
*node
, *nnode
;
871 struct ospf_opaque_functab
*functab
;
873 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
874 if (functab
->ism_change_hook
!= NULL
)
875 (*functab
->ism_change_hook
)(oi
, old_status
);
880 static void opaque_lsa_nsm_change_callback(struct list
*funclist
,
881 struct ospf_neighbor
*nbr
,
884 struct listnode
*node
, *nnode
;
885 struct ospf_opaque_functab
*functab
;
887 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
888 if (functab
->nsm_change_hook
!= NULL
)
889 (*functab
->nsm_change_hook
)(nbr
, old_status
);
893 static void opaque_lsa_config_write_router_callback(struct list
*funclist
,
896 struct listnode
*node
, *nnode
;
897 struct ospf_opaque_functab
*functab
;
899 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
900 if (functab
->config_write_router
!= NULL
)
901 (*functab
->config_write_router
)(vty
);
905 static void opaque_lsa_config_write_if_callback(struct list
*funclist
,
907 struct interface
*ifp
)
909 struct listnode
*node
, *nnode
;
910 struct ospf_opaque_functab
*functab
;
912 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
913 if (functab
->config_write_if
!= NULL
)
914 (*functab
->config_write_if
)(vty
, ifp
);
918 static void opaque_lsa_config_write_debug_callback(struct list
*funclist
,
921 struct listnode
*node
, *nnode
;
922 struct ospf_opaque_functab
*functab
;
924 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
925 if (functab
->config_write_debug
!= NULL
)
926 (*functab
->config_write_debug
)(vty
);
930 static int opaque_lsa_originate_callback(struct list
*funclist
,
931 void *lsa_type_dependent
)
933 struct listnode
*node
, *nnode
;
934 struct ospf_opaque_functab
*functab
;
937 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
938 if (functab
->lsa_originator
!= NULL
)
939 if ((*functab
->lsa_originator
)(lsa_type_dependent
) != 0)
946 static int new_lsa_callback(struct list
*funclist
, struct ospf_lsa
*lsa
)
948 struct listnode
*node
, *nnode
;
949 struct ospf_opaque_functab
*functab
;
952 /* This function handles ALL types of LSAs, not only opaque ones. */
953 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
954 if (functab
->new_lsa_hook
!= NULL
)
955 if ((*functab
->new_lsa_hook
)(lsa
) != 0)
962 static int del_lsa_callback(struct list
*funclist
, struct ospf_lsa
*lsa
)
964 struct listnode
*node
, *nnode
;
965 struct ospf_opaque_functab
*functab
;
968 /* This function handles ALL types of LSAs, not only opaque ones. */
969 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
970 if (functab
->del_lsa_hook
!= NULL
)
971 if ((*functab
->del_lsa_hook
)(lsa
) != 0)
978 /*------------------------------------------------------------------------*
979 * Followings are glue functions to call Opaque-LSA specific processing.
980 *------------------------------------------------------------------------*/
982 int ospf_opaque_new_if(struct interface
*ifp
)
984 struct list
*funclist
;
987 funclist
= ospf_opaque_wildcard_funclist
;
988 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
991 funclist
= ospf_opaque_type9_funclist
;
992 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
995 funclist
= ospf_opaque_type10_funclist
;
996 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
999 funclist
= ospf_opaque_type11_funclist
;
1000 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
1008 int ospf_opaque_del_if(struct interface
*ifp
)
1010 struct list
*funclist
;
1013 funclist
= ospf_opaque_wildcard_funclist
;
1014 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1017 funclist
= ospf_opaque_type9_funclist
;
1018 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1021 funclist
= ospf_opaque_type10_funclist
;
1022 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1025 funclist
= ospf_opaque_type11_funclist
;
1026 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1034 void ospf_opaque_ism_change(struct ospf_interface
*oi
, int old_status
)
1036 struct list
*funclist
;
1038 funclist
= ospf_opaque_wildcard_funclist
;
1039 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1041 funclist
= ospf_opaque_type9_funclist
;
1042 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1044 funclist
= ospf_opaque_type10_funclist
;
1045 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1047 funclist
= ospf_opaque_type11_funclist
;
1048 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1053 void ospf_opaque_nsm_change(struct ospf_neighbor
*nbr
, int old_state
)
1056 struct list
*funclist
;
1058 if ((top
= oi_to_top(nbr
->oi
)) == NULL
)
1061 if (old_state
!= NSM_Full
&& nbr
->state
== NSM_Full
) {
1062 if (CHECK_FLAG(nbr
->options
, OSPF_OPTION_O
)) {
1063 if (!CHECK_FLAG(top
->opaque
,
1064 OPAQUE_OPERATION_READY_BIT
)) {
1065 if (IS_DEBUG_OSPF_EVENT
)
1067 "Opaque-LSA: Now get operational!");
1069 SET_FLAG(top
->opaque
,
1070 OPAQUE_OPERATION_READY_BIT
);
1073 ospf_opaque_lsa_originate_schedule(nbr
->oi
, NULL
);
1075 } else if (old_state
== NSM_Full
&& nbr
->state
!= NSM_Full
) {
1078 * If no more opaque-capable full-state neighbor remains in the
1079 * flooding scope which corresponds to Opaque-LSA type, periodic
1080 * LS flooding should be stopped.
1086 funclist
= ospf_opaque_wildcard_funclist
;
1087 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1089 funclist
= ospf_opaque_type9_funclist
;
1090 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1092 funclist
= ospf_opaque_type10_funclist
;
1093 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1095 funclist
= ospf_opaque_type11_funclist
;
1096 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1102 void ospf_opaque_config_write_router(struct vty
*vty
, struct ospf
*ospf
)
1104 struct list
*funclist
;
1106 if (CHECK_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
))
1107 vty_out(vty
, " capability opaque\n");
1109 funclist
= ospf_opaque_wildcard_funclist
;
1110 opaque_lsa_config_write_router_callback(funclist
, vty
);
1112 funclist
= ospf_opaque_type9_funclist
;
1113 opaque_lsa_config_write_router_callback(funclist
, vty
);
1115 funclist
= ospf_opaque_type10_funclist
;
1116 opaque_lsa_config_write_router_callback(funclist
, vty
);
1118 funclist
= ospf_opaque_type11_funclist
;
1119 opaque_lsa_config_write_router_callback(funclist
, vty
);
1124 void ospf_opaque_config_write_if(struct vty
*vty
, struct interface
*ifp
)
1126 struct list
*funclist
;
1128 funclist
= ospf_opaque_wildcard_funclist
;
1129 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1131 funclist
= ospf_opaque_type9_funclist
;
1132 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1134 funclist
= ospf_opaque_type10_funclist
;
1135 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1137 funclist
= ospf_opaque_type11_funclist
;
1138 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1143 void ospf_opaque_config_write_debug(struct vty
*vty
)
1145 struct list
*funclist
;
1147 funclist
= ospf_opaque_wildcard_funclist
;
1148 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1150 funclist
= ospf_opaque_type9_funclist
;
1151 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1153 funclist
= ospf_opaque_type10_funclist
;
1154 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1156 funclist
= ospf_opaque_type11_funclist
;
1157 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1162 void show_opaque_info_detail(struct vty
*vty
, struct ospf_lsa
*lsa
)
1164 struct lsa_header
*lsah
= (struct lsa_header
*)lsa
->data
;
1165 uint32_t lsid
= ntohl(lsah
->id
.s_addr
);
1166 uint8_t opaque_type
= GET_OPAQUE_TYPE(lsid
);
1167 uint32_t opaque_id
= GET_OPAQUE_ID(lsid
);
1168 struct ospf_opaque_functab
*functab
;
1170 /* Switch output functionality by vty address. */
1172 vty_out(vty
, " Opaque-Type %u (%s)\n", opaque_type
,
1173 ospf_opaque_type_name(opaque_type
));
1174 vty_out(vty
, " Opaque-ID 0x%x\n", opaque_id
);
1176 vty_out(vty
, " Opaque-Info: %u octets of data%s\n",
1177 ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
,
1178 VALID_OPAQUE_INFO_LEN(lsah
) ? "" : "(Invalid length?)");
1180 zlog_debug(" Opaque-Type %u (%s)", opaque_type
,
1181 ospf_opaque_type_name(opaque_type
));
1182 zlog_debug(" Opaque-ID 0x%x", opaque_id
);
1184 zlog_debug(" Opaque-Info: %u octets of data%s",
1185 ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
,
1186 VALID_OPAQUE_INFO_LEN(lsah
) ? ""
1187 : "(Invalid length?)");
1190 /* Call individual output functions. */
1191 if ((functab
= ospf_opaque_functab_lookup(lsa
)) != NULL
)
1192 if (functab
->show_opaque_info
!= NULL
)
1193 (*functab
->show_opaque_info
)(vty
, lsa
);
1198 void ospf_opaque_lsa_dump(struct stream
*s
, uint16_t length
)
1200 struct ospf_lsa lsa
;
1202 lsa
.data
= (struct lsa_header
*)stream_pnt(s
);
1203 show_opaque_info_detail(NULL
, &lsa
);
1207 static int ospf_opaque_lsa_install_hook(struct ospf_lsa
*lsa
)
1209 struct list
*funclist
;
1213 * Some Opaque-LSA user may want to monitor every LSA installation
1214 * into the LSDB, regardless with target LSA type.
1216 funclist
= ospf_opaque_wildcard_funclist
;
1217 if (new_lsa_callback(funclist
, lsa
) != 0)
1220 funclist
= ospf_opaque_type9_funclist
;
1221 if (new_lsa_callback(funclist
, lsa
) != 0)
1224 funclist
= ospf_opaque_type10_funclist
;
1225 if (new_lsa_callback(funclist
, lsa
) != 0)
1228 funclist
= ospf_opaque_type11_funclist
;
1229 if (new_lsa_callback(funclist
, lsa
) != 0)
1237 static int ospf_opaque_lsa_delete_hook(struct ospf_lsa
*lsa
)
1239 struct list
*funclist
;
1243 * Some Opaque-LSA user may want to monitor every LSA deletion
1244 * from the LSDB, regardless with target LSA type.
1246 funclist
= ospf_opaque_wildcard_funclist
;
1247 if (del_lsa_callback(funclist
, lsa
) != 0)
1250 funclist
= ospf_opaque_type9_funclist
;
1251 if (del_lsa_callback(funclist
, lsa
) != 0)
1254 funclist
= ospf_opaque_type10_funclist
;
1255 if (del_lsa_callback(funclist
, lsa
) != 0)
1258 funclist
= ospf_opaque_type11_funclist
;
1259 if (del_lsa_callback(funclist
, lsa
) != 0)
1267 /*------------------------------------------------------------------------*
1268 * Followings are Opaque-LSA origination/refresh management functions.
1269 *------------------------------------------------------------------------*/
1271 static int ospf_opaque_type9_lsa_originate(struct thread
*t
);
1272 static int ospf_opaque_type10_lsa_originate(struct thread
*t
);
1273 static int ospf_opaque_type11_lsa_originate(struct thread
*t
);
1274 static void ospf_opaque_lsa_reoriginate_resume(struct list
*listtop
, void *arg
);
1276 void ospf_opaque_lsa_originate_schedule(struct ospf_interface
*oi
, int *delay0
)
1279 struct ospf_area
*area
;
1280 struct listnode
*node
, *nnode
;
1281 struct opaque_info_per_type
*oipt
;
1284 if ((top
= oi_to_top(oi
)) == NULL
|| (area
= oi
->area
) == NULL
) {
1285 if (IS_DEBUG_OSPF_EVENT
)
1287 "ospf_opaque_lsa_originate_schedule: Invalid argument?");
1291 /* It may not a right time to schedule origination now. */
1292 if (!CHECK_FLAG(top
->opaque
, OPAQUE_OPERATION_READY_BIT
)) {
1293 if (IS_DEBUG_OSPF_EVENT
)
1295 "ospf_opaque_lsa_originate_schedule: Not operational.");
1296 return; /* This is not an error. */
1303 * There might be some entries that have been waiting for triggering
1304 * of per opaque-type re-origination get resumed.
1306 ospf_opaque_lsa_reoriginate_resume(oi
->opaque_lsa_self
, (void *)oi
);
1307 ospf_opaque_lsa_reoriginate_resume(area
->opaque_lsa_self
, (void *)area
);
1308 ospf_opaque_lsa_reoriginate_resume(top
->opaque_lsa_self
, (void *)top
);
1311 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1313 if (!list_isempty(ospf_opaque_type9_funclist
)
1314 && list_isempty(oi
->opaque_lsa_self
)
1315 && oi
->t_opaque_lsa_self
== NULL
) {
1316 if (IS_DEBUG_OSPF_EVENT
)
1318 "Schedule Type-9 Opaque-LSA origination in %d ms later.",
1320 oi
->t_opaque_lsa_self
= NULL
;
1321 thread_add_timer_msec(master
, ospf_opaque_type9_lsa_originate
,
1322 oi
, delay
, &oi
->t_opaque_lsa_self
);
1323 delay
+= top
->min_ls_interval
;
1326 if (!list_isempty(ospf_opaque_type10_funclist
)
1327 && list_isempty(area
->opaque_lsa_self
)
1328 && area
->t_opaque_lsa_self
== NULL
) {
1330 * One AREA may contain multiple OIs, but above 2nd and 3rd
1331 * conditions prevent from scheduling the originate function
1334 if (IS_DEBUG_OSPF_EVENT
)
1336 "Schedule Type-10 Opaque-LSA origination in %d ms later.",
1338 area
->t_opaque_lsa_self
= NULL
;
1339 thread_add_timer_msec(master
, ospf_opaque_type10_lsa_originate
,
1340 area
, delay
, &area
->t_opaque_lsa_self
);
1341 delay
+= top
->min_ls_interval
;
1344 if (!list_isempty(ospf_opaque_type11_funclist
)
1345 && list_isempty(top
->opaque_lsa_self
)
1346 && top
->t_opaque_lsa_self
== NULL
) {
1348 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1349 * conditions prevent from scheduling the originate function
1352 if (IS_DEBUG_OSPF_EVENT
)
1354 "Schedule Type-11 Opaque-LSA origination in %d ms later.",
1356 top
->t_opaque_lsa_self
= NULL
;
1357 thread_add_timer_msec(master
, ospf_opaque_type11_lsa_originate
,
1358 top
, delay
, &top
->t_opaque_lsa_self
);
1359 delay
+= top
->min_ls_interval
;
1363 * Following section treats a special situation that this node's
1364 * opaque capability has changed as "ON -> OFF -> ON".
1366 if (!list_isempty(ospf_opaque_type9_funclist
)
1367 && !list_isempty(oi
->opaque_lsa_self
)) {
1368 for (ALL_LIST_ELEMENTS(oi
->opaque_lsa_self
, node
, nnode
,
1371 * removed the test for
1372 * (! list_isempty (oipt->id_list)) * Handler is
1374 * because opaque cababilities ON -> OFF -> ON result in
1375 * list_isempty (oipt->id_list)
1378 if (oipt
->t_opaque_lsa_self
1379 != NULL
/* Waiting for a thread call. */
1380 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1385 ospf_opaque_lsa_reoriginate_schedule(
1386 (void *)oi
, OSPF_OPAQUE_LINK_LSA
,
1391 if (!list_isempty(ospf_opaque_type10_funclist
)
1392 && !list_isempty(area
->opaque_lsa_self
)) {
1393 for (ALL_LIST_ELEMENTS(area
->opaque_lsa_self
, node
, nnode
,
1396 * removed the test for
1397 * (! list_isempty (oipt->id_list)) * Handler is
1399 * because opaque cababilities ON -> OFF -> ON result in
1400 * list_isempty (oipt->id_list)
1403 if (oipt
->t_opaque_lsa_self
1404 != NULL
/* Waiting for a thread call. */
1405 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1410 ospf_opaque_lsa_reoriginate_schedule(
1411 (void *)area
, OSPF_OPAQUE_AREA_LSA
,
1416 if (!list_isempty(ospf_opaque_type11_funclist
)
1417 && !list_isempty(top
->opaque_lsa_self
)) {
1418 for (ALL_LIST_ELEMENTS(top
->opaque_lsa_self
, node
, nnode
,
1421 * removed the test for
1422 * (! list_isempty (oipt->id_list)) * Handler is
1424 * because opaque cababilities ON -> OFF -> ON result in
1425 * list_isempty (oipt->id_list)
1428 if (oipt
->t_opaque_lsa_self
1429 != NULL
/* Waiting for a thread call. */
1430 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1435 ospf_opaque_lsa_reoriginate_schedule((void *)top
,
1445 static int ospf_opaque_type9_lsa_originate(struct thread
*t
)
1447 struct ospf_interface
*oi
;
1451 oi
->t_opaque_lsa_self
= NULL
;
1453 if (IS_DEBUG_OSPF_EVENT
)
1454 zlog_debug("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
1457 rc
= opaque_lsa_originate_callback(ospf_opaque_type9_funclist
, oi
);
1462 static int ospf_opaque_type10_lsa_originate(struct thread
*t
)
1464 struct ospf_area
*area
;
1467 area
= THREAD_ARG(t
);
1468 area
->t_opaque_lsa_self
= NULL
;
1470 if (IS_DEBUG_OSPF_EVENT
)
1472 "Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
1473 inet_ntoa(area
->area_id
));
1475 rc
= opaque_lsa_originate_callback(ospf_opaque_type10_funclist
, area
);
1480 static int ospf_opaque_type11_lsa_originate(struct thread
*t
)
1485 top
= THREAD_ARG(t
);
1486 top
->t_opaque_lsa_self
= NULL
;
1488 if (IS_DEBUG_OSPF_EVENT
)
1490 "Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
1492 rc
= opaque_lsa_originate_callback(ospf_opaque_type11_funclist
, top
);
1497 static void ospf_opaque_lsa_reoriginate_resume(struct list
*listtop
, void *arg
)
1499 struct listnode
*node
, *nnode
;
1500 struct opaque_info_per_type
*oipt
;
1501 struct ospf_opaque_functab
*functab
;
1503 if (listtop
== NULL
)
1507 * Pickup oipt entries those which in SUSPEND status, and give
1508 * them a chance to start re-origination now.
1510 for (ALL_LIST_ELEMENTS(listtop
, node
, nnode
, oipt
)) {
1511 if (oipt
->status
!= PROC_SUSPEND
)
1514 oipt
->status
= PROC_NORMAL
;
1516 if ((functab
= oipt
->functab
) == NULL
1517 || functab
->lsa_originator
== NULL
)
1520 if ((*functab
->lsa_originator
)(arg
) != 0) {
1523 "ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)",
1533 struct ospf_lsa
*ospf_opaque_lsa_install(struct ospf_lsa
*lsa
, int rt_recalc
)
1535 struct ospf_lsa
*new = NULL
;
1536 struct opaque_info_per_type
*oipt
;
1537 struct opaque_info_per_id
*oipi
;
1540 /* Don't take "rt_recalc" into consideration for now. */ /* XXX */
1542 if (!IS_LSA_SELF(lsa
)) {
1543 new = lsa
; /* Don't touch this LSA. */
1547 if (IS_DEBUG_OSPF(lsa
, LSA_INSTALL
))
1549 "Install Type-%u Opaque-LSA: [opaque-type=%u, opaque-id=%x]",
1551 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
1552 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
1554 /* Replace the existing lsa with the new one. */
1555 if ((oipt
= lookup_opaque_info_by_type(lsa
)) != NULL
1556 && (oipi
= lookup_opaque_info_by_id(oipt
, lsa
)) != NULL
) {
1557 ospf_lsa_unlock(&oipi
->lsa
);
1558 oipi
->lsa
= ospf_lsa_lock(lsa
);
1560 /* Register the new lsa entry and get its control info. */
1561 else if ((oipi
= register_opaque_lsa(lsa
)) == NULL
) {
1562 flog_warn(EC_OSPF_LSA
,
1563 "ospf_opaque_lsa_install: register_opaque_lsa() ?");
1568 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1569 * for periodic refresh of self-originated Opaque-LSAs.
1571 switch (lsa
->data
->type
) {
1572 case OSPF_OPAQUE_LINK_LSA
:
1573 if ((top
= oi_to_top(lsa
->oi
)) == NULL
) {
1574 /* Above conditions must have passed. */
1575 flog_warn(EC_OSPF_LSA
,
1576 "ospf_opaque_lsa_install: Something wrong?");
1580 case OSPF_OPAQUE_AREA_LSA
:
1581 if (lsa
->area
== NULL
|| (top
= lsa
->area
->ospf
) == NULL
) {
1582 /* Above conditions must have passed. */
1583 flog_warn(EC_OSPF_LSA
,
1584 "ospf_opaque_lsa_install: Something wrong?");
1588 case OSPF_OPAQUE_AS_LSA
:
1589 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
1590 if (lsa
->area
!= NULL
&& (top
= lsa
->area
->ospf
) == NULL
) {
1591 /* Above conditions must have passed. */
1592 flog_warn(EC_OSPF_LSA
,
1593 "ospf_opaque_lsa_install: Something wrong?");
1598 flog_warn(EC_OSPF_LSA_UNEXPECTED
,
1599 "ospf_opaque_lsa_install: Unexpected LSA-type(%u)",
1604 ospf_refresher_register_lsa(top
, lsa
);
1611 struct ospf_lsa
*ospf_opaque_lsa_refresh(struct ospf_lsa
*lsa
)
1614 struct ospf_opaque_functab
*functab
;
1615 struct ospf_lsa
*new = NULL
;
1617 ospf
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
1619 if ((functab
= ospf_opaque_functab_lookup(lsa
)) == NULL
1620 || functab
->lsa_refresher
== NULL
) {
1622 * Though this LSA seems to have originated on this node, the
1623 * handling module for this "lsa-type and opaque-type" was
1624 * already deleted sometime ago.
1625 * Anyway, this node still has a responsibility to flush this
1626 * LSA from the routing domain.
1628 if (IS_DEBUG_OSPF_EVENT
)
1629 zlog_debug("LSA[Type%d:%s]: Flush stray Opaque-LSA",
1630 lsa
->data
->type
, inet_ntoa(lsa
->data
->id
));
1632 lsa
->data
->ls_age
= htons(OSPF_LSA_MAXAGE
);
1633 ospf_lsa_flush(ospf
, lsa
);
1635 new = (*functab
->lsa_refresher
)(lsa
);
1640 /*------------------------------------------------------------------------*
1641 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1642 * triggered by external interventions (vty session, signaling, etc).
1643 *------------------------------------------------------------------------*/
1645 #define OSPF_OPAQUE_TIMER_ON(T,F,L,V) thread_add_timer_msec (master, (F), (L), (V), &(T))
1647 static struct ospf_lsa
*pseudo_lsa(struct ospf_interface
*oi
,
1648 struct ospf_area
*area
, uint8_t lsa_type
,
1649 uint8_t opaque_type
);
1650 static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread
*t
);
1651 static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread
*t
);
1652 static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread
*t
);
1653 static int ospf_opaque_lsa_refresh_timer(struct thread
*t
);
1655 void ospf_opaque_lsa_reoriginate_schedule(void *lsa_type_dependent
,
1656 uint8_t lsa_type
, uint8_t opaque_type
)
1658 struct ospf
*top
= NULL
;
1659 struct ospf_area dummy
, *area
= NULL
;
1660 struct ospf_interface
*oi
= NULL
;
1662 struct ospf_lsa
*lsa
;
1663 struct opaque_info_per_type
*oipt
;
1664 int (*func
)(struct thread
* t
) = NULL
;
1668 case OSPF_OPAQUE_LINK_LSA
:
1669 if ((oi
= (struct ospf_interface
*)lsa_type_dependent
)
1673 "ospf_opaque_lsa_reoriginate_schedule: Type-9 Opaque-LSA: Invalid parameter?");
1676 if ((top
= oi_to_top(oi
)) == NULL
) {
1679 "ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1683 if (!list_isempty(ospf_opaque_type9_funclist
)
1684 && list_isempty(oi
->opaque_lsa_self
)
1685 && oi
->t_opaque_lsa_self
!= NULL
) {
1688 "Type-9 Opaque-LSA (opaque_type=%u): Common origination for OI(%s) has already started",
1689 opaque_type
, IF_NAME(oi
));
1692 func
= ospf_opaque_type9_lsa_reoriginate_timer
;
1694 case OSPF_OPAQUE_AREA_LSA
:
1695 if ((area
= (struct ospf_area
*)lsa_type_dependent
) == NULL
) {
1698 "ospf_opaque_lsa_reoriginate_schedule: Type-10 Opaque-LSA: Invalid parameter?");
1701 if ((top
= area
->ospf
) == NULL
) {
1704 "ospf_opaque_lsa_reoriginate_schedule: AREA(%s) -> TOP?",
1705 inet_ntoa(area
->area_id
));
1708 if (!list_isempty(ospf_opaque_type10_funclist
)
1709 && list_isempty(area
->opaque_lsa_self
)
1710 && area
->t_opaque_lsa_self
!= NULL
) {
1713 "Type-10 Opaque-LSA (opaque_type=%u): Common origination for AREA(%s) has already started",
1714 opaque_type
, inet_ntoa(area
->area_id
));
1717 func
= ospf_opaque_type10_lsa_reoriginate_timer
;
1719 case OSPF_OPAQUE_AS_LSA
:
1720 if ((top
= (struct ospf
*)lsa_type_dependent
) == NULL
) {
1723 "ospf_opaque_lsa_reoriginate_schedule: Type-11 Opaque-LSA: Invalid parameter?");
1726 if (!list_isempty(ospf_opaque_type11_funclist
)
1727 && list_isempty(top
->opaque_lsa_self
)
1728 && top
->t_opaque_lsa_self
!= NULL
) {
1731 "Type-11 Opaque-LSA (opaque_type=%u): Common origination has already started",
1736 /* Fake "area" to pass "ospf" to a lookup function later. */
1740 func
= ospf_opaque_type11_lsa_reoriginate_timer
;
1744 EC_OSPF_LSA_UNEXPECTED
,
1745 "ospf_opaque_lsa_reoriginate_schedule: Unexpected LSA-type(%u)",
1750 /* It may not a right time to schedule reorigination now. */
1751 if (!CHECK_FLAG(top
->opaque
, OPAQUE_OPERATION_READY_BIT
)) {
1752 if (IS_DEBUG_OSPF_EVENT
)
1754 "ospf_opaque_lsa_reoriginate_schedule: Not operational.");
1755 goto out
; /* This is not an error. */
1758 /* Generate a dummy lsa to be passed for a lookup function. */
1759 lsa
= pseudo_lsa(oi
, area
, lsa_type
, opaque_type
);
1760 lsa
->vrf_id
= top
->vrf_id
;
1762 if ((oipt
= lookup_opaque_info_by_type(lsa
)) == NULL
) {
1763 struct ospf_opaque_functab
*functab
;
1764 if ((functab
= ospf_opaque_functab_lookup(lsa
)) == NULL
) {
1767 "ospf_opaque_lsa_reoriginate_schedule: No associated function?: lsa_type(%u), opaque_type(%u)",
1768 lsa_type
, opaque_type
);
1771 if ((oipt
= register_opaque_info_per_type(functab
, lsa
))
1775 "ospf_opaque_lsa_reoriginate_schedule: Cannot get a control info?: lsa_type(%u), opaque_type(%u)",
1776 lsa_type
, opaque_type
);
1781 if (oipt
->t_opaque_lsa_self
!= NULL
) {
1782 if (IS_DEBUG_OSPF_EVENT
)
1784 "Type-%u Opaque-LSA has already scheduled to"
1785 " RE-ORIGINATE: [opaque-type=%u]",
1787 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)));
1792 * Different from initial origination time, in which various conditions
1793 * (opaque capability, neighbor status etc) are assured by caller of
1794 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1795 * it is highly possible that these conditions might not be satisfied
1796 * at the time of re-origination function is to be called.
1798 delay
= top
->min_ls_interval
; /* XXX */
1800 if (IS_DEBUG_OSPF_EVENT
)
1802 "Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
1803 " ms later: [opaque-type=%u]",
1805 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)));
1807 OSPF_OPAQUE_TIMER_ON(oipt
->t_opaque_lsa_self
, func
, oipt
, delay
);
1813 static struct ospf_lsa
*pseudo_lsa(struct ospf_interface
*oi
,
1814 struct ospf_area
*area
, uint8_t lsa_type
,
1815 uint8_t opaque_type
)
1817 static struct ospf_lsa lsa
= {0};
1818 static struct lsa_header lsah
= {0};
1824 lsa
.vrf_id
= VRF_DEFAULT
;
1826 lsah
.type
= lsa_type
;
1827 tmp
= SET_OPAQUE_LSID(opaque_type
, 0); /* Opaque-ID is unused here. */
1828 lsah
.id
.s_addr
= htonl(tmp
);
1833 static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread
*t
)
1835 struct opaque_info_per_type
*oipt
;
1836 struct ospf_opaque_functab
*functab
;
1838 struct ospf_interface
*oi
;
1841 oipt
= THREAD_ARG(t
);
1842 oipt
->t_opaque_lsa_self
= NULL
;
1844 if ((functab
= oipt
->functab
) == NULL
1845 || functab
->lsa_originator
== NULL
) {
1848 "ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1852 oi
= (struct ospf_interface
*)oipt
->owner
;
1853 if ((top
= oi_to_top(oi
)) == NULL
) {
1856 "ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1860 if (!CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)
1861 || !ospf_if_is_enable(oi
)
1862 || ospf_nbr_count_opaque_capable(oi
) == 0) {
1863 if (IS_DEBUG_OSPF_EVENT
)
1865 "Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...",
1868 oipt
->status
= PROC_SUSPEND
;
1873 if (IS_DEBUG_OSPF_EVENT
)
1875 "Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)",
1876 oipt
->opaque_type
, IF_NAME(oi
));
1878 rc
= (*functab
->lsa_originator
)(oi
);
1883 static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread
*t
)
1885 struct opaque_info_per_type
*oipt
;
1886 struct ospf_opaque_functab
*functab
;
1887 struct listnode
*node
, *nnode
;
1889 struct ospf_area
*area
;
1890 struct ospf_interface
*oi
;
1893 oipt
= THREAD_ARG(t
);
1894 oipt
->t_opaque_lsa_self
= NULL
;
1896 if ((functab
= oipt
->functab
) == NULL
1897 || functab
->lsa_originator
== NULL
) {
1900 "ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1904 area
= (struct ospf_area
*)oipt
->owner
;
1905 if (area
== NULL
|| (top
= area
->ospf
) == NULL
) {
1908 "ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1912 /* There must be at least one "opaque-capable, full-state" neighbor. */
1914 for (ALL_LIST_ELEMENTS(area
->oiflist
, node
, nnode
, oi
)) {
1915 if ((n
= ospf_nbr_count_opaque_capable(oi
)) > 0)
1919 if (n
== 0 || !CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)) {
1920 if (IS_DEBUG_OSPF_EVENT
)
1922 "Suspend re-origination of Type-10 Opaque-LSAs"
1923 " (opaque-type=%u) for a while...",
1926 oipt
->status
= PROC_SUSPEND
;
1931 if (IS_DEBUG_OSPF_EVENT
)
1933 "Timer[Type10-LSA]: Re-originate Opaque-LSAs"
1934 " (opaque-type=%u) for Area %s",
1935 oipt
->opaque_type
, inet_ntoa(area
->area_id
));
1937 rc
= (*functab
->lsa_originator
)(area
);
1942 static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread
*t
)
1944 struct opaque_info_per_type
*oipt
;
1945 struct ospf_opaque_functab
*functab
;
1949 oipt
= THREAD_ARG(t
);
1950 oipt
->t_opaque_lsa_self
= NULL
;
1952 if ((functab
= oipt
->functab
) == NULL
1953 || functab
->lsa_originator
== NULL
) {
1956 "ospf_opaque_type11_lsa_reoriginate_timer: No associated function?");
1960 if ((top
= (struct ospf
*)oipt
->owner
) == NULL
) {
1963 "ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1967 if (!CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)) {
1968 if (IS_DEBUG_OSPF_EVENT
)
1970 "Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...",
1973 oipt
->status
= PROC_SUSPEND
;
1978 if (IS_DEBUG_OSPF_EVENT
)
1980 "Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).",
1983 rc
= (*functab
->lsa_originator
)(top
);
1988 void ospf_opaque_lsa_refresh_schedule(struct ospf_lsa
*lsa0
)
1990 struct opaque_info_per_type
*oipt
;
1991 struct opaque_info_per_id
*oipi
;
1992 struct ospf_lsa
*lsa
;
1996 if ((oipt
= lookup_opaque_info_by_type(lsa0
)) == NULL
1997 || (oipi
= lookup_opaque_info_by_id(oipt
, lsa0
)) == NULL
) {
2000 "ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
2004 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2005 if ((lsa
= oipi
->lsa
) == NULL
) {
2006 flog_warn(EC_OSPF_LSA
,
2007 "ospf_opaque_lsa_refresh_schedule: Something wrong?");
2011 if (oipi
->t_opaque_lsa_self
!= NULL
) {
2012 if (IS_DEBUG_OSPF_EVENT
)
2014 "Type-%u Opaque-LSA has already scheduled to REFRESH: [opaque-type=%u, opaque-id=%x]",
2016 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
2017 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
2021 /* Delete this lsa from neighbor retransmit-list. */
2022 switch (lsa
->data
->type
) {
2023 case OSPF_OPAQUE_LINK_LSA
:
2024 case OSPF_OPAQUE_AREA_LSA
:
2025 ospf_ls_retransmit_delete_nbr_area(lsa
->area
, lsa
);
2027 case OSPF_OPAQUE_AS_LSA
:
2028 top
= ospf_lookup_by_vrf_id(lsa0
->vrf_id
);
2029 if ((lsa0
->area
!= NULL
) && (lsa0
->area
->ospf
!= NULL
))
2030 top
= lsa0
->area
->ospf
;
2031 ospf_ls_retransmit_delete_nbr_as(top
, lsa
);
2035 EC_OSPF_LSA_UNEXPECTED
,
2036 "ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)",
2041 delay
= ospf_lsa_refresh_delay(lsa
);
2043 if (IS_DEBUG_OSPF_EVENT
)
2045 "Schedule Type-%u Opaque-LSA to REFRESH in %d sec later: [opaque-type=%u, opaque-id=%x]",
2046 lsa
->data
->type
, delay
,
2047 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
2048 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
2050 OSPF_OPAQUE_TIMER_ON(oipi
->t_opaque_lsa_self
,
2051 ospf_opaque_lsa_refresh_timer
, oipi
, delay
* 1000);
2056 static int ospf_opaque_lsa_refresh_timer(struct thread
*t
)
2058 struct opaque_info_per_id
*oipi
;
2059 struct ospf_opaque_functab
*functab
;
2060 struct ospf_lsa
*lsa
;
2062 if (IS_DEBUG_OSPF_EVENT
)
2063 zlog_debug("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
2065 oipi
= THREAD_ARG(t
);
2066 oipi
->t_opaque_lsa_self
= NULL
;
2068 if ((lsa
= oipi
->lsa
) != NULL
)
2069 if ((functab
= oipi
->opqctl_type
->functab
) != NULL
)
2070 if (functab
->lsa_refresher
!= NULL
)
2071 (*functab
->lsa_refresher
)(lsa
);
2076 void ospf_opaque_lsa_flush_schedule(struct ospf_lsa
*lsa0
)
2078 struct opaque_info_per_type
*oipt
;
2079 struct opaque_info_per_id
*oipi
;
2080 struct ospf_lsa
*lsa
;
2083 top
= ospf_lookup_by_vrf_id(lsa0
->vrf_id
);
2085 if ((oipt
= lookup_opaque_info_by_type(lsa0
)) == NULL
2086 || (oipi
= lookup_opaque_info_by_id(oipt
, lsa0
)) == NULL
) {
2087 flog_warn(EC_OSPF_LSA
,
2088 "ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2092 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2093 if ((lsa
= oipi
->lsa
) == NULL
) {
2094 flog_warn(EC_OSPF_LSA
,
2095 "ospf_opaque_lsa_flush_schedule: Something wrong?");
2099 /* Delete this lsa from neighbor retransmit-list. */
2100 switch (lsa
->data
->type
) {
2101 case OSPF_OPAQUE_LINK_LSA
:
2102 case OSPF_OPAQUE_AREA_LSA
:
2103 ospf_ls_retransmit_delete_nbr_area(lsa
->area
, lsa
);
2105 case OSPF_OPAQUE_AS_LSA
:
2106 if ((lsa0
->area
!= NULL
) && (lsa0
->area
->ospf
!= NULL
))
2107 top
= lsa0
->area
->ospf
;
2108 ospf_ls_retransmit_delete_nbr_as(top
, lsa
);
2112 EC_OSPF_LSA_UNEXPECTED
,
2113 "ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)",
2118 /* Dequeue listnode entry from the list. */
2119 listnode_delete(oipt
->id_list
, oipi
);
2121 /* Disassociate internal control information with the given lsa. */
2122 free_opaque_info_per_id((void *)oipi
);
2124 /* Force given lsa's age to MaxAge. */
2125 lsa
->data
->ls_age
= htons(OSPF_LSA_MAXAGE
);
2127 if (IS_DEBUG_OSPF_EVENT
)
2129 "Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]",
2131 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
2132 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
2134 /* This lsa will be flushed and removed eventually. */
2135 ospf_lsa_flush(top
, lsa
);
2141 void ospf_opaque_self_originated_lsa_received(struct ospf_neighbor
*nbr
,
2142 struct ospf_lsa
*lsa
)
2146 if ((top
= oi_to_top(nbr
->oi
)) == NULL
)
2150 * Since these LSA entries are not yet installed into corresponding
2151 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2153 lsa
->data
->ls_age
= htons(OSPF_LSA_MAXAGE
);
2154 switch (lsa
->data
->type
) {
2155 case OSPF_OPAQUE_LINK_LSA
:
2156 ospf_flood_through_area(nbr
->oi
->area
, NULL
/*inbr*/, lsa
);
2158 case OSPF_OPAQUE_AREA_LSA
:
2159 ospf_flood_through_area(nbr
->oi
->area
, NULL
/*inbr*/, lsa
);
2161 case OSPF_OPAQUE_AS_LSA
:
2162 ospf_flood_through_as(top
, NULL
/*inbr*/, lsa
);
2166 EC_OSPF_LSA_UNEXPECTED
,
2167 "ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)",
2171 ospf_lsa_discard(lsa
); /* List "lsas" will be deleted by caller. */
2174 /*------------------------------------------------------------------------*
2175 * Followings are util functions; probably be used by Opaque-LSAs only...
2176 *------------------------------------------------------------------------*/
2178 struct ospf
*oi_to_top(struct ospf_interface
*oi
)
2180 struct ospf
*top
= NULL
;
2181 struct ospf_area
*area
;
2183 if (oi
== NULL
|| (area
= oi
->area
) == NULL
2184 || (top
= area
->ospf
) == NULL
)
2185 flog_warn(EC_OSPF_LSA
,
2186 "Broken relationship for \"OI -> AREA -> OSPF\"?");