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_mpls_te_finish();
131 ospf_router_info_finish();
138 int ospf_opaque_type9_lsa_init(struct ospf_interface
*oi
)
140 if (oi
->opaque_lsa_self
!= NULL
)
141 list_delete(&oi
->opaque_lsa_self
);
143 oi
->opaque_lsa_self
= list_new();
144 oi
->opaque_lsa_self
->del
= free_opaque_info_per_type
;
145 oi
->t_opaque_lsa_self
= NULL
;
149 void ospf_opaque_type9_lsa_term(struct ospf_interface
*oi
)
151 OSPF_TIMER_OFF(oi
->t_opaque_lsa_self
);
152 if (oi
->opaque_lsa_self
!= NULL
)
153 list_delete(&oi
->opaque_lsa_self
);
154 oi
->opaque_lsa_self
= NULL
;
158 int ospf_opaque_type10_lsa_init(struct ospf_area
*area
)
160 if (area
->opaque_lsa_self
!= NULL
)
161 list_delete(&area
->opaque_lsa_self
);
163 area
->opaque_lsa_self
= list_new();
164 area
->opaque_lsa_self
->del
= free_opaque_info_per_type
;
165 area
->t_opaque_lsa_self
= NULL
;
167 #ifdef MONITOR_LSDB_CHANGE
168 area
->lsdb
->new_lsa_hook
= ospf_opaque_lsa_install_hook
;
169 area
->lsdb
->del_lsa_hook
= ospf_opaque_lsa_delete_hook
;
170 #endif /* MONITOR_LSDB_CHANGE */
174 void ospf_opaque_type10_lsa_term(struct ospf_area
*area
)
176 #ifdef MONITOR_LSDB_CHANGE
177 area
->lsdb
->new_lsa_hook
= area
->lsdb
->del_lsa_hook
= NULL
;
178 #endif /* MONITOR_LSDB_CHANGE */
180 OSPF_TIMER_OFF(area
->t_opaque_lsa_self
);
181 if (area
->opaque_lsa_self
!= NULL
)
182 list_delete(&area
->opaque_lsa_self
);
186 int ospf_opaque_type11_lsa_init(struct ospf
*top
)
188 if (top
->opaque_lsa_self
!= NULL
)
189 list_delete(&top
->opaque_lsa_self
);
191 top
->opaque_lsa_self
= list_new();
192 top
->opaque_lsa_self
->del
= free_opaque_info_per_type
;
193 top
->t_opaque_lsa_self
= NULL
;
195 #ifdef MONITOR_LSDB_CHANGE
196 top
->lsdb
->new_lsa_hook
= ospf_opaque_lsa_install_hook
;
197 top
->lsdb
->del_lsa_hook
= ospf_opaque_lsa_delete_hook
;
198 #endif /* MONITOR_LSDB_CHANGE */
202 void ospf_opaque_type11_lsa_term(struct ospf
*top
)
204 #ifdef MONITOR_LSDB_CHANGE
205 top
->lsdb
->new_lsa_hook
= top
->lsdb
->del_lsa_hook
= NULL
;
206 #endif /* MONITOR_LSDB_CHANGE */
208 OSPF_TIMER_OFF(top
->t_opaque_lsa_self
);
209 if (top
->opaque_lsa_self
!= NULL
)
210 list_delete(&top
->opaque_lsa_self
);
214 static const char *ospf_opaque_type_name(uint8_t opaque_type
)
216 const char *name
= "Unknown";
218 switch (opaque_type
) {
219 case OPAQUE_TYPE_WILDCARD
: /* This is a special assignment! */
222 case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA
:
223 name
= "Traffic Engineering LSA";
225 case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC
:
226 name
= "Sycamore optical topology description";
228 case OPAQUE_TYPE_GRACE_LSA
:
231 case OPAQUE_TYPE_INTER_AS_LSA
:
232 name
= "Inter-AS TE-v2 LSA";
234 case OPAQUE_TYPE_ROUTER_INFORMATION_LSA
:
235 name
= "Router Information LSA";
237 case OPAQUE_TYPE_EXTENDED_PREFIX_LSA
:
238 name
= "Extended Prefix Opaque LSA";
240 case OPAQUE_TYPE_EXTENDED_LINK_LSA
:
241 name
= "Extended Link Opaque LSA";
244 if (OPAQUE_TYPE_RANGE_UNASSIGNED(opaque_type
))
247 uint32_t bigger_range
= opaque_type
;
249 * Get around type-limits warning: comparison is always
250 * true due to limited range of data type
252 if (OPAQUE_TYPE_RANGE_RESERVED(bigger_range
))
253 name
= "Private/Experimental";
260 /*------------------------------------------------------------------------*
261 * Followings are management functions to store user specified callbacks.
262 *------------------------------------------------------------------------*/
264 struct opaque_info_per_type
; /* Forward declaration. */
266 struct ospf_opaque_functab
{
268 struct opaque_info_per_type
*oipt
;
270 int (*new_if_hook
)(struct interface
*ifp
);
271 int (*del_if_hook
)(struct interface
*ifp
);
272 void (*ism_change_hook
)(struct ospf_interface
*oi
, int old_status
);
273 void (*nsm_change_hook
)(struct ospf_neighbor
*nbr
, int old_status
);
274 void (*config_write_router
)(struct vty
*vty
);
275 void (*config_write_if
)(struct vty
*vty
, struct interface
*ifp
);
276 void (*config_write_debug
)(struct vty
*vty
);
277 void (*show_opaque_info
)(struct vty
*vty
, struct ospf_lsa
*lsa
);
278 int (*lsa_originator
)(void *arg
);
279 struct ospf_lsa
*(*lsa_refresher
)(struct ospf_lsa
*lsa
);
280 int (*new_lsa_hook
)(struct ospf_lsa
*lsa
);
281 int (*del_lsa_hook
)(struct ospf_lsa
*lsa
);
284 /* Handle LSA-9/10/11 altogether. */
285 static struct list
*ospf_opaque_wildcard_funclist
;
286 static struct list
*ospf_opaque_type9_funclist
;
287 static struct list
*ospf_opaque_type10_funclist
;
288 static struct list
*ospf_opaque_type11_funclist
;
290 static void ospf_opaque_del_functab(void *val
)
292 XFREE(MTYPE_OSPF_OPAQUE_FUNCTAB
, val
);
296 static void ospf_opaque_funclist_init(void)
298 struct list
*funclist
;
300 funclist
= ospf_opaque_wildcard_funclist
= list_new();
301 funclist
->del
= ospf_opaque_del_functab
;
303 funclist
= ospf_opaque_type9_funclist
= list_new();
304 funclist
->del
= ospf_opaque_del_functab
;
306 funclist
= ospf_opaque_type10_funclist
= list_new();
307 funclist
->del
= ospf_opaque_del_functab
;
309 funclist
= ospf_opaque_type11_funclist
= list_new();
310 funclist
->del
= ospf_opaque_del_functab
;
314 static void ospf_opaque_funclist_term(void)
316 struct list
*funclist
;
318 funclist
= ospf_opaque_wildcard_funclist
;
319 list_delete(&funclist
);
321 funclist
= ospf_opaque_type9_funclist
;
322 list_delete(&funclist
);
324 funclist
= ospf_opaque_type10_funclist
;
325 list_delete(&funclist
);
327 funclist
= ospf_opaque_type11_funclist
;
328 list_delete(&funclist
);
332 static struct list
*ospf_get_opaque_funclist(uint8_t lsa_type
)
334 struct list
*funclist
= NULL
;
337 case OPAQUE_TYPE_WILDCARD
:
339 * This is an ugly trick to handle type-9/10/11 LSA altogether.
340 * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor
341 * an officially assigned opaque-type.
342 * Though it is possible that the value might be officially used
343 * in the future, we use it internally as a special label, for
346 funclist
= ospf_opaque_wildcard_funclist
;
348 case OSPF_OPAQUE_LINK_LSA
:
349 funclist
= ospf_opaque_type9_funclist
;
351 case OSPF_OPAQUE_AREA_LSA
:
352 funclist
= ospf_opaque_type10_funclist
;
354 case OSPF_OPAQUE_AS_LSA
:
355 funclist
= ospf_opaque_type11_funclist
;
358 flog_warn(EC_OSPF_LSA_UNEXPECTED
,
359 "ospf_get_opaque_funclist: Unexpected LSA-type(%u)",
366 /* XXX: such a huge argument list can /not/ be healthy... */
367 int ospf_register_opaque_functab(
368 uint8_t lsa_type
, uint8_t opaque_type
,
369 int (*new_if_hook
)(struct interface
*ifp
),
370 int (*del_if_hook
)(struct interface
*ifp
),
371 void (*ism_change_hook
)(struct ospf_interface
*oi
, int old_status
),
372 void (*nsm_change_hook
)(struct ospf_neighbor
*nbr
, int old_status
),
373 void (*config_write_router
)(struct vty
*vty
),
374 void (*config_write_if
)(struct vty
*vty
, struct interface
*ifp
),
375 void (*config_write_debug
)(struct vty
*vty
),
376 void (*show_opaque_info
)(struct vty
*vty
, struct ospf_lsa
*lsa
),
377 int (*lsa_originator
)(void *arg
),
378 struct ospf_lsa
*(*lsa_refresher
)(struct ospf_lsa
*lsa
),
379 int (*new_lsa_hook
)(struct ospf_lsa
*lsa
),
380 int (*del_lsa_hook
)(struct ospf_lsa
*lsa
))
382 struct list
*funclist
;
383 struct ospf_opaque_functab
*new;
385 if ((funclist
= ospf_get_opaque_funclist(lsa_type
)) == NULL
)
388 struct listnode
*node
, *nnode
;
389 struct ospf_opaque_functab
*functab
;
391 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
392 if (functab
->opaque_type
== opaque_type
) {
395 "ospf_register_opaque_functab: Duplicated entry?: lsa_type(%u), opaque_type(%u)",
396 lsa_type
, opaque_type
);
400 new = XCALLOC(MTYPE_OSPF_OPAQUE_FUNCTAB
,
401 sizeof(struct ospf_opaque_functab
));
403 new->opaque_type
= opaque_type
;
405 new->new_if_hook
= new_if_hook
;
406 new->del_if_hook
= del_if_hook
;
407 new->ism_change_hook
= ism_change_hook
;
408 new->nsm_change_hook
= nsm_change_hook
;
409 new->config_write_router
= config_write_router
;
410 new->config_write_if
= config_write_if
;
411 new->config_write_debug
= config_write_debug
;
412 new->show_opaque_info
= show_opaque_info
;
413 new->lsa_originator
= lsa_originator
;
414 new->lsa_refresher
= lsa_refresher
;
415 new->new_lsa_hook
= new_lsa_hook
;
416 new->del_lsa_hook
= del_lsa_hook
;
418 listnode_add(funclist
, new);
423 void ospf_delete_opaque_functab(uint8_t lsa_type
, uint8_t opaque_type
)
425 struct list
*funclist
;
426 struct listnode
*node
, *nnode
;
427 struct ospf_opaque_functab
*functab
;
429 if ((funclist
= ospf_get_opaque_funclist(lsa_type
)) != NULL
)
430 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
)) {
431 if (functab
->opaque_type
== opaque_type
) {
432 /* Cleanup internal control information, if it
434 if (functab
->oipt
!= NULL
) {
435 free_opaque_info_owner(functab
->oipt
);
436 free_opaque_info_per_type(
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 * Followings 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_owner(oipt
);
560 free_opaque_info_per_type(oipt
);
562 goto out
; /* This case may not exist. */
565 listnode_add(top
->opaque_lsa_self
, oipt
);
569 EC_OSPF_LSA_UNEXPECTED
,
570 "register_opaque_info_per_type: Unexpected LSA-type(%u)",
572 free_opaque_info_owner(oipt
);
573 free_opaque_info_per_type(oipt
);
575 goto out
; /* This case may not exist. */
578 oipt
->lsa_type
= new->data
->type
;
579 oipt
->opaque_type
= GET_OPAQUE_TYPE(ntohl(new->data
->id
.s_addr
));
580 oipt
->status
= PROC_NORMAL
;
581 oipt
->t_opaque_lsa_self
= NULL
;
582 oipt
->functab
= functab
;
583 functab
->oipt
= oipt
;
584 oipt
->id_list
= list_new();
585 oipt
->id_list
->del
= free_opaque_info_per_id
;
591 /* Remove "oipt" from its owner's self-originated LSA list. */
592 static void free_opaque_info_owner(void *val
)
594 struct opaque_info_per_type
*oipt
= (struct opaque_info_per_type
*)val
;
596 switch (oipt
->lsa_type
) {
597 case OSPF_OPAQUE_LINK_LSA
: {
598 struct ospf_interface
*oi
=
599 (struct ospf_interface
*)(oipt
->owner
);
600 listnode_delete(oi
->opaque_lsa_self
, oipt
);
603 case OSPF_OPAQUE_AREA_LSA
: {
604 struct ospf_area
*area
= (struct ospf_area
*)(oipt
->owner
);
605 listnode_delete(area
->opaque_lsa_self
, oipt
);
608 case OSPF_OPAQUE_AS_LSA
: {
609 struct ospf
*top
= (struct ospf
*)(oipt
->owner
);
610 listnode_delete(top
->opaque_lsa_self
, oipt
);
614 flog_warn(EC_OSPF_LSA_UNEXPECTED
,
615 "free_opaque_info_owner: Unexpected LSA-type(%u)",
617 break; /* This case may not exist. */
621 static void free_opaque_info_per_type(void *val
)
623 struct opaque_info_per_type
*oipt
= (struct opaque_info_per_type
*)val
;
624 struct opaque_info_per_id
*oipi
;
625 struct ospf_lsa
*lsa
;
626 struct listnode
*node
, *nnode
;
628 /* Control information per opaque-id may still exist. */
629 for (ALL_LIST_ELEMENTS(oipt
->id_list
, node
, nnode
, oipi
)) {
630 if ((lsa
= oipi
->lsa
) == NULL
)
632 if (IS_LSA_MAXAGE(lsa
))
634 ospf_opaque_lsa_flush_schedule(lsa
);
637 OSPF_TIMER_OFF(oipt
->t_opaque_lsa_self
);
638 list_delete(&oipt
->id_list
);
639 XFREE(MTYPE_OPAQUE_INFO_PER_TYPE
, oipt
);
643 static struct opaque_info_per_type
*
644 lookup_opaque_info_by_type(struct ospf_lsa
*lsa
)
647 struct ospf_area
*area
;
648 struct ospf_interface
*oi
;
649 struct list
*listtop
= NULL
;
650 struct listnode
*node
, *nnode
;
651 struct opaque_info_per_type
*oipt
= NULL
;
652 uint8_t key
= GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
));
654 switch (lsa
->data
->type
) {
655 case OSPF_OPAQUE_LINK_LSA
:
656 if ((oi
= lsa
->oi
) != NULL
)
657 listtop
= oi
->opaque_lsa_self
;
661 "Type-9 Opaque-LSA: Reference to OI is missing?");
663 case OSPF_OPAQUE_AREA_LSA
:
664 if ((area
= lsa
->area
) != NULL
)
665 listtop
= area
->opaque_lsa_self
;
669 "Type-10 Opaque-LSA: Reference to AREA is missing?");
671 case OSPF_OPAQUE_AS_LSA
:
672 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
673 if ((area
= lsa
->area
) != NULL
&& (top
= area
->ospf
) == NULL
) {
676 "Type-11 Opaque-LSA: Reference to OSPF is missing?");
677 break; /* Unlikely to happen. */
679 listtop
= top
->opaque_lsa_self
;
682 flog_warn(EC_OSPF_LSA_UNEXPECTED
,
683 "lookup_opaque_info_by_type: Unexpected LSA-type(%u)",
689 for (ALL_LIST_ELEMENTS(listtop
, node
, nnode
, oipt
))
690 if (oipt
->opaque_type
== key
)
696 static struct opaque_info_per_id
*
697 register_opaque_info_per_id(struct opaque_info_per_type
*oipt
,
698 struct ospf_lsa
*new)
700 struct opaque_info_per_id
*oipi
;
702 oipi
= XCALLOC(MTYPE_OPAQUE_INFO_PER_ID
,
703 sizeof(struct opaque_info_per_id
));
705 oipi
->opaque_id
= GET_OPAQUE_ID(ntohl(new->data
->id
.s_addr
));
706 oipi
->t_opaque_lsa_self
= NULL
;
707 oipi
->opqctl_type
= oipt
;
708 oipi
->lsa
= ospf_lsa_lock(new);
710 listnode_add(oipt
->id_list
, oipi
);
715 static void free_opaque_info_per_id(void *val
)
717 struct opaque_info_per_id
*oipi
= (struct opaque_info_per_id
*)val
;
719 OSPF_TIMER_OFF(oipi
->t_opaque_lsa_self
);
720 if (oipi
->lsa
!= NULL
)
721 ospf_lsa_unlock(&oipi
->lsa
);
722 XFREE(MTYPE_OPAQUE_INFO_PER_ID
, oipi
);
726 static struct opaque_info_per_id
*
727 lookup_opaque_info_by_id(struct opaque_info_per_type
*oipt
,
728 struct ospf_lsa
*lsa
)
730 struct listnode
*node
, *nnode
;
731 struct opaque_info_per_id
*oipi
;
732 uint32_t key
= GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
));
734 for (ALL_LIST_ELEMENTS(oipt
->id_list
, node
, nnode
, oipi
))
735 if (oipi
->opaque_id
== key
)
741 static struct opaque_info_per_id
*register_opaque_lsa(struct ospf_lsa
*new)
743 struct ospf_opaque_functab
*functab
;
744 struct opaque_info_per_type
*oipt
;
745 struct opaque_info_per_id
*oipi
= NULL
;
747 if ((functab
= ospf_opaque_functab_lookup(new)) == NULL
)
750 if ((oipt
= lookup_opaque_info_by_type(new)) == NULL
751 && (oipt
= register_opaque_info_per_type(functab
, new)) == NULL
)
754 if ((oipi
= register_opaque_info_per_id(oipt
, new)) == NULL
)
761 /*------------------------------------------------------------------------*
762 * Followings are (vty) configuration functions for Opaque-LSAs handling.
763 *------------------------------------------------------------------------*/
765 DEFUN (capability_opaque
,
766 capability_opaque_cmd
,
768 "Enable specific OSPF feature\n"
771 VTY_DECLVAR_INSTANCE_CONTEXT(ospf
, ospf
);
773 /* Turn on the "master switch" of opaque-lsa capability. */
774 if (!CHECK_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
)) {
775 if (IS_DEBUG_OSPF_EVENT
)
776 zlog_debug("Opaque capability: OFF -> ON");
778 SET_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
);
779 ospf_renegotiate_optional_capabilities(ospf
);
787 "OSPF specific commands\n"
788 "Enable the Opaque-LSA capability (rfc2370)\n")
790 return capability_opaque(self
, vty
, argc
, argv
);
793 DEFUN (no_capability_opaque
,
794 no_capability_opaque_cmd
,
795 "no capability opaque",
797 "Enable specific OSPF feature\n"
800 VTY_DECLVAR_INSTANCE_CONTEXT(ospf
, ospf
);
802 /* Turn off the "master switch" of opaque-lsa capability. */
803 if (CHECK_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
)) {
804 if (IS_DEBUG_OSPF_EVENT
)
805 zlog_debug("Opaque capability: ON -> OFF");
807 UNSET_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
);
808 ospf_renegotiate_optional_capabilities(ospf
);
813 DEFUN (no_ospf_opaque
,
815 "no ospf opaque-lsa",
817 "OSPF specific commands\n"
818 "Enable the Opaque-LSA capability (rfc2370)\n")
820 return no_capability_opaque(self
, vty
, argc
, argv
);
823 static void ospf_opaque_register_vty(void)
825 install_element(OSPF_NODE
, &capability_opaque_cmd
);
826 install_element(OSPF_NODE
, &no_capability_opaque_cmd
);
827 install_element(OSPF_NODE
, &ospf_opaque_cmd
);
828 install_element(OSPF_NODE
, &no_ospf_opaque_cmd
);
832 /*------------------------------------------------------------------------*
833 * Followings are collection of user-registered function callers.
834 *------------------------------------------------------------------------*/
836 static int opaque_lsa_new_if_callback(struct list
*funclist
,
837 struct interface
*ifp
)
839 struct listnode
*node
, *nnode
;
840 struct ospf_opaque_functab
*functab
;
843 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
844 if (functab
->new_if_hook
!= NULL
)
845 if ((*functab
->new_if_hook
)(ifp
) != 0)
852 static int opaque_lsa_del_if_callback(struct list
*funclist
,
853 struct interface
*ifp
)
855 struct listnode
*node
, *nnode
;
856 struct ospf_opaque_functab
*functab
;
859 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
860 if (functab
->del_if_hook
!= NULL
)
861 if ((*functab
->del_if_hook
)(ifp
) != 0)
868 static void opaque_lsa_ism_change_callback(struct list
*funclist
,
869 struct ospf_interface
*oi
,
872 struct listnode
*node
, *nnode
;
873 struct ospf_opaque_functab
*functab
;
875 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
876 if (functab
->ism_change_hook
!= NULL
)
877 (*functab
->ism_change_hook
)(oi
, old_status
);
882 static void opaque_lsa_nsm_change_callback(struct list
*funclist
,
883 struct ospf_neighbor
*nbr
,
886 struct listnode
*node
, *nnode
;
887 struct ospf_opaque_functab
*functab
;
889 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
890 if (functab
->nsm_change_hook
!= NULL
)
891 (*functab
->nsm_change_hook
)(nbr
, old_status
);
895 static void opaque_lsa_config_write_router_callback(struct list
*funclist
,
898 struct listnode
*node
, *nnode
;
899 struct ospf_opaque_functab
*functab
;
901 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
902 if (functab
->config_write_router
!= NULL
)
903 (*functab
->config_write_router
)(vty
);
907 static void opaque_lsa_config_write_if_callback(struct list
*funclist
,
909 struct interface
*ifp
)
911 struct listnode
*node
, *nnode
;
912 struct ospf_opaque_functab
*functab
;
914 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
915 if (functab
->config_write_if
!= NULL
)
916 (*functab
->config_write_if
)(vty
, ifp
);
920 static void opaque_lsa_config_write_debug_callback(struct list
*funclist
,
923 struct listnode
*node
, *nnode
;
924 struct ospf_opaque_functab
*functab
;
926 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
927 if (functab
->config_write_debug
!= NULL
)
928 (*functab
->config_write_debug
)(vty
);
932 static int opaque_lsa_originate_callback(struct list
*funclist
,
933 void *lsa_type_dependent
)
935 struct listnode
*node
, *nnode
;
936 struct ospf_opaque_functab
*functab
;
939 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
940 if (functab
->lsa_originator
!= NULL
)
941 if ((*functab
->lsa_originator
)(lsa_type_dependent
) != 0)
948 static int new_lsa_callback(struct list
*funclist
, struct ospf_lsa
*lsa
)
950 struct listnode
*node
, *nnode
;
951 struct ospf_opaque_functab
*functab
;
954 /* This function handles ALL types of LSAs, not only opaque ones. */
955 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
956 if (functab
->new_lsa_hook
!= NULL
)
957 if ((*functab
->new_lsa_hook
)(lsa
) != 0)
964 static int del_lsa_callback(struct list
*funclist
, struct ospf_lsa
*lsa
)
966 struct listnode
*node
, *nnode
;
967 struct ospf_opaque_functab
*functab
;
970 /* This function handles ALL types of LSAs, not only opaque ones. */
971 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
972 if (functab
->del_lsa_hook
!= NULL
)
973 if ((*functab
->del_lsa_hook
)(lsa
) != 0)
980 /*------------------------------------------------------------------------*
981 * Followings are glue functions to call Opaque-LSA specific processing.
982 *------------------------------------------------------------------------*/
984 int ospf_opaque_new_if(struct interface
*ifp
)
986 struct list
*funclist
;
989 funclist
= ospf_opaque_wildcard_funclist
;
990 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
993 funclist
= ospf_opaque_type9_funclist
;
994 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
997 funclist
= ospf_opaque_type10_funclist
;
998 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
1001 funclist
= ospf_opaque_type11_funclist
;
1002 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
1010 int ospf_opaque_del_if(struct interface
*ifp
)
1012 struct list
*funclist
;
1015 funclist
= ospf_opaque_wildcard_funclist
;
1016 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1019 funclist
= ospf_opaque_type9_funclist
;
1020 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1023 funclist
= ospf_opaque_type10_funclist
;
1024 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1027 funclist
= ospf_opaque_type11_funclist
;
1028 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1036 void ospf_opaque_ism_change(struct ospf_interface
*oi
, int old_status
)
1038 struct list
*funclist
;
1040 funclist
= ospf_opaque_wildcard_funclist
;
1041 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1043 funclist
= ospf_opaque_type9_funclist
;
1044 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1046 funclist
= ospf_opaque_type10_funclist
;
1047 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1049 funclist
= ospf_opaque_type11_funclist
;
1050 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1055 void ospf_opaque_nsm_change(struct ospf_neighbor
*nbr
, int old_state
)
1058 struct list
*funclist
;
1060 if ((top
= oi_to_top(nbr
->oi
)) == NULL
)
1063 if (old_state
!= NSM_Full
&& nbr
->state
== NSM_Full
) {
1064 if (CHECK_FLAG(nbr
->options
, OSPF_OPTION_O
)) {
1065 if (!CHECK_FLAG(top
->opaque
,
1066 OPAQUE_OPERATION_READY_BIT
)) {
1067 if (IS_DEBUG_OSPF_EVENT
)
1069 "Opaque-LSA: Now get operational!");
1071 SET_FLAG(top
->opaque
,
1072 OPAQUE_OPERATION_READY_BIT
);
1075 ospf_opaque_lsa_originate_schedule(nbr
->oi
, NULL
);
1077 } else if (old_state
== NSM_Full
&& nbr
->state
!= NSM_Full
) {
1080 * If no more opaque-capable full-state neighbor remains in the
1081 * flooding scope which corresponds to Opaque-LSA type, periodic
1082 * LS flooding should be stopped.
1088 funclist
= ospf_opaque_wildcard_funclist
;
1089 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1091 funclist
= ospf_opaque_type9_funclist
;
1092 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1094 funclist
= ospf_opaque_type10_funclist
;
1095 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1097 funclist
= ospf_opaque_type11_funclist
;
1098 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1104 void ospf_opaque_config_write_router(struct vty
*vty
, struct ospf
*ospf
)
1106 struct list
*funclist
;
1108 if (CHECK_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
))
1109 vty_out(vty
, " capability opaque\n");
1111 funclist
= ospf_opaque_wildcard_funclist
;
1112 opaque_lsa_config_write_router_callback(funclist
, vty
);
1114 funclist
= ospf_opaque_type9_funclist
;
1115 opaque_lsa_config_write_router_callback(funclist
, vty
);
1117 funclist
= ospf_opaque_type10_funclist
;
1118 opaque_lsa_config_write_router_callback(funclist
, vty
);
1120 funclist
= ospf_opaque_type11_funclist
;
1121 opaque_lsa_config_write_router_callback(funclist
, vty
);
1126 void ospf_opaque_config_write_if(struct vty
*vty
, struct interface
*ifp
)
1128 struct list
*funclist
;
1130 funclist
= ospf_opaque_wildcard_funclist
;
1131 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1133 funclist
= ospf_opaque_type9_funclist
;
1134 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1136 funclist
= ospf_opaque_type10_funclist
;
1137 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1139 funclist
= ospf_opaque_type11_funclist
;
1140 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1145 void ospf_opaque_config_write_debug(struct vty
*vty
)
1147 struct list
*funclist
;
1149 funclist
= ospf_opaque_wildcard_funclist
;
1150 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1152 funclist
= ospf_opaque_type9_funclist
;
1153 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1155 funclist
= ospf_opaque_type10_funclist
;
1156 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1158 funclist
= ospf_opaque_type11_funclist
;
1159 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1164 void show_opaque_info_detail(struct vty
*vty
, struct ospf_lsa
*lsa
,
1167 struct lsa_header
*lsah
= lsa
->data
;
1168 uint32_t lsid
= ntohl(lsah
->id
.s_addr
);
1169 uint8_t opaque_type
= GET_OPAQUE_TYPE(lsid
);
1170 uint32_t opaque_id
= GET_OPAQUE_ID(lsid
);
1171 struct ospf_opaque_functab
*functab
;
1173 /* Switch output functionality by vty address. */
1176 vty_out(vty
, " Opaque-Type %u (%s)\n", opaque_type
,
1177 ospf_opaque_type_name(opaque_type
));
1178 vty_out(vty
, " Opaque-ID 0x%x\n", opaque_id
);
1180 vty_out(vty
, " Opaque-Info: %u octets of data%s\n",
1181 ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
,
1182 VALID_OPAQUE_INFO_LEN(lsah
)
1184 : "(Invalid length?)");
1187 zlog_debug(" Opaque-Type %u (%s)", opaque_type
,
1188 ospf_opaque_type_name(opaque_type
));
1189 zlog_debug(" Opaque-ID 0x%x", opaque_id
);
1191 zlog_debug(" Opaque-Info: %u octets of data%s",
1192 ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
,
1193 VALID_OPAQUE_INFO_LEN(lsah
) ? ""
1194 : "(Invalid length?)");
1197 /* Call individual output functions. */
1198 if ((functab
= ospf_opaque_functab_lookup(lsa
)) != NULL
)
1199 if (functab
->show_opaque_info
!= NULL
)
1200 (*functab
->show_opaque_info
)(vty
, lsa
);
1205 void ospf_opaque_lsa_dump(struct stream
*s
, uint16_t length
)
1207 struct ospf_lsa lsa
;
1209 lsa
.data
= (struct lsa_header
*)stream_pnt(s
);
1210 show_opaque_info_detail(NULL
, &lsa
, NULL
);
1214 static int ospf_opaque_lsa_install_hook(struct ospf_lsa
*lsa
)
1216 struct list
*funclist
;
1220 * Some Opaque-LSA user may want to monitor every LSA installation
1221 * into the LSDB, regardless with target LSA type.
1223 funclist
= ospf_opaque_wildcard_funclist
;
1224 if (new_lsa_callback(funclist
, lsa
) != 0)
1227 funclist
= ospf_opaque_type9_funclist
;
1228 if (new_lsa_callback(funclist
, lsa
) != 0)
1231 funclist
= ospf_opaque_type10_funclist
;
1232 if (new_lsa_callback(funclist
, lsa
) != 0)
1235 funclist
= ospf_opaque_type11_funclist
;
1236 if (new_lsa_callback(funclist
, lsa
) != 0)
1244 static int ospf_opaque_lsa_delete_hook(struct ospf_lsa
*lsa
)
1246 struct list
*funclist
;
1250 * Some Opaque-LSA user may want to monitor every LSA deletion
1251 * from the LSDB, regardless with target LSA type.
1253 funclist
= ospf_opaque_wildcard_funclist
;
1254 if (del_lsa_callback(funclist
, lsa
) != 0)
1257 funclist
= ospf_opaque_type9_funclist
;
1258 if (del_lsa_callback(funclist
, lsa
) != 0)
1261 funclist
= ospf_opaque_type10_funclist
;
1262 if (del_lsa_callback(funclist
, lsa
) != 0)
1265 funclist
= ospf_opaque_type11_funclist
;
1266 if (del_lsa_callback(funclist
, lsa
) != 0)
1274 /*------------------------------------------------------------------------*
1275 * Followings are Opaque-LSA origination/refresh management functions.
1276 *------------------------------------------------------------------------*/
1278 static int ospf_opaque_type9_lsa_originate(struct thread
*t
);
1279 static int ospf_opaque_type10_lsa_originate(struct thread
*t
);
1280 static int ospf_opaque_type11_lsa_originate(struct thread
*t
);
1281 static void ospf_opaque_lsa_reoriginate_resume(struct list
*listtop
, void *arg
);
1283 void ospf_opaque_lsa_originate_schedule(struct ospf_interface
*oi
, int *delay0
)
1286 struct ospf_area
*area
;
1287 struct listnode
*node
, *nnode
;
1288 struct opaque_info_per_type
*oipt
;
1291 if ((top
= oi_to_top(oi
)) == NULL
|| (area
= oi
->area
) == NULL
) {
1292 if (IS_DEBUG_OSPF_EVENT
)
1294 "ospf_opaque_lsa_originate_schedule: Invalid argument?");
1298 /* It may not a right time to schedule origination now. */
1299 if (!CHECK_FLAG(top
->opaque
, OPAQUE_OPERATION_READY_BIT
)) {
1300 if (IS_DEBUG_OSPF_EVENT
)
1302 "ospf_opaque_lsa_originate_schedule: Not operational.");
1303 return; /* This is not an error. */
1310 * There might be some entries that have been waiting for triggering
1311 * of per opaque-type re-origination get resumed.
1313 ospf_opaque_lsa_reoriginate_resume(oi
->opaque_lsa_self
, (void *)oi
);
1314 ospf_opaque_lsa_reoriginate_resume(area
->opaque_lsa_self
, (void *)area
);
1315 ospf_opaque_lsa_reoriginate_resume(top
->opaque_lsa_self
, (void *)top
);
1318 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1320 if (!list_isempty(ospf_opaque_type9_funclist
)
1321 && list_isempty(oi
->opaque_lsa_self
)
1322 && oi
->t_opaque_lsa_self
== NULL
) {
1323 if (IS_DEBUG_OSPF_EVENT
)
1325 "Schedule Type-9 Opaque-LSA origination in %d ms later.",
1327 oi
->t_opaque_lsa_self
= NULL
;
1328 thread_add_timer_msec(master
, ospf_opaque_type9_lsa_originate
,
1329 oi
, delay
, &oi
->t_opaque_lsa_self
);
1330 delay
+= top
->min_ls_interval
;
1333 if (!list_isempty(ospf_opaque_type10_funclist
)
1334 && list_isempty(area
->opaque_lsa_self
)
1335 && area
->t_opaque_lsa_self
== NULL
) {
1337 * One AREA may contain multiple OIs, but above 2nd and 3rd
1338 * conditions prevent from scheduling the originate function
1341 if (IS_DEBUG_OSPF_EVENT
)
1343 "Schedule Type-10 Opaque-LSA origination in %d ms later.",
1345 area
->t_opaque_lsa_self
= NULL
;
1346 thread_add_timer_msec(master
, ospf_opaque_type10_lsa_originate
,
1347 area
, delay
, &area
->t_opaque_lsa_self
);
1348 delay
+= top
->min_ls_interval
;
1351 if (!list_isempty(ospf_opaque_type11_funclist
)
1352 && list_isempty(top
->opaque_lsa_self
)
1353 && top
->t_opaque_lsa_self
== NULL
) {
1355 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1356 * conditions prevent from scheduling the originate function
1359 if (IS_DEBUG_OSPF_EVENT
)
1361 "Schedule Type-11 Opaque-LSA origination in %d ms later.",
1363 top
->t_opaque_lsa_self
= NULL
;
1364 thread_add_timer_msec(master
, ospf_opaque_type11_lsa_originate
,
1365 top
, delay
, &top
->t_opaque_lsa_self
);
1366 delay
+= top
->min_ls_interval
;
1370 * Following section treats a special situation that this node's
1371 * opaque capability has changed as "ON -> OFF -> ON".
1373 if (!list_isempty(ospf_opaque_type9_funclist
)
1374 && !list_isempty(oi
->opaque_lsa_self
)) {
1375 for (ALL_LIST_ELEMENTS(oi
->opaque_lsa_self
, node
, nnode
,
1378 * removed the test for
1379 * (! list_isempty (oipt->id_list)) * Handler is
1381 * because opaque cababilities ON -> OFF -> ON result in
1382 * list_isempty (oipt->id_list)
1385 if (oipt
->t_opaque_lsa_self
1386 != NULL
/* Waiting for a thread call. */
1387 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1392 ospf_opaque_lsa_reoriginate_schedule(
1393 (void *)oi
, OSPF_OPAQUE_LINK_LSA
,
1398 if (!list_isempty(ospf_opaque_type10_funclist
)
1399 && !list_isempty(area
->opaque_lsa_self
)) {
1400 for (ALL_LIST_ELEMENTS(area
->opaque_lsa_self
, node
, nnode
,
1403 * removed the test for
1404 * (! list_isempty (oipt->id_list)) * Handler is
1406 * because opaque cababilities ON -> OFF -> ON result in
1407 * list_isempty (oipt->id_list)
1410 if (oipt
->t_opaque_lsa_self
1411 != NULL
/* Waiting for a thread call. */
1412 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1417 ospf_opaque_lsa_reoriginate_schedule(
1418 (void *)area
, OSPF_OPAQUE_AREA_LSA
,
1423 if (!list_isempty(ospf_opaque_type11_funclist
)
1424 && !list_isempty(top
->opaque_lsa_self
)) {
1425 for (ALL_LIST_ELEMENTS(top
->opaque_lsa_self
, node
, nnode
,
1428 * removed the test for
1429 * (! list_isempty (oipt->id_list)) * Handler is
1431 * because opaque cababilities ON -> OFF -> ON result in
1432 * list_isempty (oipt->id_list)
1435 if (oipt
->t_opaque_lsa_self
1436 != NULL
/* Waiting for a thread call. */
1437 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1442 ospf_opaque_lsa_reoriginate_schedule((void *)top
,
1452 static int ospf_opaque_type9_lsa_originate(struct thread
*t
)
1454 struct ospf_interface
*oi
;
1458 oi
->t_opaque_lsa_self
= NULL
;
1460 if (IS_DEBUG_OSPF_EVENT
)
1461 zlog_debug("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
1464 rc
= opaque_lsa_originate_callback(ospf_opaque_type9_funclist
, oi
);
1469 static int ospf_opaque_type10_lsa_originate(struct thread
*t
)
1471 struct ospf_area
*area
;
1474 area
= THREAD_ARG(t
);
1475 area
->t_opaque_lsa_self
= NULL
;
1477 if (IS_DEBUG_OSPF_EVENT
)
1479 "Timer[Type10-LSA]: Originate Opaque-LSAs for Area %pI4",
1482 rc
= opaque_lsa_originate_callback(ospf_opaque_type10_funclist
, area
);
1487 static int 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 rc
= opaque_lsa_originate_callback(ospf_opaque_type11_funclist
, top
);
1504 static void ospf_opaque_lsa_reoriginate_resume(struct list
*listtop
, void *arg
)
1506 struct listnode
*node
, *nnode
;
1507 struct opaque_info_per_type
*oipt
;
1508 struct ospf_opaque_functab
*functab
;
1510 if (listtop
== NULL
)
1514 * Pickup oipt entries those which in SUSPEND status, and give
1515 * them a chance to start re-origination now.
1517 for (ALL_LIST_ELEMENTS(listtop
, node
, nnode
, oipt
)) {
1518 if (oipt
->status
!= PROC_SUSPEND
)
1521 oipt
->status
= PROC_NORMAL
;
1523 if ((functab
= oipt
->functab
) == NULL
1524 || functab
->lsa_originator
== NULL
)
1527 if ((*functab
->lsa_originator
)(arg
) != 0) {
1530 "ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)",
1540 struct ospf_lsa
*ospf_opaque_lsa_install(struct ospf_lsa
*lsa
, int rt_recalc
)
1542 struct ospf_lsa
*new = NULL
;
1543 struct opaque_info_per_type
*oipt
;
1544 struct opaque_info_per_id
*oipi
;
1547 /* Don't take "rt_recalc" into consideration for now. */ /* XXX */
1549 if (!IS_LSA_SELF(lsa
)) {
1550 new = lsa
; /* Don't touch this LSA. */
1554 if (IS_DEBUG_OSPF(lsa
, LSA_INSTALL
))
1556 "Install Type-%u Opaque-LSA: [opaque-type=%u, opaque-id=%x]",
1558 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
1559 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
1561 /* Replace the existing lsa with the new one. */
1562 if ((oipt
= lookup_opaque_info_by_type(lsa
)) != NULL
1563 && (oipi
= lookup_opaque_info_by_id(oipt
, lsa
)) != NULL
) {
1564 ospf_lsa_unlock(&oipi
->lsa
);
1565 oipi
->lsa
= ospf_lsa_lock(lsa
);
1567 /* Register the new lsa entry */
1568 else if (register_opaque_lsa(lsa
) == NULL
) {
1569 flog_warn(EC_OSPF_LSA
,
1570 "ospf_opaque_lsa_install: register_opaque_lsa() ?");
1575 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1576 * for periodic refresh of self-originated Opaque-LSAs.
1578 switch (lsa
->data
->type
) {
1579 case OSPF_OPAQUE_LINK_LSA
:
1580 if ((top
= oi_to_top(lsa
->oi
)) == NULL
) {
1581 /* Above conditions must have passed. */
1582 flog_warn(EC_OSPF_LSA
,
1583 "ospf_opaque_lsa_install: Something wrong?");
1587 case OSPF_OPAQUE_AREA_LSA
:
1588 if (lsa
->area
== NULL
|| (top
= lsa
->area
->ospf
) == NULL
) {
1589 /* Above conditions must have passed. */
1590 flog_warn(EC_OSPF_LSA
,
1591 "ospf_opaque_lsa_install: Something wrong?");
1595 case OSPF_OPAQUE_AS_LSA
:
1596 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
1597 if (lsa
->area
!= NULL
&& (top
= lsa
->area
->ospf
) == NULL
) {
1598 /* Above conditions must have passed. */
1599 flog_warn(EC_OSPF_LSA
,
1600 "ospf_opaque_lsa_install: Something wrong?");
1605 flog_warn(EC_OSPF_LSA_UNEXPECTED
,
1606 "ospf_opaque_lsa_install: Unexpected LSA-type(%u)",
1611 ospf_refresher_register_lsa(top
, lsa
);
1618 struct ospf_lsa
*ospf_opaque_lsa_refresh(struct ospf_lsa
*lsa
)
1621 struct ospf_opaque_functab
*functab
;
1622 struct ospf_lsa
*new = NULL
;
1624 ospf
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
1626 if ((functab
= ospf_opaque_functab_lookup(lsa
)) == NULL
1627 || functab
->lsa_refresher
== NULL
) {
1629 * Though this LSA seems to have originated on this node, the
1630 * handling module for this "lsa-type and opaque-type" was
1631 * already deleted sometime ago.
1632 * Anyway, this node still has a responsibility to flush this
1633 * LSA from the routing domain.
1635 if (IS_DEBUG_OSPF_EVENT
)
1636 zlog_debug("LSA[Type%d:%pI4]: Flush stray Opaque-LSA",
1637 lsa
->data
->type
, &lsa
->data
->id
);
1639 lsa
->data
->ls_age
= htons(OSPF_LSA_MAXAGE
);
1640 ospf_lsa_flush(ospf
, lsa
);
1642 new = (*functab
->lsa_refresher
)(lsa
);
1647 /*------------------------------------------------------------------------*
1648 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1649 * triggered by external interventions (vty session, signaling, etc).
1650 *------------------------------------------------------------------------*/
1652 #define OSPF_OPAQUE_TIMER_ON(T,F,L,V) thread_add_timer_msec (master, (F), (L), (V), &(T))
1654 static struct ospf_lsa
*pseudo_lsa(struct ospf_interface
*oi
,
1655 struct ospf_area
*area
, uint8_t lsa_type
,
1656 uint8_t opaque_type
);
1657 static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread
*t
);
1658 static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread
*t
);
1659 static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread
*t
);
1660 static int ospf_opaque_lsa_refresh_timer(struct thread
*t
);
1662 void ospf_opaque_lsa_reoriginate_schedule(void *lsa_type_dependent
,
1663 uint8_t lsa_type
, uint8_t opaque_type
)
1665 struct ospf
*top
= NULL
;
1666 struct ospf_area dummy
, *area
= NULL
;
1667 struct ospf_interface
*oi
= NULL
;
1669 struct ospf_lsa
*lsa
;
1670 struct opaque_info_per_type
*oipt
;
1671 int (*func
)(struct thread
* t
) = NULL
;
1675 case OSPF_OPAQUE_LINK_LSA
:
1676 if ((oi
= (struct ospf_interface
*)lsa_type_dependent
)
1680 "ospf_opaque_lsa_reoriginate_schedule: Type-9 Opaque-LSA: Invalid parameter?");
1683 if ((top
= oi_to_top(oi
)) == NULL
) {
1686 "ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1690 if (!list_isempty(ospf_opaque_type9_funclist
)
1691 && list_isempty(oi
->opaque_lsa_self
)
1692 && oi
->t_opaque_lsa_self
!= NULL
) {
1695 "Type-9 Opaque-LSA (opaque_type=%u): Common origination for OI(%s) has already started",
1696 opaque_type
, IF_NAME(oi
));
1699 func
= ospf_opaque_type9_lsa_reoriginate_timer
;
1701 case OSPF_OPAQUE_AREA_LSA
:
1702 if ((area
= (struct ospf_area
*)lsa_type_dependent
) == NULL
) {
1705 "ospf_opaque_lsa_reoriginate_schedule: Type-10 Opaque-LSA: Invalid parameter?");
1708 if ((top
= area
->ospf
) == NULL
) {
1711 "ospf_opaque_lsa_reoriginate_schedule: AREA(%pI4) -> TOP?",
1715 if (!list_isempty(ospf_opaque_type10_funclist
)
1716 && list_isempty(area
->opaque_lsa_self
)
1717 && area
->t_opaque_lsa_self
!= NULL
) {
1720 "Type-10 Opaque-LSA (opaque_type=%u): Common origination for AREA(%pI4) has already started",
1721 opaque_type
, &area
->area_id
);
1724 func
= ospf_opaque_type10_lsa_reoriginate_timer
;
1726 case OSPF_OPAQUE_AS_LSA
:
1727 if ((top
= (struct ospf
*)lsa_type_dependent
) == NULL
) {
1730 "ospf_opaque_lsa_reoriginate_schedule: Type-11 Opaque-LSA: Invalid parameter?");
1733 if (!list_isempty(ospf_opaque_type11_funclist
)
1734 && list_isempty(top
->opaque_lsa_self
)
1735 && top
->t_opaque_lsa_self
!= NULL
) {
1738 "Type-11 Opaque-LSA (opaque_type=%u): Common origination has already started",
1743 /* Fake "area" to pass "ospf" to a lookup function later. */
1747 func
= ospf_opaque_type11_lsa_reoriginate_timer
;
1751 EC_OSPF_LSA_UNEXPECTED
,
1752 "ospf_opaque_lsa_reoriginate_schedule: Unexpected LSA-type(%u)",
1757 /* It may not a right time to schedule reorigination now. */
1758 if (!CHECK_FLAG(top
->opaque
, OPAQUE_OPERATION_READY_BIT
)) {
1759 if (IS_DEBUG_OSPF_EVENT
)
1761 "ospf_opaque_lsa_reoriginate_schedule: Not operational.");
1762 goto out
; /* This is not an error. */
1765 /* Generate a dummy lsa to be passed for a lookup function. */
1766 lsa
= pseudo_lsa(oi
, area
, lsa_type
, opaque_type
);
1767 lsa
->vrf_id
= top
->vrf_id
;
1769 if ((oipt
= lookup_opaque_info_by_type(lsa
)) == NULL
) {
1770 struct ospf_opaque_functab
*functab
;
1771 if ((functab
= ospf_opaque_functab_lookup(lsa
)) == NULL
) {
1774 "ospf_opaque_lsa_reoriginate_schedule: No associated function?: lsa_type(%u), opaque_type(%u)",
1775 lsa_type
, opaque_type
);
1778 if ((oipt
= register_opaque_info_per_type(functab
, lsa
))
1782 "ospf_opaque_lsa_reoriginate_schedule: Cannot get a control info?: lsa_type(%u), opaque_type(%u)",
1783 lsa_type
, opaque_type
);
1788 if (oipt
->t_opaque_lsa_self
!= NULL
) {
1789 if (IS_DEBUG_OSPF_EVENT
)
1791 "Type-%u Opaque-LSA has already scheduled to RE-ORIGINATE: [opaque-type=%u]",
1793 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)));
1798 * Different from initial origination time, in which various conditions
1799 * (opaque capability, neighbor status etc) are assured by caller of
1800 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1801 * it is highly possible that these conditions might not be satisfied
1802 * at the time of re-origination function is to be called.
1804 delay
= top
->min_ls_interval
; /* XXX */
1806 if (IS_DEBUG_OSPF_EVENT
)
1808 "Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d ms later: [opaque-type=%u]",
1810 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)));
1812 OSPF_OPAQUE_TIMER_ON(oipt
->t_opaque_lsa_self
, func
, oipt
, delay
);
1818 static struct ospf_lsa
*pseudo_lsa(struct ospf_interface
*oi
,
1819 struct ospf_area
*area
, uint8_t lsa_type
,
1820 uint8_t opaque_type
)
1822 static struct ospf_lsa lsa
= {0};
1823 static struct lsa_header lsah
= {0};
1829 lsa
.vrf_id
= VRF_DEFAULT
;
1831 lsah
.type
= lsa_type
;
1832 tmp
= SET_OPAQUE_LSID(opaque_type
, 0); /* Opaque-ID is unused here. */
1833 lsah
.id
.s_addr
= htonl(tmp
);
1838 static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread
*t
)
1840 struct opaque_info_per_type
*oipt
;
1841 struct ospf_opaque_functab
*functab
;
1843 struct ospf_interface
*oi
;
1846 oipt
= THREAD_ARG(t
);
1847 oipt
->t_opaque_lsa_self
= NULL
;
1849 if ((functab
= oipt
->functab
) == NULL
1850 || functab
->lsa_originator
== NULL
) {
1853 "ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1857 oi
= (struct ospf_interface
*)oipt
->owner
;
1858 if ((top
= oi_to_top(oi
)) == NULL
) {
1861 "ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1865 if (!CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)
1866 || !ospf_if_is_enable(oi
)
1867 || ospf_nbr_count_opaque_capable(oi
) == 0) {
1868 if (IS_DEBUG_OSPF_EVENT
)
1870 "Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...",
1873 oipt
->status
= PROC_SUSPEND
;
1878 if (IS_DEBUG_OSPF_EVENT
)
1880 "Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)",
1881 oipt
->opaque_type
, IF_NAME(oi
));
1883 rc
= (*functab
->lsa_originator
)(oi
);
1888 static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread
*t
)
1890 struct opaque_info_per_type
*oipt
;
1891 struct ospf_opaque_functab
*functab
;
1892 struct listnode
*node
, *nnode
;
1894 struct ospf_area
*area
;
1895 struct ospf_interface
*oi
;
1898 oipt
= THREAD_ARG(t
);
1899 oipt
->t_opaque_lsa_self
= NULL
;
1901 if ((functab
= oipt
->functab
) == NULL
1902 || functab
->lsa_originator
== NULL
) {
1905 "ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1909 area
= (struct ospf_area
*)oipt
->owner
;
1910 if (area
== NULL
|| (top
= area
->ospf
) == NULL
) {
1913 "ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1917 /* There must be at least one "opaque-capable, full-state" neighbor. */
1919 for (ALL_LIST_ELEMENTS(area
->oiflist
, node
, nnode
, oi
)) {
1920 if ((n
= ospf_nbr_count_opaque_capable(oi
)) > 0)
1924 if (n
== 0 || !CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)) {
1925 if (IS_DEBUG_OSPF_EVENT
)
1927 "Suspend re-origination of Type-10 Opaque-LSAs (opaque-type=%u) for a while...",
1930 oipt
->status
= PROC_SUSPEND
;
1935 if (IS_DEBUG_OSPF_EVENT
)
1937 "Timer[Type10-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for Area %pI4",
1938 oipt
->opaque_type
, &area
->area_id
);
1940 rc
= (*functab
->lsa_originator
)(area
);
1945 static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread
*t
)
1947 struct opaque_info_per_type
*oipt
;
1948 struct ospf_opaque_functab
*functab
;
1952 oipt
= THREAD_ARG(t
);
1953 oipt
->t_opaque_lsa_self
= NULL
;
1955 if ((functab
= oipt
->functab
) == NULL
1956 || functab
->lsa_originator
== NULL
) {
1959 "ospf_opaque_type11_lsa_reoriginate_timer: No associated function?");
1963 if ((top
= (struct ospf
*)oipt
->owner
) == NULL
) {
1966 "ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1970 if (!CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)) {
1971 if (IS_DEBUG_OSPF_EVENT
)
1973 "Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...",
1976 oipt
->status
= PROC_SUSPEND
;
1981 if (IS_DEBUG_OSPF_EVENT
)
1983 "Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).",
1986 rc
= (*functab
->lsa_originator
)(top
);
1991 void ospf_opaque_lsa_refresh_schedule(struct ospf_lsa
*lsa0
)
1993 struct opaque_info_per_type
*oipt
;
1994 struct opaque_info_per_id
*oipi
;
1995 struct ospf_lsa
*lsa
;
1999 if ((oipt
= lookup_opaque_info_by_type(lsa0
)) == NULL
2000 || (oipi
= lookup_opaque_info_by_id(oipt
, lsa0
)) == NULL
) {
2003 "ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
2007 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2008 if ((lsa
= oipi
->lsa
) == NULL
) {
2009 flog_warn(EC_OSPF_LSA
,
2010 "ospf_opaque_lsa_refresh_schedule: Something wrong?");
2014 if (oipi
->t_opaque_lsa_self
!= NULL
) {
2015 if (IS_DEBUG_OSPF_EVENT
)
2017 "Type-%u Opaque-LSA has already scheduled to REFRESH: [opaque-type=%u, opaque-id=%x]",
2019 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
2020 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
2024 /* Delete this lsa from neighbor retransmit-list. */
2025 switch (lsa
->data
->type
) {
2026 case OSPF_OPAQUE_LINK_LSA
:
2027 case OSPF_OPAQUE_AREA_LSA
:
2028 ospf_ls_retransmit_delete_nbr_area(lsa
->area
, lsa
);
2030 case OSPF_OPAQUE_AS_LSA
:
2031 top
= ospf_lookup_by_vrf_id(lsa0
->vrf_id
);
2032 if ((lsa0
->area
!= NULL
) && (lsa0
->area
->ospf
!= NULL
))
2033 top
= lsa0
->area
->ospf
;
2034 ospf_ls_retransmit_delete_nbr_as(top
, lsa
);
2038 EC_OSPF_LSA_UNEXPECTED
,
2039 "ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)",
2044 delay
= ospf_lsa_refresh_delay(lsa
);
2046 if (IS_DEBUG_OSPF_EVENT
)
2048 "Schedule Type-%u Opaque-LSA to REFRESH in %d sec later: [opaque-type=%u, opaque-id=%x]",
2049 lsa
->data
->type
, delay
,
2050 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
2051 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
2053 OSPF_OPAQUE_TIMER_ON(oipi
->t_opaque_lsa_self
,
2054 ospf_opaque_lsa_refresh_timer
, oipi
, delay
* 1000);
2059 static int ospf_opaque_lsa_refresh_timer(struct thread
*t
)
2061 struct opaque_info_per_id
*oipi
;
2062 struct ospf_opaque_functab
*functab
;
2063 struct ospf_lsa
*lsa
;
2065 if (IS_DEBUG_OSPF_EVENT
)
2066 zlog_debug("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
2068 oipi
= THREAD_ARG(t
);
2069 oipi
->t_opaque_lsa_self
= NULL
;
2071 if ((lsa
= oipi
->lsa
) != NULL
)
2072 if ((functab
= oipi
->opqctl_type
->functab
) != NULL
)
2073 if (functab
->lsa_refresher
!= NULL
)
2074 (*functab
->lsa_refresher
)(lsa
);
2079 void ospf_opaque_lsa_flush_schedule(struct ospf_lsa
*lsa0
)
2081 struct opaque_info_per_type
*oipt
;
2082 struct opaque_info_per_id
*oipi
;
2083 struct ospf_lsa
*lsa
;
2086 top
= ospf_lookup_by_vrf_id(lsa0
->vrf_id
);
2088 if ((oipt
= lookup_opaque_info_by_type(lsa0
)) == NULL
2089 || (oipi
= lookup_opaque_info_by_id(oipt
, lsa0
)) == NULL
) {
2090 flog_warn(EC_OSPF_LSA
,
2091 "ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2095 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2096 if ((lsa
= oipi
->lsa
) == NULL
) {
2097 flog_warn(EC_OSPF_LSA
,
2098 "ospf_opaque_lsa_flush_schedule: Something wrong?");
2102 /* Delete this lsa from neighbor retransmit-list. */
2103 switch (lsa
->data
->type
) {
2104 case OSPF_OPAQUE_LINK_LSA
:
2105 case OSPF_OPAQUE_AREA_LSA
:
2106 ospf_ls_retransmit_delete_nbr_area(lsa
->area
, lsa
);
2108 case OSPF_OPAQUE_AS_LSA
:
2109 if ((lsa0
->area
!= NULL
) && (lsa0
->area
->ospf
!= NULL
))
2110 top
= lsa0
->area
->ospf
;
2111 ospf_ls_retransmit_delete_nbr_as(top
, lsa
);
2115 EC_OSPF_LSA_UNEXPECTED
,
2116 "ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)",
2121 /* Dequeue listnode entry from the list. */
2122 listnode_delete(oipt
->id_list
, oipi
);
2124 /* Disassociate internal control information with the given lsa. */
2125 free_opaque_info_per_id((void *)oipi
);
2127 /* Force given lsa's age to MaxAge. */
2128 lsa
->data
->ls_age
= htons(OSPF_LSA_MAXAGE
);
2130 if (IS_DEBUG_OSPF_EVENT
)
2132 "Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]",
2134 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
2135 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
2137 /* This lsa will be flushed and removed eventually. */
2138 ospf_lsa_flush(top
, lsa
);
2144 void ospf_opaque_self_originated_lsa_received(struct ospf_neighbor
*nbr
,
2145 struct ospf_lsa
*lsa
)
2149 if ((top
= oi_to_top(nbr
->oi
)) == NULL
)
2153 * Since these LSA entries are not yet installed into corresponding
2154 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2156 lsa
->data
->ls_age
= htons(OSPF_LSA_MAXAGE
);
2157 switch (lsa
->data
->type
) {
2158 case OSPF_OPAQUE_LINK_LSA
:
2159 ospf_flood_through_area(nbr
->oi
->area
, NULL
/*inbr*/, lsa
);
2161 case OSPF_OPAQUE_AREA_LSA
:
2162 ospf_flood_through_area(nbr
->oi
->area
, NULL
/*inbr*/, lsa
);
2164 case OSPF_OPAQUE_AS_LSA
:
2165 ospf_flood_through_as(top
, NULL
/*inbr*/, lsa
);
2169 EC_OSPF_LSA_UNEXPECTED
,
2170 "ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)",
2174 ospf_lsa_discard(lsa
); /* List "lsas" will be deleted by caller. */
2177 /*------------------------------------------------------------------------*
2178 * Followings are util functions; probably be used by Opaque-LSAs only...
2179 *------------------------------------------------------------------------*/
2181 struct ospf
*oi_to_top(struct ospf_interface
*oi
)
2183 struct ospf
*top
= NULL
;
2184 struct ospf_area
*area
;
2186 if (oi
== NULL
|| (area
= oi
->area
) == NULL
2187 || (top
= area
->ospf
) == NULL
)
2188 flog_warn(EC_OSPF_LSA
,
2189 "Broken relationship for \"OI -> AREA -> OSPF\"?");