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
19 * along with GNU Zebra; see the file COPYING. If not, write to the Free
20 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
37 #include "sockunion.h" /* for inet_aton() */
39 #include "ospfd/ospfd.h"
40 #include "ospfd/ospf_interface.h"
41 #include "ospfd/ospf_ism.h"
42 #include "ospfd/ospf_asbr.h"
43 #include "ospfd/ospf_lsa.h"
44 #include "ospfd/ospf_lsdb.h"
45 #include "ospfd/ospf_neighbor.h"
46 #include "ospfd/ospf_nsm.h"
47 #include "ospfd/ospf_flood.h"
48 #include "ospfd/ospf_packet.h"
49 #include "ospfd/ospf_spf.h"
50 #include "ospfd/ospf_dump.h"
51 #include "ospfd/ospf_route.h"
52 #include "ospfd/ospf_ase.h"
53 #include "ospfd/ospf_zebra.h"
55 DEFINE_MTYPE_STATIC(OSPFD
, OSPF_OPAQUE_FUNCTAB
, "OSPF opaque function table")
56 DEFINE_MTYPE_STATIC(OSPFD
, OPAQUE_INFO_PER_TYPE
, "OSPF opaque per-type info")
57 DEFINE_MTYPE_STATIC(OSPFD
, OPAQUE_INFO_PER_ID
, "OSPF opaque per-ID info")
59 /*------------------------------------------------------------------------*
60 * Followings are initialize/terminate functions for Opaque-LSAs handling.
61 *------------------------------------------------------------------------*/
63 #include "ospfd/ospf_te.h"
64 #include "ospfd/ospf_ri.h"
66 #ifdef SUPPORT_OSPF_API
67 int ospf_apiserver_init(void);
68 void ospf_apiserver_term(void);
69 /* Init apiserver? It's disabled by default. */
70 int ospf_apiserver_enable
;
71 #endif /* SUPPORT_OSPF_API */
73 static void ospf_opaque_register_vty(void);
74 static void ospf_opaque_funclist_init(void);
75 static void ospf_opaque_funclist_term(void);
76 static void free_opaque_info_per_type(void *val
);
77 static void free_opaque_info_per_id(void *val
);
78 static int ospf_opaque_lsa_install_hook(struct ospf_lsa
*lsa
);
79 static int ospf_opaque_lsa_delete_hook(struct ospf_lsa
*lsa
);
81 void ospf_opaque_init(void)
83 ospf_opaque_register_vty();
84 ospf_opaque_funclist_init();
86 if (ospf_mpls_te_init() != 0)
89 if (ospf_router_info_init() != 0)
92 #ifdef SUPPORT_OSPF_API
93 if ((ospf_apiserver_enable
) && (ospf_apiserver_init() != 0))
95 #endif /* SUPPORT_OSPF_API */
100 void ospf_opaque_term(void)
104 ospf_router_info_term();
106 #ifdef SUPPORT_OSPF_API
107 ospf_apiserver_term();
108 #endif /* SUPPORT_OSPF_API */
110 ospf_opaque_funclist_term();
114 int ospf_opaque_type9_lsa_init(struct ospf_interface
*oi
)
116 if (oi
->opaque_lsa_self
!= NULL
)
117 list_delete(oi
->opaque_lsa_self
);
119 oi
->opaque_lsa_self
= list_new();
120 oi
->opaque_lsa_self
->del
= free_opaque_info_per_type
;
121 oi
->t_opaque_lsa_self
= NULL
;
125 void ospf_opaque_type9_lsa_term(struct ospf_interface
*oi
)
127 OSPF_TIMER_OFF(oi
->t_opaque_lsa_self
);
128 if (oi
->opaque_lsa_self
!= NULL
)
129 list_delete(oi
->opaque_lsa_self
);
130 oi
->opaque_lsa_self
= NULL
;
134 int ospf_opaque_type10_lsa_init(struct ospf_area
*area
)
136 if (area
->opaque_lsa_self
!= NULL
)
137 list_delete(area
->opaque_lsa_self
);
139 area
->opaque_lsa_self
= list_new();
140 area
->opaque_lsa_self
->del
= free_opaque_info_per_type
;
141 area
->t_opaque_lsa_self
= NULL
;
143 #ifdef MONITOR_LSDB_CHANGE
144 area
->lsdb
->new_lsa_hook
= ospf_opaque_lsa_install_hook
;
145 area
->lsdb
->del_lsa_hook
= ospf_opaque_lsa_delete_hook
;
146 #endif /* MONITOR_LSDB_CHANGE */
150 void ospf_opaque_type10_lsa_term(struct ospf_area
*area
)
152 #ifdef MONITOR_LSDB_CHANGE
153 area
->lsdb
->new_lsa_hook
= area
->lsdb
->del_lsa_hook
= NULL
;
154 #endif /* MONITOR_LSDB_CHANGE */
156 OSPF_TIMER_OFF(area
->t_opaque_lsa_self
);
157 if (area
->opaque_lsa_self
!= NULL
)
158 list_delete(area
->opaque_lsa_self
);
159 area
->opaque_lsa_self
= NULL
;
163 int ospf_opaque_type11_lsa_init(struct ospf
*top
)
165 if (top
->opaque_lsa_self
!= NULL
)
166 list_delete(top
->opaque_lsa_self
);
168 top
->opaque_lsa_self
= list_new();
169 top
->opaque_lsa_self
->del
= free_opaque_info_per_type
;
170 top
->t_opaque_lsa_self
= NULL
;
172 #ifdef MONITOR_LSDB_CHANGE
173 top
->lsdb
->new_lsa_hook
= ospf_opaque_lsa_install_hook
;
174 top
->lsdb
->del_lsa_hook
= ospf_opaque_lsa_delete_hook
;
175 #endif /* MONITOR_LSDB_CHANGE */
179 void ospf_opaque_type11_lsa_term(struct ospf
*top
)
181 #ifdef MONITOR_LSDB_CHANGE
182 top
->lsdb
->new_lsa_hook
= top
->lsdb
->del_lsa_hook
= NULL
;
183 #endif /* MONITOR_LSDB_CHANGE */
185 OSPF_TIMER_OFF(top
->t_opaque_lsa_self
);
186 if (top
->opaque_lsa_self
!= NULL
)
187 list_delete(top
->opaque_lsa_self
);
188 top
->opaque_lsa_self
= NULL
;
192 static const char *ospf_opaque_type_name(u_char opaque_type
)
194 const char *name
= "Unknown";
196 switch (opaque_type
) {
197 case OPAQUE_TYPE_WILDCARD
: /* This is a special assignment! */
200 case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA
:
201 name
= "Traffic Engineering LSA";
203 case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC
:
204 name
= "Sycamore optical topology description";
206 case OPAQUE_TYPE_GRACE_LSA
:
209 case OPAQUE_TYPE_INTER_AS_LSA
:
210 name
= "Inter-AS TE-v2 LSA";
212 case OPAQUE_TYPE_ROUTER_INFORMATION_LSA
:
213 name
= "Router Information LSA";
216 if (OPAQUE_TYPE_RANGE_UNASSIGNED(opaque_type
))
219 u_int32_t bigger_range
= opaque_type
;
221 * Get around type-limits warning: comparison is always
222 * true due to limited range of data type
224 if (OPAQUE_TYPE_RANGE_RESERVED(bigger_range
))
225 name
= "Private/Experimental";
232 /*------------------------------------------------------------------------*
233 * Followings are management functions to store user specified callbacks.
234 *------------------------------------------------------------------------*/
236 struct opaque_info_per_type
; /* Forward declaration. */
238 struct ospf_opaque_functab
{
240 struct opaque_info_per_type
*oipt
;
242 int (*new_if_hook
)(struct interface
*ifp
);
243 int (*del_if_hook
)(struct interface
*ifp
);
244 void (*ism_change_hook
)(struct ospf_interface
*oi
, int old_status
);
245 void (*nsm_change_hook
)(struct ospf_neighbor
*nbr
, int old_status
);
246 void (*config_write_router
)(struct vty
*vty
);
247 void (*config_write_if
)(struct vty
*vty
, struct interface
*ifp
);
248 void (*config_write_debug
)(struct vty
*vty
);
249 void (*show_opaque_info
)(struct vty
*vty
, struct ospf_lsa
*lsa
);
250 int (*lsa_originator
)(void *arg
);
251 struct ospf_lsa
*(*lsa_refresher
)(struct ospf_lsa
*lsa
);
252 int (*new_lsa_hook
)(struct ospf_lsa
*lsa
);
253 int (*del_lsa_hook
)(struct ospf_lsa
*lsa
);
256 /* Handle LSA-9/10/11 altogether. */
257 static struct list
*ospf_opaque_wildcard_funclist
;
258 static struct list
*ospf_opaque_type9_funclist
;
259 static struct list
*ospf_opaque_type10_funclist
;
260 static struct list
*ospf_opaque_type11_funclist
;
262 static void ospf_opaque_del_functab(void *val
)
264 XFREE(MTYPE_OSPF_OPAQUE_FUNCTAB
, val
);
268 static void ospf_opaque_funclist_init(void)
270 struct list
*funclist
;
272 funclist
= ospf_opaque_wildcard_funclist
= list_new();
273 funclist
->del
= ospf_opaque_del_functab
;
275 funclist
= ospf_opaque_type9_funclist
= list_new();
276 funclist
->del
= ospf_opaque_del_functab
;
278 funclist
= ospf_opaque_type10_funclist
= list_new();
279 funclist
->del
= ospf_opaque_del_functab
;
281 funclist
= ospf_opaque_type11_funclist
= list_new();
282 funclist
->del
= ospf_opaque_del_functab
;
286 static void ospf_opaque_funclist_term(void)
288 struct list
*funclist
;
290 funclist
= ospf_opaque_wildcard_funclist
;
291 list_delete(funclist
);
293 funclist
= ospf_opaque_type9_funclist
;
294 list_delete(funclist
);
296 funclist
= ospf_opaque_type10_funclist
;
297 list_delete(funclist
);
299 funclist
= ospf_opaque_type11_funclist
;
300 list_delete(funclist
);
304 static struct list
*ospf_get_opaque_funclist(u_char lsa_type
)
306 struct list
*funclist
= NULL
;
309 case OPAQUE_TYPE_WILDCARD
:
311 * This is an ugly trick to handle type-9/10/11 LSA altogether.
312 * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor
313 * an officially assigned opaque-type.
314 * Though it is possible that the value might be officially used
315 * in the future, we use it internally as a special label, for
318 funclist
= ospf_opaque_wildcard_funclist
;
320 case OSPF_OPAQUE_LINK_LSA
:
321 funclist
= ospf_opaque_type9_funclist
;
323 case OSPF_OPAQUE_AREA_LSA
:
324 funclist
= ospf_opaque_type10_funclist
;
326 case OSPF_OPAQUE_AS_LSA
:
327 funclist
= ospf_opaque_type11_funclist
;
330 zlog_warn("ospf_get_opaque_funclist: Unexpected LSA-type(%u)",
337 /* XXX: such a huge argument list can /not/ be healthy... */
338 int ospf_register_opaque_functab(
339 u_char lsa_type
, u_char opaque_type
,
340 int (*new_if_hook
)(struct interface
*ifp
),
341 int (*del_if_hook
)(struct interface
*ifp
),
342 void (*ism_change_hook
)(struct ospf_interface
*oi
, int old_status
),
343 void (*nsm_change_hook
)(struct ospf_neighbor
*nbr
, int old_status
),
344 void (*config_write_router
)(struct vty
*vty
),
345 void (*config_write_if
)(struct vty
*vty
, struct interface
*ifp
),
346 void (*config_write_debug
)(struct vty
*vty
),
347 void (*show_opaque_info
)(struct vty
*vty
, struct ospf_lsa
*lsa
),
348 int (*lsa_originator
)(void *arg
),
349 struct ospf_lsa
*(*lsa_refresher
)(struct ospf_lsa
*lsa
),
350 int (*new_lsa_hook
)(struct ospf_lsa
*lsa
),
351 int (*del_lsa_hook
)(struct ospf_lsa
*lsa
))
353 struct list
*funclist
;
354 struct ospf_opaque_functab
*new;
357 if ((funclist
= ospf_get_opaque_funclist(lsa_type
)) == NULL
) {
359 "ospf_register_opaque_functab: Cannot get funclist"
360 " for Type-%u LSAs?",
364 struct listnode
*node
, *nnode
;
365 struct ospf_opaque_functab
*functab
;
367 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
368 if (functab
->opaque_type
== opaque_type
) {
370 "ospf_register_opaque_functab: Duplicated entry?:"
371 " lsa_type(%u), opaque_type(%u)",
372 lsa_type
, opaque_type
);
377 if ((new = XCALLOC(MTYPE_OSPF_OPAQUE_FUNCTAB
,
378 sizeof(struct ospf_opaque_functab
)))
380 zlog_warn("ospf_register_opaque_functab: XMALLOC: %s",
381 safe_strerror(errno
));
385 new->opaque_type
= opaque_type
;
387 new->new_if_hook
= new_if_hook
;
388 new->del_if_hook
= del_if_hook
;
389 new->ism_change_hook
= ism_change_hook
;
390 new->nsm_change_hook
= nsm_change_hook
;
391 new->config_write_router
= config_write_router
;
392 new->config_write_if
= config_write_if
;
393 new->config_write_debug
= config_write_debug
;
394 new->show_opaque_info
= show_opaque_info
;
395 new->lsa_originator
= lsa_originator
;
396 new->lsa_refresher
= lsa_refresher
;
397 new->new_lsa_hook
= new_lsa_hook
;
398 new->del_lsa_hook
= del_lsa_hook
;
400 listnode_add(funclist
, new);
407 void ospf_delete_opaque_functab(u_char lsa_type
, u_char opaque_type
)
409 struct list
*funclist
;
410 struct listnode
*node
, *nnode
;
411 struct ospf_opaque_functab
*functab
;
413 if ((funclist
= ospf_get_opaque_funclist(lsa_type
)) != NULL
)
414 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
)) {
415 if (functab
->opaque_type
== opaque_type
) {
416 /* Cleanup internal control information, if it
418 if (functab
->oipt
!= NULL
)
419 free_opaque_info_per_type(
422 /* Dequeue listnode entry from the list. */
423 listnode_delete(funclist
, functab
);
425 /* Avoid misjudgement in the next lookup. */
426 if (listcount(funclist
) == 0)
427 funclist
->head
= funclist
->tail
= NULL
;
429 XFREE(MTYPE_OSPF_OPAQUE_FUNCTAB
, functab
);
437 static struct ospf_opaque_functab
*
438 ospf_opaque_functab_lookup(struct ospf_lsa
*lsa
)
440 struct list
*funclist
;
441 struct listnode
*node
;
442 struct ospf_opaque_functab
*functab
;
443 u_char key
= GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
));
445 if ((funclist
= ospf_get_opaque_funclist(lsa
->data
->type
)) != NULL
)
446 for (ALL_LIST_ELEMENTS_RO(funclist
, node
, functab
))
447 if (functab
->opaque_type
== key
)
453 /*------------------------------------------------------------------------*
454 * Followings are management functions for self-originated LSA entries.
455 *------------------------------------------------------------------------*/
458 * Opaque-LSA control information per opaque-type.
459 * Single Opaque-Type may have multiple instances; each of them will be
460 * identified by their opaque-id.
462 struct opaque_info_per_type
{
466 enum { PROC_NORMAL
, PROC_SUSPEND
} status
;
469 * Thread for (re-)origination scheduling for this opaque-type.
471 * Initial origination of Opaque-LSAs is controlled by generic
472 * Opaque-LSA handling module so that same opaque-type entries are
473 * called all at once when certain conditions are met.
474 * However, there might be cases that some Opaque-LSA clients need
475 * to (re-)originate their own Opaque-LSAs out-of-sync with others.
476 * This thread is prepared for that specific purpose.
478 struct thread
*t_opaque_lsa_self
;
481 * Backpointer to an "owner" which is LSA-type dependent.
482 * type-9: struct ospf_interface
483 * type-10: struct ospf_area
484 * type-11: struct ospf
488 /* Collection of callback functions for this opaque-type. */
489 struct ospf_opaque_functab
*functab
;
491 /* List of Opaque-LSA control informations per opaque-id. */
492 struct list
*id_list
;
495 /* Opaque-LSA control information per opaque-id. */
496 struct opaque_info_per_id
{
499 /* Thread for refresh/flush scheduling for this opaque-type/id. */
500 struct thread
*t_opaque_lsa_self
;
502 /* Backpointer to Opaque-LSA control information per opaque-type. */
503 struct opaque_info_per_type
*opqctl_type
;
505 /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
506 struct ospf_lsa
*lsa
;
509 static struct opaque_info_per_type
*
510 register_opaque_info_per_type(struct ospf_opaque_functab
*functab
,
511 struct ospf_lsa
*new);
512 static struct opaque_info_per_type
*
513 lookup_opaque_info_by_type(struct ospf_lsa
*lsa
);
514 static struct opaque_info_per_id
*
515 register_opaque_info_per_id(struct opaque_info_per_type
*oipt
,
516 struct ospf_lsa
*new);
517 static struct opaque_info_per_id
*
518 lookup_opaque_info_by_id(struct opaque_info_per_type
*oipt
,
519 struct ospf_lsa
*lsa
);
520 static struct opaque_info_per_id
*register_opaque_lsa(struct ospf_lsa
*new);
523 static struct opaque_info_per_type
*
524 register_opaque_info_per_type(struct ospf_opaque_functab
*functab
,
525 struct ospf_lsa
*new)
528 struct opaque_info_per_type
*oipt
;
530 if ((oipt
= XCALLOC(MTYPE_OPAQUE_INFO_PER_TYPE
,
531 sizeof(struct opaque_info_per_type
)))
533 zlog_warn("register_opaque_info_per_type: XMALLOC: %s",
534 safe_strerror(errno
));
538 switch (new->data
->type
) {
539 case OSPF_OPAQUE_LINK_LSA
:
540 oipt
->owner
= new->oi
;
541 listnode_add(new->oi
->opaque_lsa_self
, oipt
);
543 case OSPF_OPAQUE_AREA_LSA
:
544 oipt
->owner
= new->area
;
545 listnode_add(new->area
->opaque_lsa_self
, oipt
);
547 case OSPF_OPAQUE_AS_LSA
:
549 if (new->area
!= NULL
&& (top
= new->area
->ospf
) == NULL
) {
550 free_opaque_info_per_type((void *)oipt
);
552 goto out
; /* This case may not exist. */
555 listnode_add(top
->opaque_lsa_self
, oipt
);
559 "register_opaque_info_per_type: Unexpected LSA-type(%u)",
561 free_opaque_info_per_type((void *)oipt
);
563 goto out
; /* This case may not exist. */
566 oipt
->lsa_type
= new->data
->type
;
567 oipt
->opaque_type
= GET_OPAQUE_TYPE(ntohl(new->data
->id
.s_addr
));
568 oipt
->status
= PROC_NORMAL
;
569 oipt
->t_opaque_lsa_self
= NULL
;
570 oipt
->functab
= functab
;
571 functab
->oipt
= oipt
;
572 oipt
->id_list
= list_new();
573 oipt
->id_list
->del
= free_opaque_info_per_id
;
579 static void free_opaque_info_per_type(void *val
)
581 struct opaque_info_per_type
*oipt
= (struct opaque_info_per_type
*)val
;
582 struct opaque_info_per_id
*oipi
;
583 struct ospf_lsa
*lsa
;
584 struct listnode
*node
, *nnode
;
586 /* Control information per opaque-id may still exist. */
587 for (ALL_LIST_ELEMENTS(oipt
->id_list
, node
, nnode
, oipi
)) {
588 if ((lsa
= oipi
->lsa
) == NULL
)
590 if (IS_LSA_MAXAGE(lsa
))
592 ospf_opaque_lsa_flush_schedule(lsa
);
595 /* Remove "oipt" from its owner's self-originated LSA list. */
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 zlog_warn("free_opaque_info_per_type: Unexpected LSA-type(%u)",
616 break; /* This case may not exist. */
619 OSPF_TIMER_OFF(oipt
->t_opaque_lsa_self
);
620 list_delete(oipt
->id_list
);
621 XFREE(MTYPE_OPAQUE_INFO_PER_TYPE
, oipt
);
625 static struct opaque_info_per_type
*
626 lookup_opaque_info_by_type(struct ospf_lsa
*lsa
)
629 struct ospf_area
*area
;
630 struct ospf_interface
*oi
;
631 struct list
*listtop
= NULL
;
632 struct listnode
*node
, *nnode
;
633 struct opaque_info_per_type
*oipt
= NULL
;
634 u_char key
= GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
));
636 switch (lsa
->data
->type
) {
637 case OSPF_OPAQUE_LINK_LSA
:
638 if ((oi
= lsa
->oi
) != NULL
)
639 listtop
= oi
->opaque_lsa_self
;
642 "Type-9 Opaque-LSA: Reference to OI is missing?");
644 case OSPF_OPAQUE_AREA_LSA
:
645 if ((area
= lsa
->area
) != NULL
)
646 listtop
= area
->opaque_lsa_self
;
649 "Type-10 Opaque-LSA: Reference to AREA is missing?");
651 case OSPF_OPAQUE_AS_LSA
:
653 if ((area
= lsa
->area
) != NULL
&& (top
= area
->ospf
) == NULL
) {
655 "Type-11 Opaque-LSA: Reference to OSPF is missing?");
656 break; /* Unlikely to happen. */
658 listtop
= top
->opaque_lsa_self
;
661 zlog_warn("lookup_opaque_info_by_type: Unexpected LSA-type(%u)",
667 for (ALL_LIST_ELEMENTS(listtop
, node
, nnode
, oipt
))
668 if (oipt
->opaque_type
== key
)
674 static struct opaque_info_per_id
*
675 register_opaque_info_per_id(struct opaque_info_per_type
*oipt
,
676 struct ospf_lsa
*new)
678 struct opaque_info_per_id
*oipi
;
680 if ((oipi
= XCALLOC(MTYPE_OPAQUE_INFO_PER_ID
,
681 sizeof(struct opaque_info_per_id
)))
683 zlog_warn("register_opaque_info_per_id: XMALLOC: %s",
684 safe_strerror(errno
));
687 oipi
->opaque_id
= GET_OPAQUE_ID(ntohl(new->data
->id
.s_addr
));
688 oipi
->t_opaque_lsa_self
= NULL
;
689 oipi
->opqctl_type
= oipt
;
690 oipi
->lsa
= ospf_lsa_lock(new);
692 listnode_add(oipt
->id_list
, oipi
);
698 static void free_opaque_info_per_id(void *val
)
700 struct opaque_info_per_id
*oipi
= (struct opaque_info_per_id
*)val
;
702 OSPF_TIMER_OFF(oipi
->t_opaque_lsa_self
);
703 if (oipi
->lsa
!= NULL
)
704 ospf_lsa_unlock(&oipi
->lsa
);
705 XFREE(MTYPE_OPAQUE_INFO_PER_ID
, oipi
);
709 static struct opaque_info_per_id
*
710 lookup_opaque_info_by_id(struct opaque_info_per_type
*oipt
,
711 struct ospf_lsa
*lsa
)
713 struct listnode
*node
, *nnode
;
714 struct opaque_info_per_id
*oipi
;
715 u_int32_t key
= GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
));
717 for (ALL_LIST_ELEMENTS(oipt
->id_list
, node
, nnode
, oipi
))
718 if (oipi
->opaque_id
== key
)
724 static struct opaque_info_per_id
*register_opaque_lsa(struct ospf_lsa
*new)
726 struct ospf_opaque_functab
*functab
;
727 struct opaque_info_per_type
*oipt
;
728 struct opaque_info_per_id
*oipi
= NULL
;
730 if ((functab
= ospf_opaque_functab_lookup(new)) == NULL
)
733 if ((oipt
= lookup_opaque_info_by_type(new)) == NULL
734 && (oipt
= register_opaque_info_per_type(functab
, new)) == NULL
)
737 if ((oipi
= register_opaque_info_per_id(oipt
, new)) == NULL
)
744 /*------------------------------------------------------------------------*
745 * Followings are (vty) configuration functions for Opaque-LSAs handling.
746 *------------------------------------------------------------------------*/
748 DEFUN (capability_opaque
,
749 capability_opaque_cmd
,
751 "Enable specific OSPF feature\n"
754 VTY_DECLVAR_CONTEXT(ospf
, ospf
);
756 /* Turn on the "master switch" of opaque-lsa capability. */
757 if (!CHECK_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
)) {
758 if (IS_DEBUG_OSPF_EVENT
)
759 zlog_debug("Opaque capability: OFF -> ON");
761 SET_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
);
762 ospf_renegotiate_optional_capabilities(ospf
);
770 "OSPF specific commands\n"
771 "Enable the Opaque-LSA capability (rfc2370)\n")
773 return capability_opaque(self
, vty
, argc
, argv
);
776 DEFUN (no_capability_opaque
,
777 no_capability_opaque_cmd
,
778 "no capability opaque",
780 "Enable specific OSPF feature\n"
783 VTY_DECLVAR_CONTEXT(ospf
, ospf
);
785 /* Turn off the "master switch" of opaque-lsa capability. */
786 if (CHECK_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
)) {
787 if (IS_DEBUG_OSPF_EVENT
)
788 zlog_debug("Opaque capability: ON -> OFF");
790 UNSET_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
);
791 ospf_renegotiate_optional_capabilities(ospf
);
796 DEFUN (no_ospf_opaque
,
798 "no ospf opaque-lsa",
800 "OSPF specific commands\n"
801 "Enable the Opaque-LSA capability (rfc2370)\n")
803 return no_capability_opaque(self
, vty
, argc
, argv
);
806 static void ospf_opaque_register_vty(void)
808 install_element(OSPF_NODE
, &capability_opaque_cmd
);
809 install_element(OSPF_NODE
, &no_capability_opaque_cmd
);
810 install_element(OSPF_NODE
, &ospf_opaque_cmd
);
811 install_element(OSPF_NODE
, &no_ospf_opaque_cmd
);
815 /*------------------------------------------------------------------------*
816 * Followings are collection of user-registered function callers.
817 *------------------------------------------------------------------------*/
819 static int opaque_lsa_new_if_callback(struct list
*funclist
,
820 struct interface
*ifp
)
822 struct listnode
*node
, *nnode
;
823 struct ospf_opaque_functab
*functab
;
826 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
827 if (functab
->new_if_hook
!= NULL
)
828 if ((*functab
->new_if_hook
)(ifp
) != 0)
835 static int opaque_lsa_del_if_callback(struct list
*funclist
,
836 struct interface
*ifp
)
838 struct listnode
*node
, *nnode
;
839 struct ospf_opaque_functab
*functab
;
842 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
843 if (functab
->del_if_hook
!= NULL
)
844 if ((*functab
->del_if_hook
)(ifp
) != 0)
851 static void opaque_lsa_ism_change_callback(struct list
*funclist
,
852 struct ospf_interface
*oi
,
855 struct listnode
*node
, *nnode
;
856 struct ospf_opaque_functab
*functab
;
858 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
859 if (functab
->ism_change_hook
!= NULL
)
860 (*functab
->ism_change_hook
)(oi
, old_status
);
865 static void opaque_lsa_nsm_change_callback(struct list
*funclist
,
866 struct ospf_neighbor
*nbr
,
869 struct listnode
*node
, *nnode
;
870 struct ospf_opaque_functab
*functab
;
872 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
873 if (functab
->nsm_change_hook
!= NULL
)
874 (*functab
->nsm_change_hook
)(nbr
, old_status
);
878 static void opaque_lsa_config_write_router_callback(struct list
*funclist
,
881 struct listnode
*node
, *nnode
;
882 struct ospf_opaque_functab
*functab
;
884 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
885 if (functab
->config_write_router
!= NULL
)
886 (*functab
->config_write_router
)(vty
);
890 static void opaque_lsa_config_write_if_callback(struct list
*funclist
,
892 struct interface
*ifp
)
894 struct listnode
*node
, *nnode
;
895 struct ospf_opaque_functab
*functab
;
897 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
898 if (functab
->config_write_if
!= NULL
)
899 (*functab
->config_write_if
)(vty
, ifp
);
903 static void opaque_lsa_config_write_debug_callback(struct list
*funclist
,
906 struct listnode
*node
, *nnode
;
907 struct ospf_opaque_functab
*functab
;
909 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
910 if (functab
->config_write_debug
!= NULL
)
911 (*functab
->config_write_debug
)(vty
);
915 static int opaque_lsa_originate_callback(struct list
*funclist
,
916 void *lsa_type_dependent
)
918 struct listnode
*node
, *nnode
;
919 struct ospf_opaque_functab
*functab
;
922 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
923 if (functab
->lsa_originator
!= NULL
)
924 if ((*functab
->lsa_originator
)(lsa_type_dependent
) != 0)
931 static int new_lsa_callback(struct list
*funclist
, struct ospf_lsa
*lsa
)
933 struct listnode
*node
, *nnode
;
934 struct ospf_opaque_functab
*functab
;
937 /* This function handles ALL types of LSAs, not only opaque ones. */
938 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
939 if (functab
->new_lsa_hook
!= NULL
)
940 if ((*functab
->new_lsa_hook
)(lsa
) != 0)
947 static int del_lsa_callback(struct list
*funclist
, struct ospf_lsa
*lsa
)
949 struct listnode
*node
, *nnode
;
950 struct ospf_opaque_functab
*functab
;
953 /* This function handles ALL types of LSAs, not only opaque ones. */
954 for (ALL_LIST_ELEMENTS(funclist
, node
, nnode
, functab
))
955 if (functab
->del_lsa_hook
!= NULL
)
956 if ((*functab
->del_lsa_hook
)(lsa
) != 0)
963 /*------------------------------------------------------------------------*
964 * Followings are glue functions to call Opaque-LSA specific processing.
965 *------------------------------------------------------------------------*/
967 int ospf_opaque_new_if(struct interface
*ifp
)
969 struct list
*funclist
;
972 funclist
= ospf_opaque_wildcard_funclist
;
973 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
976 funclist
= ospf_opaque_type9_funclist
;
977 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
980 funclist
= ospf_opaque_type10_funclist
;
981 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
984 funclist
= ospf_opaque_type11_funclist
;
985 if (opaque_lsa_new_if_callback(funclist
, ifp
) != 0)
993 int ospf_opaque_del_if(struct interface
*ifp
)
995 struct list
*funclist
;
998 funclist
= ospf_opaque_wildcard_funclist
;
999 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1002 funclist
= ospf_opaque_type9_funclist
;
1003 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1006 funclist
= ospf_opaque_type10_funclist
;
1007 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1010 funclist
= ospf_opaque_type11_funclist
;
1011 if (opaque_lsa_del_if_callback(funclist
, ifp
) != 0)
1019 void ospf_opaque_ism_change(struct ospf_interface
*oi
, int old_status
)
1021 struct list
*funclist
;
1023 funclist
= ospf_opaque_wildcard_funclist
;
1024 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1026 funclist
= ospf_opaque_type9_funclist
;
1027 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1029 funclist
= ospf_opaque_type10_funclist
;
1030 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1032 funclist
= ospf_opaque_type11_funclist
;
1033 opaque_lsa_ism_change_callback(funclist
, oi
, old_status
);
1038 void ospf_opaque_nsm_change(struct ospf_neighbor
*nbr
, int old_state
)
1041 struct list
*funclist
;
1043 if ((top
= oi_to_top(nbr
->oi
)) == NULL
)
1046 if (old_state
!= NSM_Full
&& nbr
->state
== NSM_Full
) {
1047 if (CHECK_FLAG(nbr
->options
, OSPF_OPTION_O
)) {
1048 if (!CHECK_FLAG(top
->opaque
,
1049 OPAQUE_OPERATION_READY_BIT
)) {
1050 if (IS_DEBUG_OSPF_EVENT
)
1052 "Opaque-LSA: Now get operational!");
1054 SET_FLAG(top
->opaque
,
1055 OPAQUE_OPERATION_READY_BIT
);
1058 ospf_opaque_lsa_originate_schedule(nbr
->oi
, NULL
);
1060 } else if (old_state
== NSM_Full
&& nbr
->state
!= NSM_Full
) {
1063 * If no more opaque-capable full-state neighbor remains in the
1064 * flooding scope which corresponds to Opaque-LSA type, periodic
1065 * LS flooding should be stopped.
1071 funclist
= ospf_opaque_wildcard_funclist
;
1072 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1074 funclist
= ospf_opaque_type9_funclist
;
1075 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1077 funclist
= ospf_opaque_type10_funclist
;
1078 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1080 funclist
= ospf_opaque_type11_funclist
;
1081 opaque_lsa_nsm_change_callback(funclist
, nbr
, old_state
);
1087 void ospf_opaque_config_write_router(struct vty
*vty
, struct ospf
*ospf
)
1089 struct list
*funclist
;
1091 if (CHECK_FLAG(ospf
->config
, OSPF_OPAQUE_CAPABLE
))
1092 vty_out(vty
, " capability opaque%s", VTY_NEWLINE
);
1094 funclist
= ospf_opaque_wildcard_funclist
;
1095 opaque_lsa_config_write_router_callback(funclist
, vty
);
1097 funclist
= ospf_opaque_type9_funclist
;
1098 opaque_lsa_config_write_router_callback(funclist
, vty
);
1100 funclist
= ospf_opaque_type10_funclist
;
1101 opaque_lsa_config_write_router_callback(funclist
, vty
);
1103 funclist
= ospf_opaque_type11_funclist
;
1104 opaque_lsa_config_write_router_callback(funclist
, vty
);
1109 void ospf_opaque_config_write_if(struct vty
*vty
, struct interface
*ifp
)
1111 struct list
*funclist
;
1113 funclist
= ospf_opaque_wildcard_funclist
;
1114 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1116 funclist
= ospf_opaque_type9_funclist
;
1117 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1119 funclist
= ospf_opaque_type10_funclist
;
1120 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1122 funclist
= ospf_opaque_type11_funclist
;
1123 opaque_lsa_config_write_if_callback(funclist
, vty
, ifp
);
1128 void ospf_opaque_config_write_debug(struct vty
*vty
)
1130 struct list
*funclist
;
1132 funclist
= ospf_opaque_wildcard_funclist
;
1133 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1135 funclist
= ospf_opaque_type9_funclist
;
1136 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1138 funclist
= ospf_opaque_type10_funclist
;
1139 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1141 funclist
= ospf_opaque_type11_funclist
;
1142 opaque_lsa_config_write_debug_callback(funclist
, vty
);
1147 void show_opaque_info_detail(struct vty
*vty
, struct ospf_lsa
*lsa
)
1149 struct lsa_header
*lsah
= (struct lsa_header
*)lsa
->data
;
1150 u_int32_t lsid
= ntohl(lsah
->id
.s_addr
);
1151 u_char opaque_type
= GET_OPAQUE_TYPE(lsid
);
1152 u_int32_t opaque_id
= GET_OPAQUE_ID(lsid
);
1153 struct ospf_opaque_functab
*functab
;
1155 /* Switch output functionality by vty address. */
1157 vty_out(vty
, " Opaque-Type %u (%s)%s", opaque_type
,
1158 ospf_opaque_type_name(opaque_type
), VTY_NEWLINE
);
1159 vty_out(vty
, " Opaque-ID 0x%x%s", opaque_id
, VTY_NEWLINE
);
1161 vty_out(vty
, " Opaque-Info: %u octets of data%s%s",
1162 ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
,
1163 VALID_OPAQUE_INFO_LEN(lsah
) ? "" : "(Invalid length?)",
1166 zlog_debug(" Opaque-Type %u (%s)", opaque_type
,
1167 ospf_opaque_type_name(opaque_type
));
1168 zlog_debug(" Opaque-ID 0x%x", opaque_id
);
1170 zlog_debug(" Opaque-Info: %u octets of data%s",
1171 ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
,
1172 VALID_OPAQUE_INFO_LEN(lsah
) ? ""
1173 : "(Invalid length?)");
1176 /* Call individual output functions. */
1177 if ((functab
= ospf_opaque_functab_lookup(lsa
)) != NULL
)
1178 if (functab
->show_opaque_info
!= NULL
)
1179 (*functab
->show_opaque_info
)(vty
, lsa
);
1184 void ospf_opaque_lsa_dump(struct stream
*s
, u_int16_t length
)
1186 struct ospf_lsa lsa
;
1188 lsa
.data
= (struct lsa_header
*)STREAM_PNT(s
);
1189 show_opaque_info_detail(NULL
, &lsa
);
1193 static int ospf_opaque_lsa_install_hook(struct ospf_lsa
*lsa
)
1195 struct list
*funclist
;
1199 * Some Opaque-LSA user may want to monitor every LSA installation
1200 * into the LSDB, regardless with target LSA type.
1202 funclist
= ospf_opaque_wildcard_funclist
;
1203 if (new_lsa_callback(funclist
, lsa
) != 0)
1206 funclist
= ospf_opaque_type9_funclist
;
1207 if (new_lsa_callback(funclist
, lsa
) != 0)
1210 funclist
= ospf_opaque_type10_funclist
;
1211 if (new_lsa_callback(funclist
, lsa
) != 0)
1214 funclist
= ospf_opaque_type11_funclist
;
1215 if (new_lsa_callback(funclist
, lsa
) != 0)
1223 static int ospf_opaque_lsa_delete_hook(struct ospf_lsa
*lsa
)
1225 struct list
*funclist
;
1229 * Some Opaque-LSA user may want to monitor every LSA deletion
1230 * from the LSDB, regardless with target LSA type.
1232 funclist
= ospf_opaque_wildcard_funclist
;
1233 if (del_lsa_callback(funclist
, lsa
) != 0)
1236 funclist
= ospf_opaque_type9_funclist
;
1237 if (del_lsa_callback(funclist
, lsa
) != 0)
1240 funclist
= ospf_opaque_type10_funclist
;
1241 if (del_lsa_callback(funclist
, lsa
) != 0)
1244 funclist
= ospf_opaque_type11_funclist
;
1245 if (del_lsa_callback(funclist
, lsa
) != 0)
1253 /*------------------------------------------------------------------------*
1254 * Followings are Opaque-LSA origination/refresh management functions.
1255 *------------------------------------------------------------------------*/
1257 static int ospf_opaque_type9_lsa_originate(struct thread
*t
);
1258 static int ospf_opaque_type10_lsa_originate(struct thread
*t
);
1259 static int ospf_opaque_type11_lsa_originate(struct thread
*t
);
1260 static void ospf_opaque_lsa_reoriginate_resume(struct list
*listtop
, void *arg
);
1262 void ospf_opaque_lsa_originate_schedule(struct ospf_interface
*oi
, int *delay0
)
1265 struct ospf_area
*area
;
1266 struct listnode
*node
, *nnode
;
1267 struct opaque_info_per_type
*oipt
;
1270 if ((top
= oi_to_top(oi
)) == NULL
|| (area
= oi
->area
) == NULL
) {
1272 "ospf_opaque_lsa_originate_schedule: Invalid argument?");
1276 /* It may not a right time to schedule origination now. */
1277 if (!CHECK_FLAG(top
->opaque
, OPAQUE_OPERATION_READY_BIT
)) {
1278 if (IS_DEBUG_OSPF_EVENT
)
1280 "ospf_opaque_lsa_originate_schedule: Not operational.");
1281 goto out
; /* This is not an error. */
1288 * There might be some entries that have been waiting for triggering
1289 * of per opaque-type re-origination get resumed.
1291 ospf_opaque_lsa_reoriginate_resume(oi
->opaque_lsa_self
, (void *)oi
);
1292 ospf_opaque_lsa_reoriginate_resume(area
->opaque_lsa_self
, (void *)area
);
1293 ospf_opaque_lsa_reoriginate_resume(top
->opaque_lsa_self
, (void *)top
);
1296 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1298 if (!list_isempty(ospf_opaque_type9_funclist
)
1299 && list_isempty(oi
->opaque_lsa_self
)
1300 && oi
->t_opaque_lsa_self
== NULL
) {
1301 if (IS_DEBUG_OSPF_EVENT
)
1303 "Schedule Type-9 Opaque-LSA origination in %d ms later.",
1305 oi
->t_opaque_lsa_self
= thread_add_timer_msec(
1306 master
, ospf_opaque_type9_lsa_originate
, oi
, delay
);
1307 delay
+= top
->min_ls_interval
;
1310 if (!list_isempty(ospf_opaque_type10_funclist
)
1311 && list_isempty(area
->opaque_lsa_self
)
1312 && area
->t_opaque_lsa_self
== NULL
) {
1314 * One AREA may contain multiple OIs, but above 2nd and 3rd
1315 * conditions prevent from scheduling the originate function
1318 if (IS_DEBUG_OSPF_EVENT
)
1320 "Schedule Type-10 Opaque-LSA origination in %d ms later.",
1322 area
->t_opaque_lsa_self
= thread_add_timer_msec(
1323 master
, ospf_opaque_type10_lsa_originate
, area
, delay
);
1324 delay
+= top
->min_ls_interval
;
1327 if (!list_isempty(ospf_opaque_type11_funclist
)
1328 && list_isempty(top
->opaque_lsa_self
)
1329 && top
->t_opaque_lsa_self
== NULL
) {
1331 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1332 * conditions prevent from scheduling the originate function
1335 if (IS_DEBUG_OSPF_EVENT
)
1337 "Schedule Type-11 Opaque-LSA origination in %d ms later.",
1339 top
->t_opaque_lsa_self
= thread_add_timer_msec(
1340 master
, ospf_opaque_type11_lsa_originate
, top
, delay
);
1341 delay
+= top
->min_ls_interval
;
1345 * Following section treats a special situation that this node's
1346 * opaque capability has changed as "ON -> OFF -> ON".
1348 if (!list_isempty(ospf_opaque_type9_funclist
)
1349 && !list_isempty(oi
->opaque_lsa_self
)) {
1350 for (ALL_LIST_ELEMENTS(oi
->opaque_lsa_self
, node
, nnode
,
1353 * removed the test for
1354 * (! list_isempty (oipt->id_list)) * Handler is
1356 * because opaque cababilities ON -> OFF -> ON result in
1357 * list_isempty (oipt->id_list)
1361 oipt
->t_opaque_lsa_self
1362 != NULL
/* Waiting for a thread call. */
1363 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1368 ospf_opaque_lsa_reoriginate_schedule(
1369 (void *)oi
, OSPF_OPAQUE_LINK_LSA
,
1374 if (!list_isempty(ospf_opaque_type10_funclist
)
1375 && !list_isempty(area
->opaque_lsa_self
)) {
1376 for (ALL_LIST_ELEMENTS(area
->opaque_lsa_self
, node
, nnode
,
1379 * removed the test for
1380 * (! list_isempty (oipt->id_list)) * Handler is
1382 * because opaque cababilities ON -> OFF -> ON result in
1383 * list_isempty (oipt->id_list)
1387 oipt
->t_opaque_lsa_self
1388 != NULL
/* Waiting for a thread call. */
1389 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1394 ospf_opaque_lsa_reoriginate_schedule(
1395 (void *)area
, OSPF_OPAQUE_AREA_LSA
,
1400 if (!list_isempty(ospf_opaque_type11_funclist
)
1401 && !list_isempty(top
->opaque_lsa_self
)) {
1402 for (ALL_LIST_ELEMENTS(top
->opaque_lsa_self
, node
, nnode
,
1405 * removed the test for
1406 * (! list_isempty (oipt->id_list)) * Handler is
1408 * because opaque cababilities ON -> OFF -> ON result in
1409 * list_isempty (oipt->id_list)
1413 oipt
->t_opaque_lsa_self
1414 != NULL
/* Waiting for a thread call. */
1415 || oipt
->status
== PROC_SUSPEND
) /* Cannot
1420 ospf_opaque_lsa_reoriginate_schedule((void *)top
,
1433 static int ospf_opaque_type9_lsa_originate(struct thread
*t
)
1435 struct ospf_interface
*oi
;
1439 oi
->t_opaque_lsa_self
= NULL
;
1441 if (IS_DEBUG_OSPF_EVENT
)
1442 zlog_debug("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
1445 rc
= opaque_lsa_originate_callback(ospf_opaque_type9_funclist
, oi
);
1450 static int ospf_opaque_type10_lsa_originate(struct thread
*t
)
1452 struct ospf_area
*area
;
1455 area
= THREAD_ARG(t
);
1456 area
->t_opaque_lsa_self
= NULL
;
1458 if (IS_DEBUG_OSPF_EVENT
)
1460 "Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
1461 inet_ntoa(area
->area_id
));
1463 rc
= opaque_lsa_originate_callback(ospf_opaque_type10_funclist
, area
);
1468 static int ospf_opaque_type11_lsa_originate(struct thread
*t
)
1473 top
= THREAD_ARG(t
);
1474 top
->t_opaque_lsa_self
= NULL
;
1476 if (IS_DEBUG_OSPF_EVENT
)
1478 "Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
1480 rc
= opaque_lsa_originate_callback(ospf_opaque_type11_funclist
, top
);
1485 static void ospf_opaque_lsa_reoriginate_resume(struct list
*listtop
, void *arg
)
1487 struct listnode
*node
, *nnode
;
1488 struct opaque_info_per_type
*oipt
;
1489 struct ospf_opaque_functab
*functab
;
1491 if (listtop
== NULL
)
1495 * Pickup oipt entries those which in SUSPEND status, and give
1496 * them a chance to start re-origination now.
1498 for (ALL_LIST_ELEMENTS(listtop
, node
, nnode
, oipt
)) {
1499 if (oipt
->status
!= PROC_SUSPEND
)
1502 oipt
->status
= PROC_NORMAL
;
1504 if ((functab
= oipt
->functab
) == NULL
1505 || functab
->lsa_originator
== NULL
)
1508 if ((*functab
->lsa_originator
)(arg
) != 0) {
1510 "ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)",
1520 struct ospf_lsa
*ospf_opaque_lsa_install(struct ospf_lsa
*lsa
, int rt_recalc
)
1522 struct ospf_lsa
*new = NULL
;
1523 struct opaque_info_per_type
*oipt
;
1524 struct opaque_info_per_id
*oipi
;
1527 /* Don't take "rt_recalc" into consideration for now. */ /* XXX */
1529 if (!IS_LSA_SELF(lsa
)) {
1530 new = lsa
; /* Don't touch this LSA. */
1534 if (IS_DEBUG_OSPF(lsa
, LSA_INSTALL
))
1536 "Install Type-%u Opaque-LSA: [opaque-type=%u, opaque-id=%x]",
1538 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
1539 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
1541 /* Replace the existing lsa with the new one. */
1542 if ((oipt
= lookup_opaque_info_by_type(lsa
)) != NULL
1543 && (oipi
= lookup_opaque_info_by_id(oipt
, lsa
)) != NULL
) {
1544 ospf_lsa_unlock(&oipi
->lsa
);
1545 oipi
->lsa
= ospf_lsa_lock(lsa
);
1547 /* Register the new lsa entry and get its control info. */
1548 else if ((oipi
= register_opaque_lsa(lsa
)) == NULL
) {
1549 zlog_warn("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1554 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1555 * for periodic refresh of self-originated Opaque-LSAs.
1557 switch (lsa
->data
->type
) {
1558 case OSPF_OPAQUE_LINK_LSA
:
1559 if ((top
= oi_to_top(lsa
->oi
)) == NULL
) {
1560 /* Above conditions must have passed. */
1561 zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?");
1565 case OSPF_OPAQUE_AREA_LSA
:
1566 if (lsa
->area
== NULL
|| (top
= lsa
->area
->ospf
) == NULL
) {
1567 /* Above conditions must have passed. */
1568 zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?");
1572 case OSPF_OPAQUE_AS_LSA
:
1573 top
= ospf_lookup();
1574 if (lsa
->area
!= NULL
&& (top
= lsa
->area
->ospf
) == NULL
) {
1575 /* Above conditions must have passed. */
1576 zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?");
1581 zlog_warn("ospf_opaque_lsa_install: Unexpected LSA-type(%u)",
1586 ospf_refresher_register_lsa(top
, lsa
);
1593 struct ospf_lsa
*ospf_opaque_lsa_refresh(struct ospf_lsa
*lsa
)
1596 struct ospf_opaque_functab
*functab
;
1597 struct ospf_lsa
*new = NULL
;
1599 ospf
= ospf_lookup();
1601 if ((functab
= ospf_opaque_functab_lookup(lsa
)) == NULL
1602 || functab
->lsa_refresher
== NULL
) {
1604 * Though this LSA seems to have originated on this node, the
1605 * handling module for this "lsa-type and opaque-type" was
1606 * already deleted sometime ago.
1607 * Anyway, this node still has a responsibility to flush this
1608 * LSA from the routing domain.
1610 if (IS_DEBUG_OSPF_EVENT
)
1611 zlog_debug("LSA[Type%d:%s]: Flush stray Opaque-LSA",
1612 lsa
->data
->type
, inet_ntoa(lsa
->data
->id
));
1614 lsa
->data
->ls_age
= htons(OSPF_LSA_MAXAGE
);
1615 ospf_lsa_flush(ospf
, lsa
);
1617 new = (*functab
->lsa_refresher
)(lsa
);
1622 /*------------------------------------------------------------------------*
1623 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1624 * triggered by external interventions (vty session, signaling, etc).
1625 *------------------------------------------------------------------------*/
1627 #define OSPF_OPAQUE_TIMER_ON(T, F, L, V) \
1629 (T) = thread_add_timer_msec(master, (F), (L), (V))
1631 static struct ospf_lsa
*pseudo_lsa(struct ospf_interface
*oi
,
1632 struct ospf_area
*area
, u_char lsa_type
,
1633 u_char opaque_type
);
1634 static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread
*t
);
1635 static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread
*t
);
1636 static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread
*t
);
1637 static int ospf_opaque_lsa_refresh_timer(struct thread
*t
);
1639 void ospf_opaque_lsa_reoriginate_schedule(void *lsa_type_dependent
,
1640 u_char lsa_type
, u_char opaque_type
)
1643 struct ospf_area dummy
, *area
= NULL
;
1644 struct ospf_interface
*oi
= NULL
;
1646 struct ospf_lsa
*lsa
;
1647 struct opaque_info_per_type
*oipt
;
1648 int (*func
)(struct thread
* t
) = NULL
;
1652 case OSPF_OPAQUE_LINK_LSA
:
1653 if ((oi
= (struct ospf_interface
*)lsa_type_dependent
)
1656 "ospf_opaque_lsa_reoriginate_schedule:"
1657 " Type-9 Opaque-LSA: Invalid parameter?");
1660 if ((top
= oi_to_top(oi
)) == NULL
) {
1662 "ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1666 if (!list_isempty(ospf_opaque_type9_funclist
)
1667 && list_isempty(oi
->opaque_lsa_self
)
1668 && oi
->t_opaque_lsa_self
!= NULL
) {
1670 "Type-9 Opaque-LSA (opaque_type=%u):"
1671 " Common origination for OI(%s) has already started",
1672 opaque_type
, IF_NAME(oi
));
1675 func
= ospf_opaque_type9_lsa_reoriginate_timer
;
1677 case OSPF_OPAQUE_AREA_LSA
:
1678 if ((area
= (struct ospf_area
*)lsa_type_dependent
) == NULL
) {
1680 "ospf_opaque_lsa_reoriginate_schedule:"
1681 " Type-10 Opaque-LSA: Invalid parameter?");
1684 if ((top
= area
->ospf
) == NULL
) {
1686 "ospf_opaque_lsa_reoriginate_schedule:"
1687 " AREA(%s) -> TOP?",
1688 inet_ntoa(area
->area_id
));
1691 if (!list_isempty(ospf_opaque_type10_funclist
)
1692 && list_isempty(area
->opaque_lsa_self
)
1693 && area
->t_opaque_lsa_self
!= NULL
) {
1695 "Type-10 Opaque-LSA (opaque_type=%u):"
1696 " Common origination for AREA(%s) has already started",
1697 opaque_type
, inet_ntoa(area
->area_id
));
1700 func
= ospf_opaque_type10_lsa_reoriginate_timer
;
1702 case OSPF_OPAQUE_AS_LSA
:
1703 if ((top
= (struct ospf
*)lsa_type_dependent
) == NULL
) {
1705 "ospf_opaque_lsa_reoriginate_schedule:"
1706 " Type-11 Opaque-LSA: Invalid parameter?");
1709 if (!list_isempty(ospf_opaque_type11_funclist
)
1710 && list_isempty(top
->opaque_lsa_self
)
1711 && top
->t_opaque_lsa_self
!= NULL
) {
1713 "Type-11 Opaque-LSA (opaque_type=%u):"
1714 " Common origination has already started",
1719 /* Fake "area" to pass "ospf" to a lookup function later. */
1723 func
= ospf_opaque_type11_lsa_reoriginate_timer
;
1727 "ospf_opaque_lsa_reoriginate_schedule:"
1728 " Unexpected LSA-type(%u)",
1733 /* It may not a right time to schedule reorigination now. */
1734 if (!CHECK_FLAG(top
->opaque
, OPAQUE_OPERATION_READY_BIT
)) {
1735 if (IS_DEBUG_OSPF_EVENT
)
1737 "ospf_opaque_lsa_reoriginate_schedule: Not operational.");
1738 goto out
; /* This is not an error. */
1741 /* Generate a dummy lsa to be passed for a lookup function. */
1742 lsa
= pseudo_lsa(oi
, area
, lsa_type
, opaque_type
);
1744 if ((oipt
= lookup_opaque_info_by_type(lsa
)) == NULL
) {
1745 struct ospf_opaque_functab
*functab
;
1746 if ((functab
= ospf_opaque_functab_lookup(lsa
)) == NULL
) {
1748 "ospf_opaque_lsa_reoriginate_schedule:"
1749 " No associated function?: lsa_type(%u),"
1751 lsa_type
, opaque_type
);
1754 if ((oipt
= register_opaque_info_per_type(functab
, lsa
))
1757 "ospf_opaque_lsa_reoriginate_schedule:"
1758 " Cannot get a control info?: lsa_type(%u),"
1760 lsa_type
, opaque_type
);
1765 if (oipt
->t_opaque_lsa_self
!= NULL
) {
1766 if (IS_DEBUG_OSPF_EVENT
)
1768 "Type-%u Opaque-LSA has already scheduled to"
1769 " RE-ORIGINATE: [opaque-type=%u]",
1771 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)));
1776 * Different from initial origination time, in which various conditions
1777 * (opaque capability, neighbor status etc) are assured by caller of
1778 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1779 * it is highly possible that these conditions might not be satisfied
1780 * at the time of re-origination function is to be called.
1782 delay
= top
->min_ls_interval
; /* XXX */
1784 if (IS_DEBUG_OSPF_EVENT
)
1786 "Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
1787 " ms later: [opaque-type=%u]",
1789 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)));
1791 OSPF_OPAQUE_TIMER_ON(oipt
->t_opaque_lsa_self
, func
, oipt
, delay
* 1000);
1797 static struct ospf_lsa
*pseudo_lsa(struct ospf_interface
*oi
,
1798 struct ospf_area
*area
, u_char lsa_type
,
1801 static struct ospf_lsa lsa
= {0};
1802 static struct lsa_header lsah
= {0};
1809 lsah
.type
= lsa_type
;
1810 tmp
= SET_OPAQUE_LSID(opaque_type
, 0); /* Opaque-ID is unused here. */
1811 lsah
.id
.s_addr
= htonl(tmp
);
1816 static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread
*t
)
1818 struct opaque_info_per_type
*oipt
;
1819 struct ospf_opaque_functab
*functab
;
1821 struct ospf_interface
*oi
;
1824 oipt
= THREAD_ARG(t
);
1825 oipt
->t_opaque_lsa_self
= NULL
;
1827 if ((functab
= oipt
->functab
) == NULL
1828 || functab
->lsa_originator
== NULL
) {
1830 "ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1834 oi
= (struct ospf_interface
*)oipt
->owner
;
1835 if ((top
= oi_to_top(oi
)) == NULL
) {
1837 "ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1841 if (!CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)
1842 || !ospf_if_is_enable(oi
)
1843 || ospf_nbr_count_opaque_capable(oi
) == 0) {
1844 if (IS_DEBUG_OSPF_EVENT
)
1846 "Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...",
1849 oipt
->status
= PROC_SUSPEND
;
1854 if (IS_DEBUG_OSPF_EVENT
)
1856 "Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)",
1857 oipt
->opaque_type
, IF_NAME(oi
));
1859 rc
= (*functab
->lsa_originator
)(oi
);
1864 static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread
*t
)
1866 struct opaque_info_per_type
*oipt
;
1867 struct ospf_opaque_functab
*functab
;
1868 struct listnode
*node
, *nnode
;
1870 struct ospf_area
*area
;
1871 struct ospf_interface
*oi
;
1874 oipt
= THREAD_ARG(t
);
1875 oipt
->t_opaque_lsa_self
= NULL
;
1877 if ((functab
= oipt
->functab
) == NULL
1878 || functab
->lsa_originator
== NULL
) {
1880 "ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1884 area
= (struct ospf_area
*)oipt
->owner
;
1885 if (area
== NULL
|| (top
= area
->ospf
) == NULL
) {
1887 "ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1891 /* There must be at least one "opaque-capable, full-state" neighbor. */
1893 for (ALL_LIST_ELEMENTS(area
->oiflist
, node
, nnode
, oi
)) {
1894 if ((n
= ospf_nbr_count_opaque_capable(oi
)) > 0)
1898 if (n
== 0 || !CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)) {
1899 if (IS_DEBUG_OSPF_EVENT
)
1901 "Suspend re-origination of Type-10 Opaque-LSAs"
1902 " (opaque-type=%u) for a while...",
1905 oipt
->status
= PROC_SUSPEND
;
1910 if (IS_DEBUG_OSPF_EVENT
)
1912 "Timer[Type10-LSA]: Re-originate Opaque-LSAs"
1913 " (opaque-type=%u) for Area %s",
1914 oipt
->opaque_type
, inet_ntoa(area
->area_id
));
1916 rc
= (*functab
->lsa_originator
)(area
);
1921 static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread
*t
)
1923 struct opaque_info_per_type
*oipt
;
1924 struct ospf_opaque_functab
*functab
;
1928 oipt
= THREAD_ARG(t
);
1929 oipt
->t_opaque_lsa_self
= NULL
;
1931 if ((functab
= oipt
->functab
) == NULL
1932 || functab
->lsa_originator
== NULL
) {
1934 "ospf_opaque_type11_lsa_reoriginate_timer:"
1935 " No associated function?");
1939 if ((top
= (struct ospf
*)oipt
->owner
) == NULL
) {
1941 "ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1945 if (!CHECK_FLAG(top
->config
, OSPF_OPAQUE_CAPABLE
)) {
1946 if (IS_DEBUG_OSPF_EVENT
)
1948 "Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...",
1951 oipt
->status
= PROC_SUSPEND
;
1956 if (IS_DEBUG_OSPF_EVENT
)
1958 "Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).",
1961 rc
= (*functab
->lsa_originator
)(top
);
1966 void ospf_opaque_lsa_refresh_schedule(struct ospf_lsa
*lsa0
)
1968 struct opaque_info_per_type
*oipt
;
1969 struct opaque_info_per_id
*oipi
;
1970 struct ospf_lsa
*lsa
;
1974 if ((oipt
= lookup_opaque_info_by_type(lsa0
)) == NULL
1975 || (oipi
= lookup_opaque_info_by_id(oipt
, lsa0
)) == NULL
) {
1977 "ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
1981 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
1982 if ((lsa
= oipi
->lsa
) == NULL
) {
1983 zlog_warn("ospf_opaque_lsa_refresh_schedule: Something wrong?");
1987 if (oipi
->t_opaque_lsa_self
!= NULL
) {
1988 if (IS_DEBUG_OSPF_EVENT
)
1990 "Type-%u Opaque-LSA has already scheduled to REFRESH: [opaque-type=%u, opaque-id=%x]",
1992 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
1993 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
1997 /* Delete this lsa from neighbor retransmit-list. */
1998 switch (lsa
->data
->type
) {
1999 case OSPF_OPAQUE_LINK_LSA
:
2000 case OSPF_OPAQUE_AREA_LSA
:
2001 ospf_ls_retransmit_delete_nbr_area(lsa
->area
, lsa
);
2003 case OSPF_OPAQUE_AS_LSA
:
2004 top
= ospf_lookup();
2005 if ((lsa0
->area
!= NULL
) && (lsa0
->area
->ospf
!= NULL
))
2006 top
= lsa0
->area
->ospf
;
2007 ospf_ls_retransmit_delete_nbr_as(top
, lsa
);
2011 "ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)",
2016 delay
= ospf_lsa_refresh_delay(lsa
);
2018 if (IS_DEBUG_OSPF_EVENT
)
2020 "Schedule Type-%u Opaque-LSA to REFRESH in %d sec later: [opaque-type=%u, opaque-id=%x]",
2021 lsa
->data
->type
, delay
,
2022 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
2023 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
2025 OSPF_OPAQUE_TIMER_ON(oipi
->t_opaque_lsa_self
,
2026 ospf_opaque_lsa_refresh_timer
, oipi
, delay
* 1000);
2031 static int ospf_opaque_lsa_refresh_timer(struct thread
*t
)
2033 struct opaque_info_per_id
*oipi
;
2034 struct ospf_opaque_functab
*functab
;
2035 struct ospf_lsa
*lsa
;
2037 if (IS_DEBUG_OSPF_EVENT
)
2038 zlog_debug("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
2040 oipi
= THREAD_ARG(t
);
2041 oipi
->t_opaque_lsa_self
= NULL
;
2043 if ((lsa
= oipi
->lsa
) != NULL
)
2044 if ((functab
= oipi
->opqctl_type
->functab
) != NULL
)
2045 if (functab
->lsa_refresher
!= NULL
)
2046 (*functab
->lsa_refresher
)(lsa
);
2051 void ospf_opaque_lsa_flush_schedule(struct ospf_lsa
*lsa0
)
2053 struct opaque_info_per_type
*oipt
;
2054 struct opaque_info_per_id
*oipi
;
2055 struct ospf_lsa
*lsa
;
2058 top
= ospf_lookup();
2060 if ((oipt
= lookup_opaque_info_by_type(lsa0
)) == NULL
2061 || (oipi
= lookup_opaque_info_by_id(oipt
, lsa0
)) == NULL
) {
2062 zlog_warn("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2066 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2067 if ((lsa
= oipi
->lsa
) == NULL
) {
2068 zlog_warn("ospf_opaque_lsa_flush_schedule: Something wrong?");
2072 /* Delete this lsa from neighbor retransmit-list. */
2073 switch (lsa
->data
->type
) {
2074 case OSPF_OPAQUE_LINK_LSA
:
2075 case OSPF_OPAQUE_AREA_LSA
:
2076 ospf_ls_retransmit_delete_nbr_area(lsa
->area
, lsa
);
2078 case OSPF_OPAQUE_AS_LSA
:
2079 if ((lsa0
->area
!= NULL
) && (lsa0
->area
->ospf
!= NULL
))
2080 top
= lsa0
->area
->ospf
;
2081 ospf_ls_retransmit_delete_nbr_as(top
, lsa
);
2085 "ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)",
2090 /* Dequeue listnode entry from the list. */
2091 listnode_delete(oipt
->id_list
, oipi
);
2093 /* Avoid misjudgement in the next lookup. */
2094 if (listcount(oipt
->id_list
) == 0)
2095 oipt
->id_list
->head
= oipt
->id_list
->tail
= NULL
;
2097 /* Disassociate internal control information with the given lsa. */
2098 free_opaque_info_per_id((void *)oipi
);
2100 /* Force given lsa's age to MaxAge. */
2101 lsa
->data
->ls_age
= htons(OSPF_LSA_MAXAGE
);
2103 if (IS_DEBUG_OSPF_EVENT
)
2105 "Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]",
2107 GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)),
2108 GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)));
2110 /* This lsa will be flushed and removed eventually. */
2111 ospf_lsa_flush(top
, lsa
);
2117 void ospf_opaque_self_originated_lsa_received(struct ospf_neighbor
*nbr
,
2118 struct ospf_lsa
*lsa
)
2122 if ((top
= oi_to_top(nbr
->oi
)) == NULL
)
2126 * Since these LSA entries are not yet installed into corresponding
2127 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2129 lsa
->data
->ls_age
= htons(OSPF_LSA_MAXAGE
);
2130 switch (lsa
->data
->type
) {
2131 case OSPF_OPAQUE_LINK_LSA
:
2132 ospf_flood_through_area(nbr
->oi
->area
, NULL
/*inbr*/, lsa
);
2134 case OSPF_OPAQUE_AREA_LSA
:
2135 ospf_flood_through_area(nbr
->oi
->area
, NULL
/*inbr*/, lsa
);
2137 case OSPF_OPAQUE_AS_LSA
:
2138 ospf_flood_through_as(top
, NULL
/*inbr*/, lsa
);
2142 "ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)",
2146 ospf_lsa_discard(lsa
); /* List "lsas" will be deleted by caller. */
2149 /*------------------------------------------------------------------------*
2150 * Followings are util functions; probably be used by Opaque-LSAs only...
2151 *------------------------------------------------------------------------*/
2153 struct ospf
*oi_to_top(struct ospf_interface
*oi
)
2155 struct ospf
*top
= NULL
;
2156 struct ospf_area
*area
;
2158 if (oi
== NULL
|| (area
= oi
->area
) == NULL
2159 || (top
= area
->ospf
) == NULL
)
2160 zlog_warn("Broken relationship for \"OI -> AREA -> OSPF\"?");