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 * Following 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_del(void *val
);
78 static void free_opaque_info_per_id(void *val
);
79 static int ospf_opaque_lsa_install_hook(struct ospf_lsa
*lsa
);
80 static int ospf_opaque_lsa_delete_hook(struct ospf_lsa
*lsa
);
82 void ospf_opaque_init(void)
84 ospf_opaque_register_vty();
85 ospf_opaque_funclist_init();
87 if (ospf_mpls_te_init() != 0)
90 /* Segment Routing init */
91 if (ospf_sr_init() != 0)
94 if (ospf_router_info_init() != 0)
97 if (ospf_ext_init() != 0)
100 #ifdef SUPPORT_OSPF_API
101 if ((ospf_apiserver_enable
) && (ospf_apiserver_init() != 0))
103 #endif /* SUPPORT_OSPF_API */
108 void ospf_opaque_term(void)
112 ospf_router_info_term();
118 #ifdef SUPPORT_OSPF_API
119 ospf_apiserver_term();
120 #endif /* SUPPORT_OSPF_API */
122 ospf_opaque_funclist_term();
126 void ospf_opaque_finish(void)
128 ospf_mpls_te_finish();
130 ospf_router_info_finish();
137 int ospf_opaque_type9_lsa_init(struct ospf_interface
*oi
)
139 if (oi
->opaque_lsa_self
!= NULL
)
140 list_delete(&oi
->opaque_lsa_self
);
142 oi
->opaque_lsa_self
= list_new();
143 oi
->opaque_lsa_self
->del
= free_opaque_info_per_type_del
;
144 oi
->t_opaque_lsa_self
= NULL
;
148 void ospf_opaque_type9_lsa_term(struct ospf_interface
*oi
)
150 THREAD_OFF(oi
->t_opaque_lsa_self
);
151 if (oi
->opaque_lsa_self
!= NULL
)
152 list_delete(&oi
->opaque_lsa_self
);
153 oi
->opaque_lsa_self
= NULL
;
157 int ospf_opaque_type10_lsa_init(struct ospf_area
*area
)
159 if (area
->opaque_lsa_self
!= NULL
)
160 list_delete(&area
->opaque_lsa_self
);
162 area
->opaque_lsa_self
= list_new();
163 area
->opaque_lsa_self
->del
= free_opaque_info_per_type_del
;
164 area
->t_opaque_lsa_self
= NULL
;
166 #ifdef MONITOR_LSDB_CHANGE
167 area
->lsdb
->new_lsa_hook
= ospf_opaque_lsa_install_hook
;
168 area
->lsdb
->del_lsa_hook
= ospf_opaque_lsa_delete_hook
;
169 #endif /* MONITOR_LSDB_CHANGE */
173 void ospf_opaque_type10_lsa_term(struct ospf_area
*area
)
175 #ifdef MONITOR_LSDB_CHANGE
176 area
->lsdb
->new_lsa_hook
= area
->lsdb
->del_lsa_hook
= NULL
;
177 #endif /* MONITOR_LSDB_CHANGE */
179 THREAD_OFF(area
->t_opaque_lsa_self
);
180 if (area
->opaque_lsa_self
!= NULL
)
181 list_delete(&area
->opaque_lsa_self
);
185 int ospf_opaque_type11_lsa_init(struct ospf
*top
)
187 if (top
->opaque_lsa_self
!= NULL
)
188 list_delete(&top
->opaque_lsa_self
);
190 top
->opaque_lsa_self
= list_new();
191 top
->opaque_lsa_self
->del
= free_opaque_info_per_type_del
;
192 top
->t_opaque_lsa_self
= NULL
;
194 #ifdef MONITOR_LSDB_CHANGE
195 top
->lsdb
->new_lsa_hook
= ospf_opaque_lsa_install_hook
;
196 top
->lsdb
->del_lsa_hook
= ospf_opaque_lsa_delete_hook
;
197 #endif /* MONITOR_LSDB_CHANGE */
201 void ospf_opaque_type11_lsa_term(struct ospf
*top
)
203 #ifdef MONITOR_LSDB_CHANGE
204 top
->lsdb
->new_lsa_hook
= top
->lsdb
->del_lsa_hook
= NULL
;
205 #endif /* MONITOR_LSDB_CHANGE */
207 THREAD_OFF(top
->t_opaque_lsa_self
);
208 if (top
->opaque_lsa_self
!= NULL
)
209 list_delete(&top
->opaque_lsa_self
);
213 static const char *ospf_opaque_type_name(uint8_t opaque_type
)
215 const char *name
= "Unknown";
217 switch (opaque_type
) {
218 case OPAQUE_TYPE_WILDCARD
: /* This is a special assignment! */
221 case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA
:
222 name
= "Traffic Engineering LSA";
224 case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC
:
225 name
= "Sycamore optical topology description";
227 case OPAQUE_TYPE_GRACE_LSA
:
230 case OPAQUE_TYPE_INTER_AS_LSA
:
231 name
= "Inter-AS TE-v2 LSA";
233 case OPAQUE_TYPE_ROUTER_INFORMATION_LSA
:
234 name
= "Router Information LSA";
236 case OPAQUE_TYPE_EXTENDED_PREFIX_LSA
:
237 name
= "Extended Prefix Opaque LSA";
239 case OPAQUE_TYPE_EXTENDED_LINK_LSA
:
240 name
= "Extended Link Opaque LSA";
243 if (OPAQUE_TYPE_RANGE_UNASSIGNED(opaque_type
))
246 uint32_t bigger_range
= opaque_type
;
248 * Get around type-limits warning: comparison is always
249 * true due to limited range of data type
251 if (OPAQUE_TYPE_RANGE_RESERVED(bigger_range
))
252 name
= "Private/Experimental";
259 /*------------------------------------------------------------------------*
260 * Following are management functions to store user specified callbacks.
261 *------------------------------------------------------------------------*/
263 struct opaque_info_per_type
; /* Forward declaration. */
265 static void free_opaque_info_per_type(struct opaque_info_per_type
*oipt
,
268 struct ospf_opaque_functab
{
270 struct opaque_info_per_type
*oipt
;
272 int (*new_if_hook
)(struct interface
*ifp
);
273 int (*del_if_hook
)(struct interface
*ifp
);
274 void (*ism_change_hook
)(struct ospf_interface
*oi
, int old_status
);
275 void (*nsm_change_hook
)(struct ospf_neighbor
*nbr
, int old_status
);
276 void (*config_write_router
)(struct vty
*vty
);
277 void (*config_write_if
)(struct vty
*vty
, struct interface
*ifp
);
278 void (*config_write_debug
)(struct vty
*vty
);
279 void (*show_opaque_info
)(struct vty
*vty
, struct json_object
*json
,
280 struct ospf_lsa
*lsa
);
281 int (*lsa_originator
)(void *arg
);
282 struct ospf_lsa
*(*lsa_refresher
)(struct ospf_lsa
*lsa
);
283 int (*new_lsa_hook
)(struct ospf_lsa
*lsa
);
284 int (*del_lsa_hook
)(struct ospf_lsa
*lsa
);
287 /* Handle LSA-9/10/11 altogether. */
288 static struct list
*ospf_opaque_wildcard_funclist
;
289 static struct list
*ospf_opaque_type9_funclist
;
290 static struct list
*ospf_opaque_type10_funclist
;
291 static struct list
*ospf_opaque_type11_funclist
;
293 static void ospf_opaque_del_functab(void *val
)
295 XFREE(MTYPE_OSPF_OPAQUE_FUNCTAB
, val
);
299 static void ospf_opaque_funclist_init(void)
301 struct list
*funclist
;
303 funclist
= ospf_opaque_wildcard_funclist
= list_new();
304 funclist
->del
= ospf_opaque_del_functab
;
306 funclist
= ospf_opaque_type9_funclist
= list_new();
307 funclist
->del
= ospf_opaque_del_functab
;
309 funclist
= ospf_opaque_type10_funclist
= list_new();
310 funclist
->del
= ospf_opaque_del_functab
;
312 funclist
= ospf_opaque_type11_funclist
= list_new();
313 funclist
->del
= ospf_opaque_del_functab
;
317 static void ospf_opaque_funclist_term(void)
319 struct list
*funclist
;
321 funclist
= ospf_opaque_wildcard_funclist
;
322 list_delete(&funclist
);
324 funclist
= ospf_opaque_type9_funclist
;
325 list_delete(&funclist
);
327 funclist
= ospf_opaque_type10_funclist
;
328 list_delete(&funclist
);
330 funclist
= ospf_opaque_type11_funclist
;
331 list_delete(&funclist
);
335 static struct list
*ospf_get_opaque_funclist(uint8_t lsa_type
)
337 struct list
*funclist
= NULL
;
340 case OPAQUE_TYPE_WILDCARD
:
342 * This is an ugly trick to handle type-9/10/11 LSA altogether.
343 * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor
344 * an officially assigned opaque-type.
345 * Though it is possible that the value might be officially used
346 * in the future, we use it internally as a special label, for
349 funclist
= ospf_opaque_wildcard_funclist
;
351 case OSPF_OPAQUE_LINK_LSA
:
352 funclist
= ospf_opaque_type9_funclist
;
354 case OSPF_OPAQUE_AREA_LSA
:
355 funclist
= ospf_opaque_type10_funclist
;
357 case OSPF_OPAQUE_AS_LSA
:
358 funclist
= ospf_opaque_type11_funclist
;
361 flog_warn(EC_OSPF_LSA_UNEXPECTED
, "%s: Unexpected LSA-type(%u)",
368 /* XXX: such a huge argument list can /not/ be healthy... */
369 int ospf_register_opaque_functab(
370 uint8_t lsa_type
, uint8_t opaque_type
,
371 int (*new_if_hook
)(struct interface
*ifp
),
372 int (*del_if_hook
)(struct interface
*ifp
),
373 void (*ism_change_hook
)(struct ospf_interface
*oi
, int old_status
),
374 void (*nsm_change_hook
)(struct ospf_neighbor
*nbr
, int old_status
),
375 void (*config_write_router
)(struct vty
*vty
),
376 void (*config_write_if
)(struct vty
*vty
, struct interface
*ifp
),
377 void (*config_write_debug
)(struct vty
*vty
),
378 void (*show_opaque_info
)(struct vty
*vty
, struct json_object
*json
,
379 struct ospf_lsa
*lsa
),
380 int (*lsa_originator
)(void *arg
),
381 struct ospf_lsa
*(*lsa_refresher
)(struct ospf_lsa
*lsa
),
382 int (*new_lsa_hook
)(struct ospf_lsa
*lsa
),
383 int (*del_lsa_hook
)(struct ospf_lsa
*lsa
))
385 struct list
*funclist
;
386 struct ospf_opaque_functab
*new;
388 if ((funclist
= ospf_get_opaque_funclist(lsa_type
)) == NULL
)
391 struct listnode
*node
, *nnode
;
392 struct ospf_opaque_functab
*functab
;
394 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
395 if (functab
->opaque_type
== opaque_type
) {
398 "%s: Duplicated entry?: lsa_type(%u), opaque_type(%u)",
399 __func__
, lsa_type
, opaque_type
);
403 new = XCALLOC(MTYPE_OSPF_OPAQUE_FUNCTAB
,
404 sizeof(struct ospf_opaque_functab
));
406 new->opaque_type
= opaque_type
;
408 new->new_if_hook
= new_if_hook
;
409 new->del_if_hook
= del_if_hook
;
410 new->ism_change_hook
= ism_change_hook
;
411 new->nsm_change_hook
= nsm_change_hook
;
412 new->config_write_router
= config_write_router
;
413 new->config_write_if
= config_write_if
;
414 new->config_write_debug
= config_write_debug
;
415 new->show_opaque_info
= show_opaque_info
;
416 new->lsa_originator
= lsa_originator
;
417 new->lsa_refresher
= lsa_refresher
;
418 new->new_lsa_hook
= new_lsa_hook
;
419 new->del_lsa_hook
= del_lsa_hook
;
421 listnode_add(funclist
, new);
426 void ospf_delete_opaque_functab(uint8_t lsa_type
, uint8_t opaque_type
)
428 struct list
*funclist
;
429 struct listnode
*node
, *nnode
;
430 struct ospf_opaque_functab
*functab
;
432 if ((funclist
= ospf_get_opaque_funclist(lsa_type
)) != NULL
)
433 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
)) {
434 if (functab
->opaque_type
== opaque_type
) {
435 /* Cleanup internal control information, if it
437 if (functab
->oipt
!= NULL
)
438 free_opaque_info_per_type(functab
->oipt
,
440 /* Dequeue listnode entry from the list. */
441 listnode_delete(funclist
, functab
);
443 XFREE(MTYPE_OSPF_OPAQUE_FUNCTAB
, functab
);
451 static struct ospf_opaque_functab
*
452 ospf_opaque_functab_lookup(struct ospf_lsa
*lsa
)
454 struct list
*funclist
;
455 struct listnode
*node
;
456 struct ospf_opaque_functab
*functab
;
457 uint8_t key
= GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
));
459 if ((funclist
= ospf_get_opaque_funclist(lsa
->data
->type
)) != NULL
)
460 for (ALL_LIST_ELEMENTS_RO(funclist
, node
, functab
))
461 if (functab
->opaque_type
== key
)
467 /*------------------------------------------------------------------------*
468 * Following are management functions for self-originated LSA entries.
469 *------------------------------------------------------------------------*/
472 * Opaque-LSA control information per opaque-type.
473 * Single Opaque-Type may have multiple instances; each of them will be
474 * identified by their opaque-id.
476 struct opaque_info_per_type
{
480 enum { PROC_NORMAL
, PROC_SUSPEND
} status
;
483 * Thread for (re-)origination scheduling for this opaque-type.
485 * Initial origination of Opaque-LSAs is controlled by generic
486 * Opaque-LSA handling module so that same opaque-type entries are
487 * called all at once when certain conditions are met.
488 * However, there might be cases that some Opaque-LSA clients need
489 * to (re-)originate their own Opaque-LSAs out-of-sync with others.
490 * This thread is prepared for that specific purpose.
492 struct thread
*t_opaque_lsa_self
;
495 * Backpointer to an "owner" which is LSA-type dependent.
496 * type-9: struct ospf_interface
497 * type-10: struct ospf_area
498 * type-11: struct ospf
502 /* Collection of callback functions for this opaque-type. */
503 struct ospf_opaque_functab
*functab
;
505 /* List of Opaque-LSA control information per opaque-id. */
506 struct list
*id_list
;
509 /* Opaque-LSA control information per opaque-id. */
510 struct opaque_info_per_id
{
513 /* Thread for refresh/flush scheduling for this opaque-type/id. */
514 struct thread
*t_opaque_lsa_self
;
516 /* Backpointer to Opaque-LSA control information per opaque-type. */
517 struct opaque_info_per_type
*opqctl_type
;
519 /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
520 struct ospf_lsa
*lsa
;
523 static struct opaque_info_per_type
*
524 register_opaque_info_per_type(struct ospf_opaque_functab
*functab
,
525 struct ospf_lsa
*new);
526 static struct opaque_info_per_type
*
527 lookup_opaque_info_by_type(struct ospf_lsa
*lsa
);
528 static struct opaque_info_per_id
*
529 register_opaque_info_per_id(struct opaque_info_per_type
*oipt
,
530 struct ospf_lsa
*new);
531 static struct opaque_info_per_id
*
532 lookup_opaque_info_by_id(struct opaque_info_per_type
*oipt
,
533 struct ospf_lsa
*lsa
);
534 static struct opaque_info_per_id
*register_opaque_lsa(struct ospf_lsa
*new);
537 static struct opaque_info_per_type
*
538 register_opaque_info_per_type(struct ospf_opaque_functab
*functab
,
539 struct ospf_lsa
*new)
542 struct opaque_info_per_type
*oipt
;
544 oipt
= XCALLOC(MTYPE_OPAQUE_INFO_PER_TYPE
,
545 sizeof(struct opaque_info_per_type
));
547 switch (new->data
->type
) {
548 case OSPF_OPAQUE_LINK_LSA
:
549 oipt
->owner
= new->oi
;
550 listnode_add(new->oi
->opaque_lsa_self
, oipt
);
552 case OSPF_OPAQUE_AREA_LSA
:
553 oipt
->owner
= new->area
;
554 listnode_add(new->area
->opaque_lsa_self
, oipt
);
556 case OSPF_OPAQUE_AS_LSA
:
557 top
= ospf_lookup_by_vrf_id(new->vrf_id
);
558 if (new->area
!= NULL
&& (top
= new->area
->ospf
) == NULL
) {
559 free_opaque_info_per_type(oipt
, true);
561 goto out
; /* This case may not exist. */
564 listnode_add(top
->opaque_lsa_self
, oipt
);
567 flog_warn(EC_OSPF_LSA_UNEXPECTED
, "%s: Unexpected LSA-type(%u)",
568 __func__
, new->data
->type
);
569 free_opaque_info_per_type(oipt
, true);
571 goto out
; /* This case may not exist. */
574 oipt
->lsa_type
= new->data
->type
;
575 oipt
->opaque_type
= GET_OPAQUE_TYPE(ntohl(new->data
->id
.s_addr
));
576 oipt
->status
= PROC_NORMAL
;
577 oipt
->functab
= functab
;
578 functab
->oipt
= oipt
;
579 oipt
->id_list
= list_new();
580 oipt
->id_list
->del
= free_opaque_info_per_id
;
586 static void free_opaque_info_per_type(struct opaque_info_per_type
*oipt
,
589 struct opaque_info_per_id
*oipi
;
590 struct ospf_lsa
*lsa
;
591 struct listnode
*node
, *nnode
;
594 /* Control information per opaque-id may still exist. */
595 for (ALL_LIST_ELEMENTS(oipt
->id_list
, node
, nnode
, oipi
)) {
596 if ((lsa
= oipi
->lsa
) == NULL
)
598 if (IS_LSA_MAXAGE(lsa
))
600 ospf_opaque_lsa_flush_schedule(lsa
);
603 THREAD_OFF(oipt
->t_opaque_lsa_self
);
604 list_delete(&oipt
->id_list
);
606 /* Remove from its owner's self-originated LSA list. */
607 switch (oipt
->lsa_type
) {
608 case OSPF_OPAQUE_LINK_LSA
:
609 l
= ((struct ospf_interface
*)oipt
->owner
)
612 case OSPF_OPAQUE_AREA_LSA
:
613 l
= ((struct ospf_area
*)oipt
->owner
)->opaque_lsa_self
;
615 case OSPF_OPAQUE_AS_LSA
:
616 l
= ((struct ospf
*)oipt
->owner
)->opaque_lsa_self
;
620 EC_OSPF_LSA_UNEXPECTED
,
621 "free_opaque_info_owner: Unexpected LSA-type(%u)",
625 listnode_delete(l
, oipt
);
627 XFREE(MTYPE_OPAQUE_INFO_PER_TYPE
, oipt
);
631 static void free_opaque_info_per_type_del(void *val
)
633 free_opaque_info_per_type((struct opaque_info_per_type
*)val
, false);
636 static struct opaque_info_per_type
*
637 lookup_opaque_info_by_type(struct ospf_lsa
*lsa
)
640 struct ospf_area
*area
;
641 struct ospf_interface
*oi
;
642 struct list
*listtop
= NULL
;
643 struct listnode
*node
, *nnode
;
644 struct opaque_info_per_type
*oipt
= NULL
;
645 uint8_t key
= GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
));
647 switch (lsa
->data
->type
) {
648 case OSPF_OPAQUE_LINK_LSA
:
649 if ((oi
= lsa
->oi
) != NULL
)
650 listtop
= oi
->opaque_lsa_self
;
654 "Type-9 Opaque-LSA: Reference to OI is missing?");
656 case OSPF_OPAQUE_AREA_LSA
:
657 if ((area
= lsa
->area
) != NULL
)
658 listtop
= area
->opaque_lsa_self
;
662 "Type-10 Opaque-LSA: Reference to AREA is missing?");
664 case OSPF_OPAQUE_AS_LSA
:
665 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
666 if ((area
= lsa
->area
) != NULL
&& (top
= area
->ospf
) == NULL
) {
669 "Type-11 Opaque-LSA: Reference to OSPF is missing?");
670 break; /* Unlikely to happen. */
672 listtop
= top
->opaque_lsa_self
;
675 flog_warn(EC_OSPF_LSA_UNEXPECTED
, "%s: Unexpected LSA-type(%u)",
676 __func__
, lsa
->data
->type
);
681 for (ALL_LIST_ELEMENTS(listtop
, node
, nnode
, oipt
))
682 if (oipt
->opaque_type
== key
)
688 static struct opaque_info_per_id
*
689 register_opaque_info_per_id(struct opaque_info_per_type
*oipt
,
690 struct ospf_lsa
*new)
692 struct opaque_info_per_id
*oipi
;
694 oipi
= XCALLOC(MTYPE_OPAQUE_INFO_PER_ID
,
695 sizeof(struct opaque_info_per_id
));
697 oipi
->opaque_id
= GET_OPAQUE_ID(ntohl(new->data
->id
.s_addr
));
698 oipi
->opqctl_type
= oipt
;
699 oipi
->lsa
= ospf_lsa_lock(new);
701 listnode_add(oipt
->id_list
, oipi
);
706 static void free_opaque_info_per_id(void *val
)
708 struct opaque_info_per_id
*oipi
= (struct opaque_info_per_id
*)val
;
710 THREAD_OFF(oipi
->t_opaque_lsa_self
);
711 if (oipi
->lsa
!= NULL
)
712 ospf_lsa_unlock(&oipi
->lsa
);
713 XFREE(MTYPE_OPAQUE_INFO_PER_ID
, oipi
);
717 static struct opaque_info_per_id
*
718 lookup_opaque_info_by_id(struct opaque_info_per_type
*oipt
,
719 struct ospf_lsa
*lsa
)
721 struct listnode
*node
, *nnode
;
722 struct opaque_info_per_id
*oipi
;
723 uint32_t key
= GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
));
725 for (ALL_LIST_ELEMENTS(oipt
->id_list
, node
, nnode
, oipi
))
726 if (oipi
->opaque_id
== key
)
732 static struct opaque_info_per_id
*register_opaque_lsa(struct ospf_lsa
*new)
734 struct ospf_opaque_functab
*functab
;
735 struct opaque_info_per_type
*oipt
;
736 struct opaque_info_per_id
*oipi
= NULL
;
738 if ((functab
= ospf_opaque_functab_lookup(new)) == NULL
)
741 if ((oipt
= lookup_opaque_info_by_type(new)) == NULL
742 && (oipt
= register_opaque_info_per_type(functab
, new)) == NULL
)
745 if ((oipi
= register_opaque_info_per_id(oipt
, new)) == NULL
)
752 int ospf_opaque_is_owned(struct ospf_lsa
*lsa
)
754 struct opaque_info_per_type
*oipt
= lookup_opaque_info_by_type(lsa
);
756 return (oipt
!= NULL
&& lookup_opaque_info_by_id(oipt
, lsa
) != NULL
);
759 /*------------------------------------------------------------------------*
760 * Following 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 * Following 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 * Following 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
,
1165 struct lsa_header
*lsah
= lsa
->data
;
1166 uint32_t lsid
= ntohl(lsah
->id
.s_addr
);
1167 uint8_t opaque_type
= GET_OPAQUE_TYPE(lsid
);
1168 uint32_t opaque_id
= GET_OPAQUE_ID(lsid
);
1169 struct ospf_opaque_functab
*functab
;
1171 /* Switch output functionality by vty address. */
1174 vty_out(vty
, " Opaque-Type %u (%s)\n", opaque_type
,
1175 ospf_opaque_type_name(opaque_type
));
1176 vty_out(vty
, " Opaque-ID 0x%x\n", opaque_id
);
1178 vty_out(vty
, " Opaque-Info: %u octets of data%s\n",
1179 ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
,
1180 VALID_OPAQUE_INFO_LEN(lsah
)
1182 : "(Invalid length?)");
1184 json_object_string_add(
1186 ospf_opaque_type_name(opaque_type
));
1187 json_object_int_add(json
, "opaqueId", opaque_id
);
1188 json_object_int_add(json
, "opaqueDataLength",
1190 - OSPF_LSA_HEADER_SIZE
);
1191 json_object_boolean_add(json
, "opaqueDataLengthValid",
1192 VALID_OPAQUE_INFO_LEN(lsah
));
1195 zlog_debug(" Opaque-Type %u (%s)", opaque_type
,
1196 ospf_opaque_type_name(opaque_type
));
1197 zlog_debug(" Opaque-ID 0x%x", opaque_id
);
1199 zlog_debug(" Opaque-Info: %u octets of data%s",
1200 ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
,
1201 VALID_OPAQUE_INFO_LEN(lsah
) ? ""
1202 : "(Invalid length?)");
1205 /* Call individual output functions. */
1206 if ((functab
= ospf_opaque_functab_lookup(lsa
)) != NULL
)
1207 if (functab
->show_opaque_info
!= NULL
)
1208 (*functab
->show_opaque_info
)(vty
, json
, lsa
);
1213 void ospf_opaque_lsa_dump(struct stream
*s
, uint16_t length
)
1215 struct ospf_lsa lsa
= {};
1217 lsa
.data
= (struct lsa_header
*)stream_pnt(s
);
1219 show_opaque_info_detail(NULL
, &lsa
, NULL
);
1223 static int ospf_opaque_lsa_install_hook(struct ospf_lsa
*lsa
)
1225 struct list
*funclist
;
1229 * Some Opaque-LSA user may want to monitor every LSA installation
1230 * into the LSDB, regardless with target LSA type.
1232 funclist
= ospf_opaque_wildcard_funclist
;
1233 if (new_lsa_callback(funclist
, lsa
) != 0)
1236 funclist
= ospf_opaque_type9_funclist
;
1237 if (new_lsa_callback(funclist
, lsa
) != 0)
1240 funclist
= ospf_opaque_type10_funclist
;
1241 if (new_lsa_callback(funclist
, lsa
) != 0)
1244 funclist
= ospf_opaque_type11_funclist
;
1245 if (new_lsa_callback(funclist
, lsa
) != 0)
1253 static int ospf_opaque_lsa_delete_hook(struct ospf_lsa
*lsa
)
1255 struct list
*funclist
;
1259 * Some Opaque-LSA user may want to monitor every LSA deletion
1260 * from the LSDB, regardless with target LSA type.
1262 funclist
= ospf_opaque_wildcard_funclist
;
1263 if (del_lsa_callback(funclist
, lsa
) != 0)
1266 funclist
= ospf_opaque_type9_funclist
;
1267 if (del_lsa_callback(funclist
, lsa
) != 0)
1270 funclist
= ospf_opaque_type10_funclist
;
1271 if (del_lsa_callback(funclist
, lsa
) != 0)
1274 funclist
= ospf_opaque_type11_funclist
;
1275 if (del_lsa_callback(funclist
, lsa
) != 0)
1283 /*------------------------------------------------------------------------*
1284 * Following are Opaque-LSA origination/refresh management functions.
1285 *------------------------------------------------------------------------*/
1287 static void ospf_opaque_type9_lsa_originate(struct thread
*t
);
1288 static void ospf_opaque_type10_lsa_originate(struct thread
*t
);
1289 static void ospf_opaque_type11_lsa_originate(struct thread
*t
);
1290 static void ospf_opaque_lsa_reoriginate_resume(struct list
*listtop
, void *arg
);
1292 void ospf_opaque_lsa_originate_schedule(struct ospf_interface
*oi
, int *delay0
)
1295 struct ospf_area
*area
;
1296 struct listnode
*node
, *nnode
;
1297 struct opaque_info_per_type
*oipt
;
1300 if ((top
= oi_to_top(oi
)) == NULL
|| (area
= oi
->area
) == NULL
) {
1301 if (IS_DEBUG_OSPF_EVENT
)
1302 zlog_debug("%s: Invalid argument?", __func__
);
1306 /* It may not a right time to schedule origination now. */
1307 if (!CHECK_FLAG(top
->opaque
, OPAQUE_OPERATION_READY_BIT
)) {
1308 if (IS_DEBUG_OSPF_EVENT
)
1309 zlog_debug("%s: Not operational.", __func__
);
1310 return; /* This is not an error. */
1317 * There might be some entries that have been waiting for triggering
1318 * of per opaque-type re-origination get resumed.
1320 ospf_opaque_lsa_reoriginate_resume(oi
->opaque_lsa_self
, (void *)oi
);
1321 ospf_opaque_lsa_reoriginate_resume(area
->opaque_lsa_self
, (void *)area
);
1322 ospf_opaque_lsa_reoriginate_resume(top
->opaque_lsa_self
, (void *)top
);
1325 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1327 if (!list_isempty(ospf_opaque_type9_funclist
)
1328 && list_isempty(oi
->opaque_lsa_self
)
1329 && oi
->t_opaque_lsa_self
== NULL
) {
1330 if (IS_DEBUG_OSPF_EVENT
)
1332 "Schedule Type-9 Opaque-LSA origination in %d ms later.",
1334 oi
->t_opaque_lsa_self
= NULL
;
1335 thread_add_timer_msec(master
, ospf_opaque_type9_lsa_originate
,
1336 oi
, delay
, &oi
->t_opaque_lsa_self
);
1337 delay
+= top
->min_ls_interval
;
1340 if (!list_isempty(ospf_opaque_type10_funclist
)
1341 && list_isempty(area
->opaque_lsa_self
)
1342 && area
->t_opaque_lsa_self
== NULL
) {
1344 * One AREA may contain multiple OIs, but above 2nd and 3rd
1345 * conditions prevent from scheduling the originate function
1348 if (IS_DEBUG_OSPF_EVENT
)
1350 "Schedule Type-10 Opaque-LSA origination in %d ms later.",
1352 area
->t_opaque_lsa_self
= NULL
;
1353 thread_add_timer_msec(master
, ospf_opaque_type10_lsa_originate
,
1354 area
, delay
, &area
->t_opaque_lsa_self
);
1355 delay
+= top
->min_ls_interval
;
1358 if (!list_isempty(ospf_opaque_type11_funclist
)
1359 && list_isempty(top
->opaque_lsa_self
)
1360 && top
->t_opaque_lsa_self
== NULL
) {
1362 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1363 * conditions prevent from scheduling the originate function
1366 if (IS_DEBUG_OSPF_EVENT
)
1368 "Schedule Type-11 Opaque-LSA origination in %d ms later.",
1370 top
->t_opaque_lsa_self
= NULL
;
1371 thread_add_timer_msec(master
, ospf_opaque_type11_lsa_originate
,
1372 top
, delay
, &top
->t_opaque_lsa_self
);
1373 delay
+= top
->min_ls_interval
;
1377 * Following section treats a special situation that this node's
1378 * opaque capability has changed as "ON -> OFF -> ON".
1380 if (!list_isempty(ospf_opaque_type9_funclist
)
1381 && !list_isempty(oi
->opaque_lsa_self
)) {
1382 for (ALL_LIST_ELEMENTS(oi
->opaque_lsa_self
, node
, nnode
,
1385 * removed the test for
1386 * (! list_isempty (oipt->id_list)) * Handler is
1388 * because opaque cababilities ON -> OFF -> ON result in
1389 * list_isempty (oipt->id_list)
1392 if (oipt
->t_opaque_lsa_self
1393 != NULL
/* Waiting for a thread call. */
1394 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1399 ospf_opaque_lsa_reoriginate_schedule(
1400 (void *)oi
, OSPF_OPAQUE_LINK_LSA
,
1405 if (!list_isempty(ospf_opaque_type10_funclist
)
1406 && !list_isempty(area
->opaque_lsa_self
)) {
1407 for (ALL_LIST_ELEMENTS(area
->opaque_lsa_self
, node
, nnode
,
1410 * removed the test for
1411 * (! list_isempty (oipt->id_list)) * Handler is
1413 * because opaque cababilities ON -> OFF -> ON result in
1414 * list_isempty (oipt->id_list)
1417 if (oipt
->t_opaque_lsa_self
1418 != NULL
/* Waiting for a thread call. */
1419 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1424 ospf_opaque_lsa_reoriginate_schedule(
1425 (void *)area
, OSPF_OPAQUE_AREA_LSA
,
1430 if (!list_isempty(ospf_opaque_type11_funclist
)
1431 && !list_isempty(top
->opaque_lsa_self
)) {
1432 for (ALL_LIST_ELEMENTS(top
->opaque_lsa_self
, node
, nnode
,
1435 * removed the test for
1436 * (! list_isempty (oipt->id_list)) * Handler is
1438 * because opaque cababilities ON -> OFF -> ON result in
1439 * list_isempty (oipt->id_list)
1442 if (oipt
->t_opaque_lsa_self
1443 != NULL
/* Waiting for a thread call. */
1444 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1449 ospf_opaque_lsa_reoriginate_schedule((void *)top
,
1459 static void ospf_opaque_type9_lsa_originate(struct thread
*t
)
1461 struct ospf_interface
*oi
;
1464 oi
->t_opaque_lsa_self
= NULL
;
1466 if (IS_DEBUG_OSPF_EVENT
)
1467 zlog_debug("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
1470 opaque_lsa_originate_callback(ospf_opaque_type9_funclist
, oi
);
1473 static void ospf_opaque_type10_lsa_originate(struct thread
*t
)
1475 struct ospf_area
*area
;
1477 area
= THREAD_ARG(t
);
1478 area
->t_opaque_lsa_self
= NULL
;
1480 if (IS_DEBUG_OSPF_EVENT
)
1482 "Timer[Type10-LSA]: Originate Opaque-LSAs for Area %pI4",
1485 opaque_lsa_originate_callback(ospf_opaque_type10_funclist
, area
);
1488 static void ospf_opaque_type11_lsa_originate(struct thread
*t
)
1492 top
= THREAD_ARG(t
);
1493 top
->t_opaque_lsa_self
= NULL
;
1495 if (IS_DEBUG_OSPF_EVENT
)
1497 "Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
1499 opaque_lsa_originate_callback(ospf_opaque_type11_funclist
, top
);
1502 static void ospf_opaque_lsa_reoriginate_resume(struct list
*listtop
, void *arg
)
1504 struct listnode
*node
, *nnode
;
1505 struct opaque_info_per_type
*oipt
;
1506 struct ospf_opaque_functab
*functab
;
1508 if (listtop
== NULL
)
1512 * Pickup oipt entries those which in SUSPEND status, and give
1513 * them a chance to start re-origination now.
1515 for (ALL_LIST_ELEMENTS(listtop
, node
, nnode
, oipt
)) {
1516 if (oipt
->status
!= PROC_SUSPEND
)
1519 oipt
->status
= PROC_NORMAL
;
1521 if ((functab
= oipt
->functab
) == NULL
1522 || functab
->lsa_originator
== NULL
)
1525 if ((*functab
->lsa_originator
)(arg
) != 0) {
1526 flog_warn(EC_OSPF_LSA
, "%s: Failed (opaque-type=%u)",
1527 __func__
, oipt
->opaque_type
);
1536 struct ospf_lsa
*ospf_opaque_lsa_install(struct ospf_lsa
*lsa
, int rt_recalc
)
1538 struct ospf_lsa
*new = NULL
;
1539 struct opaque_info_per_type
*oipt
;
1540 struct opaque_info_per_id
*oipi
;
1543 /* Don't take "rt_recalc" into consideration for now. */ /* XXX */
1545 if (!IS_LSA_SELF(lsa
)) {
1546 new = lsa
; /* Don't touch this LSA. */
1550 if (IS_DEBUG_OSPF(lsa
, LSA_INSTALL
))
1552 "Install Type-%u Opaque-LSA: [opaque-type=%u, opaque-id=%x]",
1554 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
1555 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
1557 /* Replace the existing lsa with the new one. */
1558 if ((oipt
= lookup_opaque_info_by_type(lsa
)) != NULL
1559 && (oipi
= lookup_opaque_info_by_id(oipt
, lsa
)) != NULL
) {
1560 ospf_lsa_unlock(&oipi
->lsa
);
1561 oipi
->lsa
= ospf_lsa_lock(lsa
);
1563 /* Register the new lsa entry */
1564 else if (register_opaque_lsa(lsa
) == NULL
) {
1565 flog_warn(EC_OSPF_LSA
, "%s: register_opaque_lsa() ?", __func__
);
1570 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1571 * for periodic refresh of self-originated Opaque-LSAs.
1573 switch (lsa
->data
->type
) {
1574 case OSPF_OPAQUE_LINK_LSA
:
1575 if ((top
= oi_to_top(lsa
->oi
)) == NULL
) {
1576 /* Above conditions must have passed. */
1577 flog_warn(EC_OSPF_LSA
, "%s: Something wrong?",
1582 case OSPF_OPAQUE_AREA_LSA
:
1583 if (lsa
->area
== NULL
|| (top
= lsa
->area
->ospf
) == NULL
) {
1584 /* Above conditions must have passed. */
1585 flog_warn(EC_OSPF_LSA
, "%s: Something wrong?",
1590 case OSPF_OPAQUE_AS_LSA
:
1591 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
1592 if (lsa
->area
!= NULL
&& (top
= lsa
->area
->ospf
) == NULL
) {
1593 /* Above conditions must have passed. */
1594 flog_warn(EC_OSPF_LSA
, "%s: Something wrong?",
1600 flog_warn(EC_OSPF_LSA_UNEXPECTED
, "%s: Unexpected LSA-type(%u)",
1601 __func__
, lsa
->data
->type
);
1605 ospf_refresher_register_lsa(top
, lsa
);
1612 struct ospf_lsa
*ospf_opaque_lsa_refresh(struct ospf_lsa
*lsa
)
1615 struct ospf_opaque_functab
*functab
;
1616 struct ospf_lsa
*new = NULL
;
1618 ospf
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
1620 if ((functab
= ospf_opaque_functab_lookup(lsa
)) == NULL
1621 || functab
->lsa_refresher
== NULL
) {
1623 * Though this LSA seems to have originated on this node, the
1624 * handling module for this "lsa-type and opaque-type" was
1625 * already deleted sometime ago.
1626 * Anyway, this node still has a responsibility to flush this
1627 * LSA from the routing domain.
1629 if (IS_DEBUG_OSPF_EVENT
)
1630 zlog_debug("LSA[Type%d:%pI4]: Flush stray Opaque-LSA",
1631 lsa
->data
->type
, &lsa
->data
->id
);
1633 lsa
->data
->ls_age
= htons(OSPF_LSA_MAXAGE
);
1634 ospf_lsa_flush(ospf
, lsa
);
1636 new = (*functab
->lsa_refresher
)(lsa
);
1641 /*------------------------------------------------------------------------*
1642 * Following are re-origination/refresh/flush operations of Opaque-LSAs,
1643 * triggered by external interventions (vty session, signaling, etc).
1644 *------------------------------------------------------------------------*/
1646 #define OSPF_OPAQUE_TIMER_ON(T,F,L,V) thread_add_timer_msec (master, (F), (L), (V), &(T))
1648 static struct ospf_lsa
*pseudo_lsa(struct ospf_interface
*oi
,
1649 struct ospf_area
*area
, uint8_t lsa_type
,
1650 uint8_t opaque_type
);
1651 static void ospf_opaque_type9_lsa_reoriginate_timer(struct thread
*t
);
1652 static void ospf_opaque_type10_lsa_reoriginate_timer(struct thread
*t
);
1653 static void ospf_opaque_type11_lsa_reoriginate_timer(struct thread
*t
);
1654 static void ospf_opaque_lsa_refresh_timer(struct thread
*t
);
1656 void ospf_opaque_lsa_reoriginate_schedule(void *lsa_type_dependent
,
1657 uint8_t lsa_type
, uint8_t opaque_type
)
1659 struct ospf
*top
= NULL
;
1660 struct ospf_area dummy
, *area
= NULL
;
1661 struct ospf_interface
*oi
= NULL
;
1663 struct ospf_lsa
*lsa
;
1664 struct opaque_info_per_type
*oipt
;
1665 void (*func
)(struct thread
* t
) = NULL
;
1669 case OSPF_OPAQUE_LINK_LSA
:
1670 if ((oi
= (struct ospf_interface
*)lsa_type_dependent
)
1672 flog_warn(EC_OSPF_LSA
,
1673 "%s: Type-9 Opaque-LSA: Invalid parameter?",
1677 if ((top
= oi_to_top(oi
)) == NULL
) {
1678 flog_warn(EC_OSPF_LSA
, "%s: OI(%s) -> TOP?", __func__
,
1682 if (!list_isempty(ospf_opaque_type9_funclist
)
1683 && list_isempty(oi
->opaque_lsa_self
)
1684 && oi
->t_opaque_lsa_self
!= NULL
) {
1687 "Type-9 Opaque-LSA (opaque_type=%u): Common origination for OI(%s) has already started",
1688 opaque_type
, IF_NAME(oi
));
1691 func
= ospf_opaque_type9_lsa_reoriginate_timer
;
1693 case OSPF_OPAQUE_AREA_LSA
:
1694 if ((area
= (struct ospf_area
*)lsa_type_dependent
) == NULL
) {
1695 flog_warn(EC_OSPF_LSA
,
1696 "%s: Type-10 Opaque-LSA: Invalid parameter?",
1700 if ((top
= area
->ospf
) == NULL
) {
1701 flog_warn(EC_OSPF_LSA
, "%s: AREA(%pI4) -> TOP?",
1702 __func__
, &area
->area_id
);
1705 if (!list_isempty(ospf_opaque_type10_funclist
)
1706 && list_isempty(area
->opaque_lsa_self
)
1707 && area
->t_opaque_lsa_self
!= NULL
) {
1710 "Type-10 Opaque-LSA (opaque_type=%u): Common origination for AREA(%pI4) has already started",
1711 opaque_type
, &area
->area_id
);
1714 func
= ospf_opaque_type10_lsa_reoriginate_timer
;
1716 case OSPF_OPAQUE_AS_LSA
:
1717 if ((top
= (struct ospf
*)lsa_type_dependent
) == NULL
) {
1718 flog_warn(EC_OSPF_LSA
,
1719 "%s: Type-11 Opaque-LSA: Invalid parameter?",
1723 if (!list_isempty(ospf_opaque_type11_funclist
)
1724 && list_isempty(top
->opaque_lsa_self
)
1725 && top
->t_opaque_lsa_self
!= NULL
) {
1728 "Type-11 Opaque-LSA (opaque_type=%u): Common origination has already started",
1733 /* Fake "area" to pass "ospf" to a lookup function later. */
1737 func
= ospf_opaque_type11_lsa_reoriginate_timer
;
1740 flog_warn(EC_OSPF_LSA_UNEXPECTED
, "%s: Unexpected LSA-type(%u)",
1741 __func__
, lsa_type
);
1745 /* It may not a right time to schedule reorigination now. */
1746 if (!CHECK_FLAG(top
->opaque
, OPAQUE_OPERATION_READY_BIT
)) {
1747 if (IS_DEBUG_OSPF_EVENT
)
1748 zlog_debug("%s: Not operational.", __func__
);
1749 goto out
; /* This is not an error. */
1752 /* Generate a dummy lsa to be passed for a lookup function. */
1753 lsa
= pseudo_lsa(oi
, area
, lsa_type
, opaque_type
);
1754 lsa
->vrf_id
= top
->vrf_id
;
1756 if ((oipt
= lookup_opaque_info_by_type(lsa
)) == NULL
) {
1757 struct ospf_opaque_functab
*functab
;
1758 if ((functab
= ospf_opaque_functab_lookup(lsa
)) == NULL
) {
1761 "%s: No associated function?: lsa_type(%u), opaque_type(%u)",
1762 __func__
, lsa_type
, opaque_type
);
1765 if ((oipt
= register_opaque_info_per_type(functab
, lsa
))
1769 "%s: Cannot get a control info?: lsa_type(%u), opaque_type(%u)",
1770 __func__
, lsa_type
, opaque_type
);
1775 if (oipt
->t_opaque_lsa_self
!= NULL
) {
1776 if (IS_DEBUG_OSPF_EVENT
)
1778 "Type-%u Opaque-LSA has already scheduled to RE-ORIGINATE: [opaque-type=%u]",
1780 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)));
1785 * Different from initial origination time, in which various conditions
1786 * (opaque capability, neighbor status etc) are assured by caller of
1787 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1788 * it is highly possible that these conditions might not be satisfied
1789 * at the time of re-origination function is to be called.
1791 delay
= top
->min_ls_interval
; /* XXX */
1793 if (IS_DEBUG_OSPF_EVENT
)
1795 "Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d ms later: [opaque-type=%u]",
1797 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)));
1799 OSPF_OPAQUE_TIMER_ON(oipt
->t_opaque_lsa_self
, func
, oipt
, delay
);
1805 static struct ospf_lsa
*pseudo_lsa(struct ospf_interface
*oi
,
1806 struct ospf_area
*area
, uint8_t lsa_type
,
1807 uint8_t opaque_type
)
1809 static struct ospf_lsa lsa
= {0};
1810 static struct lsa_header lsah
= {0};
1816 lsa
.vrf_id
= VRF_DEFAULT
;
1818 lsah
.type
= lsa_type
;
1819 tmp
= SET_OPAQUE_LSID(opaque_type
, 0); /* Opaque-ID is unused here. */
1820 lsah
.id
.s_addr
= htonl(tmp
);
1825 static void ospf_opaque_type9_lsa_reoriginate_timer(struct thread
*t
)
1827 struct opaque_info_per_type
*oipt
;
1828 struct ospf_opaque_functab
*functab
;
1830 struct ospf_interface
*oi
;
1832 oipt
= THREAD_ARG(t
);
1834 if ((functab
= oipt
->functab
) == NULL
1835 || functab
->lsa_originator
== NULL
) {
1836 flog_warn(EC_OSPF_LSA
, "%s: No associated function?", __func__
);
1840 oi
= (struct ospf_interface
*)oipt
->owner
;
1841 if ((top
= oi_to_top(oi
)) == NULL
) {
1842 flog_warn(EC_OSPF_LSA
, "%s: Something wrong?", __func__
);
1846 if (!CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)
1847 || !ospf_if_is_enable(oi
)
1848 || ospf_nbr_count_opaque_capable(oi
) == 0) {
1849 if (IS_DEBUG_OSPF_EVENT
)
1851 "Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...",
1854 oipt
->status
= PROC_SUSPEND
;
1858 if (IS_DEBUG_OSPF_EVENT
)
1860 "Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)",
1861 oipt
->opaque_type
, IF_NAME(oi
));
1863 (*functab
->lsa_originator
)(oi
);
1866 static void ospf_opaque_type10_lsa_reoriginate_timer(struct thread
*t
)
1868 struct opaque_info_per_type
*oipt
;
1869 struct ospf_opaque_functab
*functab
;
1870 struct listnode
*node
, *nnode
;
1872 struct ospf_area
*area
;
1873 struct ospf_interface
*oi
;
1876 oipt
= THREAD_ARG(t
);
1878 if ((functab
= oipt
->functab
) == NULL
1879 || functab
->lsa_originator
== NULL
) {
1880 flog_warn(EC_OSPF_LSA
, "%s: No associated function?", __func__
);
1884 area
= (struct ospf_area
*)oipt
->owner
;
1885 if (area
== NULL
|| (top
= area
->ospf
) == NULL
) {
1886 flog_warn(EC_OSPF_LSA
, "%s: Something wrong?", __func__
);
1890 /* There must be at least one "opaque-capable, full-state" neighbor. */
1892 for (ALL_LIST_ELEMENTS(area
->oiflist
, node
, nnode
, oi
)) {
1893 if ((n
= ospf_nbr_count_opaque_capable(oi
)) > 0)
1897 if (n
== 0 || !CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)) {
1898 if (IS_DEBUG_OSPF_EVENT
)
1900 "Suspend re-origination of Type-10 Opaque-LSAs (opaque-type=%u) for a while...",
1903 oipt
->status
= PROC_SUSPEND
;
1907 if (IS_DEBUG_OSPF_EVENT
)
1909 "Timer[Type10-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for Area %pI4",
1910 oipt
->opaque_type
, &area
->area_id
);
1912 (*functab
->lsa_originator
)(area
);
1915 static void ospf_opaque_type11_lsa_reoriginate_timer(struct thread
*t
)
1917 struct opaque_info_per_type
*oipt
;
1918 struct ospf_opaque_functab
*functab
;
1921 oipt
= THREAD_ARG(t
);
1923 if ((functab
= oipt
->functab
) == NULL
1924 || functab
->lsa_originator
== NULL
) {
1925 flog_warn(EC_OSPF_LSA
, "%s: No associated function?", __func__
);
1929 if ((top
= (struct ospf
*)oipt
->owner
) == NULL
) {
1930 flog_warn(EC_OSPF_LSA
, "%s: Something wrong?", __func__
);
1934 if (!CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)) {
1935 if (IS_DEBUG_OSPF_EVENT
)
1937 "Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...",
1940 oipt
->status
= PROC_SUSPEND
;
1944 if (IS_DEBUG_OSPF_EVENT
)
1946 "Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).",
1949 (*functab
->lsa_originator
)(top
);
1952 void ospf_opaque_lsa_refresh_schedule(struct ospf_lsa
*lsa0
)
1954 struct opaque_info_per_type
*oipt
;
1955 struct opaque_info_per_id
*oipi
;
1956 struct ospf_lsa
*lsa
;
1960 if ((oipt
= lookup_opaque_info_by_type(lsa0
)) == NULL
1961 || (oipi
= lookup_opaque_info_by_id(oipt
, lsa0
)) == NULL
) {
1962 flog_warn(EC_OSPF_LSA
, "%s: Invalid parameter?", __func__
);
1966 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
1967 if ((lsa
= oipi
->lsa
) == NULL
) {
1968 flog_warn(EC_OSPF_LSA
, "%s: Something wrong?", __func__
);
1972 if (oipi
->t_opaque_lsa_self
!= NULL
) {
1973 if (IS_DEBUG_OSPF_EVENT
)
1975 "Type-%u Opaque-LSA has already scheduled to REFRESH: [opaque-type=%u, opaque-id=%x]",
1977 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
1978 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
1982 /* Delete this lsa from neighbor retransmit-list. */
1983 switch (lsa
->data
->type
) {
1984 case OSPF_OPAQUE_LINK_LSA
:
1985 case OSPF_OPAQUE_AREA_LSA
:
1986 ospf_ls_retransmit_delete_nbr_area(lsa
->area
, lsa
);
1988 case OSPF_OPAQUE_AS_LSA
:
1989 top
= ospf_lookup_by_vrf_id(lsa0
->vrf_id
);
1990 if ((lsa0
->area
!= NULL
) && (lsa0
->area
->ospf
!= NULL
))
1991 top
= lsa0
->area
->ospf
;
1992 ospf_ls_retransmit_delete_nbr_as(top
, lsa
);
1995 flog_warn(EC_OSPF_LSA_UNEXPECTED
, "%s: Unexpected LSA-type(%u)",
1996 __func__
, lsa
->data
->type
);
2000 delay
= ospf_lsa_refresh_delay(lsa
);
2002 if (IS_DEBUG_OSPF_EVENT
)
2004 "Schedule Type-%u Opaque-LSA to REFRESH in %d sec later: [opaque-type=%u, opaque-id=%x]",
2005 lsa
->data
->type
, delay
,
2006 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
2007 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
2009 OSPF_OPAQUE_TIMER_ON(oipi
->t_opaque_lsa_self
,
2010 ospf_opaque_lsa_refresh_timer
, oipi
, delay
* 1000);
2015 static void ospf_opaque_lsa_refresh_timer(struct thread
*t
)
2017 struct opaque_info_per_id
*oipi
;
2018 struct ospf_opaque_functab
*functab
;
2019 struct ospf_lsa
*lsa
;
2021 if (IS_DEBUG_OSPF_EVENT
)
2022 zlog_debug("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
2024 oipi
= THREAD_ARG(t
);
2026 if ((lsa
= oipi
->lsa
) != NULL
)
2027 if ((functab
= oipi
->opqctl_type
->functab
) != NULL
)
2028 if (functab
->lsa_refresher
!= NULL
)
2029 (*functab
->lsa_refresher
)(lsa
);
2032 void ospf_opaque_lsa_flush_schedule(struct ospf_lsa
*lsa0
)
2034 struct opaque_info_per_type
*oipt
;
2035 struct opaque_info_per_id
*oipi
;
2036 struct ospf_lsa
*lsa
;
2039 top
= ospf_lookup_by_vrf_id(lsa0
->vrf_id
);
2041 if ((oipt
= lookup_opaque_info_by_type(lsa0
)) == NULL
2042 || (oipi
= lookup_opaque_info_by_id(oipt
, lsa0
)) == NULL
) {
2043 flog_warn(EC_OSPF_LSA
, "%s: Invalid parameter?", __func__
);
2047 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2048 if ((lsa
= oipi
->lsa
) == NULL
) {
2049 flog_warn(EC_OSPF_LSA
, "%s: Something wrong?", __func__
);
2053 if (lsa
->opaque_zero_len_delete
&&
2054 lsa
->data
->length
!= htons(sizeof(struct lsa_header
))) {
2055 /* minimize the size of the withdrawal: */
2056 /* increment the sequence number and make len just header */
2057 /* and update checksum */
2058 lsa
->data
->ls_seqnum
= lsa_seqnum_increment(lsa
);
2059 lsa
->data
->length
= htons(sizeof(struct lsa_header
));
2060 lsa
->data
->checksum
= 0;
2061 lsa
->data
->checksum
= ospf_lsa_checksum(lsa
->data
);
2064 /* Delete this lsa from neighbor retransmit-list. */
2065 switch (lsa
->data
->type
) {
2066 case OSPF_OPAQUE_LINK_LSA
:
2067 case OSPF_OPAQUE_AREA_LSA
:
2068 ospf_ls_retransmit_delete_nbr_area(lsa
->area
, lsa
);
2070 case OSPF_OPAQUE_AS_LSA
:
2071 if ((lsa0
->area
!= NULL
) && (lsa0
->area
->ospf
!= NULL
))
2072 top
= lsa0
->area
->ospf
;
2073 ospf_ls_retransmit_delete_nbr_as(top
, lsa
);
2076 flog_warn(EC_OSPF_LSA_UNEXPECTED
, "%s: Unexpected LSA-type(%u)",
2077 __func__
, lsa
->data
->type
);
2081 /* This lsa will be flushed and removed eventually. */
2082 ospf_lsa_flush(top
, lsa
);
2084 /* Dequeue listnode entry from the list. */
2085 listnode_delete(oipt
->id_list
, oipi
);
2087 if (IS_DEBUG_OSPF_EVENT
)
2089 "Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]",
2091 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
2092 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
2094 /* Disassociate internal control information with the given lsa. */
2095 free_opaque_info_per_id((void *)oipi
);
2101 void ospf_opaque_self_originated_lsa_received(struct ospf_neighbor
*nbr
,
2102 struct ospf_lsa
*lsa
)
2106 if ((top
= oi_to_top(nbr
->oi
)) == NULL
)
2109 if (IS_DEBUG_OSPF_EVENT
)
2111 "LSA[Type%d:%pI4]: processing self-originated Opaque-LSA",
2112 lsa
->data
->type
, &lsa
->data
->id
);
2115 * Since these LSA entries are not yet installed into corresponding
2116 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2118 lsa
->data
->ls_age
= htons(OSPF_LSA_MAXAGE
);
2119 switch (lsa
->data
->type
) {
2120 case OSPF_OPAQUE_LINK_LSA
:
2121 ospf_flood_through_area(nbr
->oi
->area
, NULL
/*inbr*/, lsa
);
2123 case OSPF_OPAQUE_AREA_LSA
:
2124 ospf_flood_through_area(nbr
->oi
->area
, NULL
/*inbr*/, lsa
);
2126 case OSPF_OPAQUE_AS_LSA
:
2127 ospf_flood_through_as(top
, NULL
/*inbr*/, lsa
);
2130 flog_warn(EC_OSPF_LSA_UNEXPECTED
, "%s: Unexpected LSA-type(%u)",
2131 __func__
, lsa
->data
->type
);
2134 ospf_lsa_discard(lsa
); /* List "lsas" will be deleted by caller. */
2137 /*------------------------------------------------------------------------*
2138 * Following are util functions; probably be used by Opaque-LSAs only...
2139 *------------------------------------------------------------------------*/
2141 struct ospf
*oi_to_top(struct ospf_interface
*oi
)
2143 struct ospf
*top
= NULL
;
2144 struct ospf_area
*area
;
2146 if (oi
== NULL
|| (area
= oi
->area
) == NULL
2147 || (top
= area
->ospf
) == NULL
)
2148 flog_warn(EC_OSPF_LSA
,
2149 "Broken relationship for \"OI -> AREA -> OSPF\"?");