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
24 /***** MTYPE definitions are not reflected to "memory.h" yet. *****/
25 #define MTYPE_OSPF_OPAQUE_FUNCTAB 0
26 #define MTYPE_OPAQUE_INFO_PER_TYPE 0
27 #define MTYPE_OPAQUE_INFO_PER_ID 0
30 #ifdef HAVE_OPAQUE_LSA
43 #include "sockunion.h" /* for inet_aton() */
45 #include "ospfd/ospfd.h"
46 #include "ospfd/ospf_interface.h"
47 #include "ospfd/ospf_ism.h"
48 #include "ospfd/ospf_asbr.h"
49 #include "ospfd/ospf_lsa.h"
50 #include "ospfd/ospf_lsdb.h"
51 #include "ospfd/ospf_neighbor.h"
52 #include "ospfd/ospf_nsm.h"
53 #include "ospfd/ospf_flood.h"
54 #include "ospfd/ospf_packet.h"
55 #include "ospfd/ospf_spf.h"
56 #include "ospfd/ospf_dump.h"
57 #include "ospfd/ospf_route.h"
58 #include "ospfd/ospf_ase.h"
59 #include "ospfd/ospf_zebra.h"
61 /*------------------------------------------------------------------------*
62 * Followings are initialize/terminate functions for Opaque-LSAs handling.
63 *------------------------------------------------------------------------*/
66 #include "ospfd/ospf_te.h"
67 #endif /* HAVE_OSPF_TE */
69 #ifdef SUPPORT_OSPF_API
70 int ospf_apiserver_init (void);
71 void ospf_apiserver_term (void);
72 /* Init apiserver? It's disabled by default. */
73 int ospf_apiserver_enable
;
74 #endif /* SUPPORT_OSPF_API */
76 static void ospf_opaque_register_vty (void);
77 static void ospf_opaque_funclist_init (void);
78 static void ospf_opaque_funclist_term (void);
79 static void free_opaque_info_per_type (void *val
);
80 static void free_opaque_info_per_id (void *val
);
81 static int ospf_opaque_lsa_install_hook (struct ospf_lsa
*lsa
);
82 static int ospf_opaque_lsa_delete_hook (struct ospf_lsa
*lsa
);
85 ospf_opaque_init (void)
87 ospf_opaque_register_vty ();
88 ospf_opaque_funclist_init ();
91 if (ospf_mpls_te_init () != 0)
93 #endif /* HAVE_OSPF_TE */
95 #ifdef SUPPORT_OSPF_API
96 if ((ospf_apiserver_enable
) && (ospf_apiserver_init () != 0))
98 #endif /* SUPPORT_OSPF_API */
104 ospf_opaque_term (void)
107 ospf_mpls_te_term ();
108 #endif /* HAVE_OSPF_TE */
110 #ifdef SUPPORT_OSPF_API
111 ospf_apiserver_term ();
112 #endif /* SUPPORT_OSPF_API */
114 ospf_opaque_funclist_term ();
119 ospf_opaque_type9_lsa_init (struct ospf_interface
*oi
)
121 if (oi
->opaque_lsa_self
!= NULL
)
122 list_delete (oi
->opaque_lsa_self
);
124 oi
->opaque_lsa_self
= list_new ();
125 oi
->opaque_lsa_self
->del
= free_opaque_info_per_type
;
126 oi
->t_opaque_lsa_self
= NULL
;
131 ospf_opaque_type9_lsa_term (struct ospf_interface
*oi
)
133 OSPF_TIMER_OFF (oi
->t_opaque_lsa_self
);
134 if (oi
->opaque_lsa_self
!= NULL
)
135 list_delete (oi
->opaque_lsa_self
);
136 oi
->opaque_lsa_self
= NULL
;
141 ospf_opaque_type10_lsa_init (struct ospf_area
*area
)
143 if (area
->opaque_lsa_self
!= NULL
)
144 list_delete (area
->opaque_lsa_self
);
146 area
->opaque_lsa_self
= list_new ();
147 area
->opaque_lsa_self
->del
= free_opaque_info_per_type
;
148 area
->t_opaque_lsa_self
= NULL
;
150 #ifdef MONITOR_LSDB_CHANGE
151 area
->lsdb
->new_lsa_hook
= ospf_opaque_lsa_install_hook
;
152 area
->lsdb
->del_lsa_hook
= ospf_opaque_lsa_delete_hook
;
153 #endif /* MONITOR_LSDB_CHANGE */
158 ospf_opaque_type10_lsa_term (struct ospf_area
*area
)
160 #ifdef MONITOR_LSDB_CHANGE
161 area
->lsdb
->new_lsa_hook
=
162 area
->lsdb
->del_lsa_hook
= NULL
;
163 #endif /* MONITOR_LSDB_CHANGE */
165 OSPF_TIMER_OFF (area
->t_opaque_lsa_self
);
166 if (area
->opaque_lsa_self
!= NULL
)
167 list_delete (area
->opaque_lsa_self
);
168 area
->opaque_lsa_self
= NULL
;
173 ospf_opaque_type11_lsa_init (struct ospf
*top
)
175 if (top
->opaque_lsa_self
!= NULL
)
176 list_delete (top
->opaque_lsa_self
);
178 top
->opaque_lsa_self
= list_new ();
179 top
->opaque_lsa_self
->del
= free_opaque_info_per_type
;
180 top
->t_opaque_lsa_self
= NULL
;
182 #ifdef MONITOR_LSDB_CHANGE
183 top
->lsdb
->new_lsa_hook
= ospf_opaque_lsa_install_hook
;
184 top
->lsdb
->del_lsa_hook
= ospf_opaque_lsa_delete_hook
;
185 #endif /* MONITOR_LSDB_CHANGE */
190 ospf_opaque_type11_lsa_term (struct ospf
*top
)
192 #ifdef MONITOR_LSDB_CHANGE
193 top
->lsdb
->new_lsa_hook
=
194 top
->lsdb
->del_lsa_hook
= NULL
;
195 #endif /* MONITOR_LSDB_CHANGE */
197 OSPF_TIMER_OFF (top
->t_opaque_lsa_self
);
198 if (top
->opaque_lsa_self
!= NULL
)
199 list_delete (top
->opaque_lsa_self
);
200 top
->opaque_lsa_self
= NULL
;
205 ospf_opaque_type_name (u_char opaque_type
)
207 const char *name
= "Unknown";
211 case OPAQUE_TYPE_WILDCARD
: /* This is a special assignment! */
214 case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA
:
215 name
= "Traffic Engineering LSA";
217 case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC
:
218 name
= "Sycamore optical topology description";
220 case OPAQUE_TYPE_GRACE_LSA
:
224 if (OPAQUE_TYPE_RANGE_UNASSIGNED (opaque_type
))
226 /* XXX warning: comparison is always true due to limited range of data type */
227 else if (OPAQUE_TYPE_RANGE_RESERVED (opaque_type
))
228 name
= "Private/Experimental";
234 /*------------------------------------------------------------------------*
235 * Followings are management functions to store user specified callbacks.
236 *------------------------------------------------------------------------*/
238 struct opaque_info_per_type
; /* Forward declaration. */
240 struct ospf_opaque_functab
243 struct opaque_info_per_type
*oipt
;
245 int (* new_if_hook
)(struct interface
*ifp
);
246 int (* del_if_hook
)(struct interface
*ifp
);
247 void (* ism_change_hook
)(struct ospf_interface
*oi
, int old_status
);
248 void (* nsm_change_hook
)(struct ospf_neighbor
*nbr
, int old_status
);
249 void (* config_write_router
)(struct vty
*vty
);
250 void (* config_write_if
)(struct vty
*vty
, struct interface
*ifp
);
251 void (* config_write_debug
)(struct vty
*vty
);
252 void (* show_opaque_info
)(struct vty
*vty
, struct ospf_lsa
*lsa
);
253 int (* lsa_originator
)(void *arg
);
254 void (* lsa_refresher
)(struct ospf_lsa
*lsa
);
255 int (* new_lsa_hook
)(struct ospf_lsa
*lsa
);
256 int (* del_lsa_hook
)(struct ospf_lsa
*lsa
);
259 /* Handle LSA-9/10/11 altogether. */
260 static struct list
*ospf_opaque_wildcard_funclist
;
261 static struct list
*ospf_opaque_type9_funclist
;
262 static struct list
*ospf_opaque_type10_funclist
;
263 static struct list
*ospf_opaque_type11_funclist
;
266 ospf_opaque_del_functab (void *val
)
268 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB
, val
);
273 ospf_opaque_funclist_init (void)
275 struct list
*funclist
;
277 funclist
= ospf_opaque_wildcard_funclist
= list_new ();
278 funclist
->del
= ospf_opaque_del_functab
;
280 funclist
= ospf_opaque_type9_funclist
= list_new ();
281 funclist
->del
= ospf_opaque_del_functab
;
283 funclist
= ospf_opaque_type10_funclist
= list_new ();
284 funclist
->del
= ospf_opaque_del_functab
;
286 funclist
= ospf_opaque_type11_funclist
= list_new ();
287 funclist
->del
= ospf_opaque_del_functab
;
292 ospf_opaque_funclist_term (void)
294 struct list
*funclist
;
296 funclist
= ospf_opaque_wildcard_funclist
;
297 list_delete (funclist
);
299 funclist
= ospf_opaque_type9_funclist
;
300 list_delete (funclist
);
302 funclist
= ospf_opaque_type10_funclist
;
303 list_delete (funclist
);
305 funclist
= ospf_opaque_type11_funclist
;
306 list_delete (funclist
);
311 ospf_get_opaque_funclist (u_char lsa_type
)
313 struct list
*funclist
= NULL
;
317 case OPAQUE_TYPE_WILDCARD
:
319 * This is an ugly trick to handle type-9/10/11 LSA altogether.
320 * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor
321 * an officially assigned opaque-type.
322 * Though it is possible that the value might be officially used
323 * in the future, we use it internally as a special label, for now.
325 funclist
= ospf_opaque_wildcard_funclist
;
327 case OSPF_OPAQUE_LINK_LSA
:
328 funclist
= ospf_opaque_type9_funclist
;
330 case OSPF_OPAQUE_AREA_LSA
:
331 funclist
= ospf_opaque_type10_funclist
;
333 case OSPF_OPAQUE_AS_LSA
:
334 funclist
= ospf_opaque_type11_funclist
;
337 zlog_warn ("ospf_get_opaque_funclist: Unexpected LSA-type(%u)", lsa_type
);
343 /* XXX: such a huge argument list can /not/ be healthy... */
345 ospf_register_opaque_functab (
348 int (* new_if_hook
)(struct interface
*ifp
),
349 int (* del_if_hook
)(struct interface
*ifp
),
350 void (* ism_change_hook
)(struct ospf_interface
*oi
, int old_status
),
351 void (* nsm_change_hook
)(struct ospf_neighbor
*nbr
, int old_status
),
352 void (* config_write_router
)(struct vty
*vty
),
353 void (* config_write_if
)(struct vty
*vty
, struct interface
*ifp
),
354 void (* config_write_debug
)(struct vty
*vty
),
355 void (* show_opaque_info
)(struct vty
*vty
, struct ospf_lsa
*lsa
),
356 int (* lsa_originator
)(void *arg
),
357 void (* lsa_refresher
)(struct ospf_lsa
*lsa
),
358 int (* new_lsa_hook
)(struct ospf_lsa
*lsa
),
359 int (* del_lsa_hook
)(struct ospf_lsa
*lsa
))
361 struct list
*funclist
;
362 struct ospf_opaque_functab
*new;
365 if ((funclist
= ospf_get_opaque_funclist (lsa_type
)) == NULL
)
367 zlog_warn ("ospf_register_opaque_functab: Cannot get funclist"
368 " for Type-%u LSAs?",
374 struct listnode
*node
, *nnode
;
375 struct ospf_opaque_functab
*functab
;
377 for (ALL_LIST_ELEMENTS (funclist
, node
, nnode
, functab
))
378 if (functab
->opaque_type
== opaque_type
)
380 zlog_warn ("ospf_register_opaque_functab: Duplicated entry?:"
381 " lsa_type(%u), opaque_type(%u)",
382 lsa_type
, opaque_type
);
387 if ((new = XCALLOC (MTYPE_OSPF_OPAQUE_FUNCTAB
,
388 sizeof (struct ospf_opaque_functab
))) == NULL
)
390 zlog_warn ("ospf_register_opaque_functab: XMALLOC: %s",
391 safe_strerror (errno
));
395 new->opaque_type
= opaque_type
;
397 new->new_if_hook
= new_if_hook
;
398 new->del_if_hook
= del_if_hook
;
399 new->ism_change_hook
= ism_change_hook
;
400 new->nsm_change_hook
= nsm_change_hook
;
401 new->config_write_router
= config_write_router
;
402 new->config_write_if
= config_write_if
;
403 new->config_write_debug
= config_write_debug
;
404 new->show_opaque_info
= show_opaque_info
;
405 new->lsa_originator
= lsa_originator
;
406 new->lsa_refresher
= lsa_refresher
;
407 new->new_lsa_hook
= new_lsa_hook
;
408 new->del_lsa_hook
= del_lsa_hook
;
410 listnode_add (funclist
, new);
418 ospf_delete_opaque_functab (u_char lsa_type
, u_char opaque_type
)
420 struct list
*funclist
;
421 struct listnode
*node
, *nnode
;
422 struct ospf_opaque_functab
*functab
;
424 if ((funclist
= ospf_get_opaque_funclist (lsa_type
)) != NULL
)
425 for (ALL_LIST_ELEMENTS (funclist
, node
, nnode
, functab
))
427 if (functab
->opaque_type
== opaque_type
)
429 /* Cleanup internal control information, if it still remains. */
430 if (functab
->oipt
!= NULL
)
431 free_opaque_info_per_type (functab
->oipt
);
433 /* Dequeue listnode entry from the list. */
434 listnode_delete (funclist
, functab
);
436 /* Avoid misjudgement in the next lookup. */
437 if (listcount (funclist
) == 0)
438 funclist
->head
= funclist
->tail
= NULL
;
440 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB
, functab
);
448 static struct ospf_opaque_functab
*
449 ospf_opaque_functab_lookup (struct ospf_lsa
*lsa
)
451 struct list
*funclist
;
452 struct listnode
*node
;
453 struct ospf_opaque_functab
*functab
;
454 u_char key
= GET_OPAQUE_TYPE (ntohl (lsa
->data
->id
.s_addr
));
456 if ((funclist
= ospf_get_opaque_funclist (lsa
->data
->type
)) != NULL
)
457 for (ALL_LIST_ELEMENTS_RO (funclist
, node
, functab
))
458 if (functab
->opaque_type
== key
)
464 /*------------------------------------------------------------------------*
465 * Followings are management functions for self-originated LSA entries.
466 *------------------------------------------------------------------------*/
469 * Opaque-LSA control information per opaque-type.
470 * Single Opaque-Type may have multiple instances; each of them will be
471 * identified by their opaque-id.
473 struct opaque_info_per_type
478 enum { PROC_NORMAL
, PROC_SUSPEND
} status
;
481 * Thread for (re-)origination scheduling for this opaque-type.
483 * Initial origination of Opaque-LSAs is controlled by generic
484 * Opaque-LSA handling module so that same opaque-type entries are
485 * called all at once when certain conditions are met.
486 * However, there might be cases that some Opaque-LSA clients need
487 * to (re-)originate their own Opaque-LSAs out-of-sync with others.
488 * This thread is prepared for that specific purpose.
490 struct thread
*t_opaque_lsa_self
;
493 * Backpointer to an "owner" which is LSA-type dependent.
494 * type-9: struct ospf_interface
495 * type-10: struct ospf_area
496 * type-11: struct ospf
500 /* Collection of callback functions for this opaque-type. */
501 struct ospf_opaque_functab
*functab
;
503 /* List of Opaque-LSA control informations per opaque-id. */
504 struct list
*id_list
;
507 /* Opaque-LSA control information per opaque-id. */
508 struct opaque_info_per_id
512 /* Thread for refresh/flush scheduling for this opaque-type/id. */
513 struct thread
*t_opaque_lsa_self
;
515 /* Backpointer to Opaque-LSA control information per opaque-type. */
516 struct opaque_info_per_type
*opqctl_type
;
518 /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
519 struct ospf_lsa
*lsa
;
522 static struct opaque_info_per_type
*register_opaque_info_per_type (struct ospf_opaque_functab
*functab
, struct ospf_lsa
*new);
523 static struct opaque_info_per_type
*lookup_opaque_info_by_type (struct ospf_lsa
*lsa
);
524 static struct opaque_info_per_id
*register_opaque_info_per_id (struct opaque_info_per_type
*oipt
, struct ospf_lsa
*new);
525 static struct opaque_info_per_id
*lookup_opaque_info_by_id (struct opaque_info_per_type
*oipt
, struct ospf_lsa
*lsa
);
526 static struct opaque_info_per_id
*register_opaque_lsa (struct ospf_lsa
*new);
529 static struct opaque_info_per_type
*
530 register_opaque_info_per_type (struct ospf_opaque_functab
*functab
,
531 struct ospf_lsa
*new)
534 struct opaque_info_per_type
*oipt
;
536 if ((oipt
= XCALLOC (MTYPE_OPAQUE_INFO_PER_TYPE
,
537 sizeof (struct opaque_info_per_type
))) == NULL
)
539 zlog_warn ("register_opaque_info_per_type: XMALLOC: %s", safe_strerror (errno
));
543 switch (new->data
->type
)
545 case OSPF_OPAQUE_LINK_LSA
:
546 oipt
->owner
= new->oi
;
547 listnode_add (new->oi
->opaque_lsa_self
, oipt
);
549 case OSPF_OPAQUE_AREA_LSA
:
550 oipt
->owner
= new->area
;
551 listnode_add (new->area
->opaque_lsa_self
, oipt
);
553 case OSPF_OPAQUE_AS_LSA
:
554 top
= ospf_lookup ();
555 if (new->area
!= NULL
&& (top
= new->area
->ospf
) == NULL
)
557 free_opaque_info_per_type ((void *) oipt
);
559 goto out
; /* This case may not exist. */
562 listnode_add (top
->opaque_lsa_self
, oipt
);
565 zlog_warn ("register_opaque_info_per_type: Unexpected LSA-type(%u)", new->data
->type
);
566 free_opaque_info_per_type ((void *) oipt
);
568 goto out
; /* This case may not exist. */
571 oipt
->lsa_type
= new->data
->type
;
572 oipt
->opaque_type
= GET_OPAQUE_TYPE (ntohl (new->data
->id
.s_addr
));
573 oipt
->status
= PROC_NORMAL
;
574 oipt
->t_opaque_lsa_self
= NULL
;
575 oipt
->functab
= functab
;
576 functab
->oipt
= oipt
;
577 oipt
->id_list
= list_new ();
578 oipt
->id_list
->del
= free_opaque_info_per_id
;
585 free_opaque_info_per_type (void *val
)
587 struct opaque_info_per_type
*oipt
= (struct opaque_info_per_type
*) val
;
588 struct opaque_info_per_id
*oipi
;
589 struct ospf_lsa
*lsa
;
590 struct listnode
*node
, *nnode
;
592 /* Control information per opaque-id may still exist. */
593 for (ALL_LIST_ELEMENTS (oipt
->id_list
, node
, nnode
, oipi
))
595 if ((lsa
= oipi
->lsa
) == NULL
)
597 if (IS_LSA_MAXAGE (lsa
))
599 ospf_opaque_lsa_flush_schedule (lsa
);
602 /* Remove "oipt" from its owner's self-originated LSA list. */
603 switch (oipt
->lsa_type
)
605 case OSPF_OPAQUE_LINK_LSA
:
607 struct ospf_interface
*oi
= (struct ospf_interface
*)(oipt
->owner
);
608 listnode_delete (oi
->opaque_lsa_self
, oipt
);
611 case OSPF_OPAQUE_AREA_LSA
:
613 struct ospf_area
*area
= (struct ospf_area
*)(oipt
->owner
);
614 listnode_delete (area
->opaque_lsa_self
, oipt
);
617 case OSPF_OPAQUE_AS_LSA
:
619 struct ospf
*top
= (struct ospf
*)(oipt
->owner
);
620 listnode_delete (top
->opaque_lsa_self
, oipt
);
624 zlog_warn ("free_opaque_info_per_type: Unexpected LSA-type(%u)", oipt
->lsa_type
);
625 break; /* This case may not exist. */
628 OSPF_TIMER_OFF (oipt
->t_opaque_lsa_self
);
629 list_delete (oipt
->id_list
);
630 XFREE (MTYPE_OPAQUE_INFO_PER_TYPE
, oipt
);
634 static struct opaque_info_per_type
*
635 lookup_opaque_info_by_type (struct ospf_lsa
*lsa
)
638 struct ospf_area
*area
;
639 struct ospf_interface
*oi
;
640 struct list
*listtop
= NULL
;
641 struct listnode
*node
, *nnode
;
642 struct opaque_info_per_type
*oipt
= NULL
;
643 u_char key
= GET_OPAQUE_TYPE (ntohl (lsa
->data
->id
.s_addr
));
645 switch (lsa
->data
->type
)
647 case OSPF_OPAQUE_LINK_LSA
:
648 if ((oi
= lsa
->oi
) != NULL
)
649 listtop
= oi
->opaque_lsa_self
;
651 zlog_warn ("Type-9 Opaque-LSA: Reference to OI is missing?");
653 case OSPF_OPAQUE_AREA_LSA
:
654 if ((area
= lsa
->area
) != NULL
)
655 listtop
= area
->opaque_lsa_self
;
657 zlog_warn ("Type-10 Opaque-LSA: Reference to AREA is missing?");
659 case OSPF_OPAQUE_AS_LSA
:
660 top
= ospf_lookup ();
661 if ((area
= lsa
->area
) != NULL
&& (top
= area
->ospf
) == NULL
)
663 zlog_warn ("Type-11 Opaque-LSA: Reference to OSPF is missing?");
664 break; /* Unlikely to happen. */
666 listtop
= top
->opaque_lsa_self
;
669 zlog_warn ("lookup_opaque_info_by_type: Unexpected LSA-type(%u)", lsa
->data
->type
);
674 for (ALL_LIST_ELEMENTS (listtop
, node
, nnode
, oipt
))
675 if (oipt
->opaque_type
== key
)
681 static struct opaque_info_per_id
*
682 register_opaque_info_per_id (struct opaque_info_per_type
*oipt
,
683 struct ospf_lsa
*new)
685 struct opaque_info_per_id
*oipi
;
687 if ((oipi
= XCALLOC (MTYPE_OPAQUE_INFO_PER_ID
,
688 sizeof (struct opaque_info_per_id
))) == NULL
)
690 zlog_warn ("register_opaque_info_per_id: XMALLOC: %s", safe_strerror (errno
));
693 oipi
->opaque_id
= GET_OPAQUE_ID (ntohl (new->data
->id
.s_addr
));
694 oipi
->t_opaque_lsa_self
= NULL
;
695 oipi
->opqctl_type
= oipt
;
696 oipi
->lsa
= ospf_lsa_lock (new);
698 listnode_add (oipt
->id_list
, oipi
);
705 free_opaque_info_per_id (void *val
)
707 struct opaque_info_per_id
*oipi
= (struct opaque_info_per_id
*) val
;
709 OSPF_TIMER_OFF (oipi
->t_opaque_lsa_self
);
710 if (oipi
->lsa
!= NULL
)
711 ospf_lsa_unlock (&oipi
->lsa
);
712 XFREE (MTYPE_OPAQUE_INFO_PER_ID
, oipi
);
716 static struct opaque_info_per_id
*
717 lookup_opaque_info_by_id (struct opaque_info_per_type
*oipt
,
718 struct ospf_lsa
*lsa
)
720 struct listnode
*node
, *nnode
;
721 struct opaque_info_per_id
*oipi
;
722 u_int32_t key
= GET_OPAQUE_ID (ntohl (lsa
->data
->id
.s_addr
));
724 for (ALL_LIST_ELEMENTS (oipt
->id_list
, node
, nnode
, oipi
))
725 if (oipi
->opaque_id
== key
)
731 static struct opaque_info_per_id
*
732 register_opaque_lsa (struct ospf_lsa
*new)
734 struct ospf_opaque_functab
*functab
;
735 struct opaque_info_per_type
*oipt
;
736 struct opaque_info_per_id
*oipi
= NULL
;
738 if ((functab
= ospf_opaque_functab_lookup (new)) == NULL
)
741 if ((oipt
= lookup_opaque_info_by_type (new)) == NULL
742 && (oipt
= register_opaque_info_per_type (functab
, new)) == NULL
)
745 if ((oipi
= register_opaque_info_per_id (oipt
, new)) == NULL
)
752 /*------------------------------------------------------------------------*
753 * Followings are (vty) configuration functions for Opaque-LSAs handling.
754 *------------------------------------------------------------------------*/
756 DEFUN (capability_opaque
,
757 capability_opaque_cmd
,
759 "Enable specific OSPF feature\n"
762 struct ospf
*ospf
= (struct ospf
*) vty
->index
;
764 /* Turn on the "master switch" of opaque-lsa capability. */
765 if (!CHECK_FLAG (ospf
->config
, OSPF_OPAQUE_CAPABLE
))
767 if (IS_DEBUG_OSPF_EVENT
)
768 zlog_debug ("Opaque capability: OFF -> ON");
770 SET_FLAG (ospf
->config
, OSPF_OPAQUE_CAPABLE
);
771 ospf_renegotiate_optional_capabilities (ospf
);
776 ALIAS (capability_opaque
,
777 ospf_opaque_capable_cmd
,
779 "OSPF specific commands\n"
780 "Enable the Opaque-LSA capability (rfc2370)\n")
782 DEFUN (no_capability_opaque
,
783 no_capability_opaque_cmd
,
784 "no capability opaque",
786 "Enable specific OSPF feature\n"
789 struct ospf
*ospf
= (struct ospf
*) vty
->index
;
791 /* Turn off the "master switch" of opaque-lsa capability. */
792 if (CHECK_FLAG (ospf
->config
, OSPF_OPAQUE_CAPABLE
))
794 if (IS_DEBUG_OSPF_EVENT
)
795 zlog_debug ("Opaque capability: ON -> OFF");
797 UNSET_FLAG (ospf
->config
, OSPF_OPAQUE_CAPABLE
);
798 ospf_renegotiate_optional_capabilities (ospf
);
803 ALIAS (no_capability_opaque
,
804 no_ospf_opaque_capable_cmd
,
805 "no ospf opaque-lsa",
807 "OSPF specific commands\n"
808 "Disable the Opaque-LSA capability (rfc2370)\n")
811 ospf_opaque_register_vty (void)
813 install_element (OSPF_NODE
, &capability_opaque_cmd
);
814 install_element (OSPF_NODE
, &no_capability_opaque_cmd
);
815 install_element (OSPF_NODE
, &ospf_opaque_capable_cmd
);
816 install_element (OSPF_NODE
, &no_ospf_opaque_capable_cmd
);
820 /*------------------------------------------------------------------------*
821 * Followings are collection of user-registered function callers.
822 *------------------------------------------------------------------------*/
825 opaque_lsa_new_if_callback (struct list
*funclist
, struct interface
*ifp
)
827 struct listnode
*node
, *nnode
;
828 struct ospf_opaque_functab
*functab
;
831 for (ALL_LIST_ELEMENTS (funclist
, node
, nnode
, functab
))
832 if (functab
->new_if_hook
!= NULL
)
833 if ((* functab
->new_if_hook
)(ifp
) != 0)
841 opaque_lsa_del_if_callback (struct list
*funclist
, struct interface
*ifp
)
843 struct listnode
*node
, *nnode
;
844 struct ospf_opaque_functab
*functab
;
847 for (ALL_LIST_ELEMENTS (funclist
, node
, nnode
, functab
))
848 if (functab
->del_if_hook
!= NULL
)
849 if ((* functab
->del_if_hook
)(ifp
) != 0)
857 opaque_lsa_ism_change_callback (struct list
*funclist
,
858 struct ospf_interface
*oi
, int old_status
)
860 struct listnode
*node
, *nnode
;
861 struct ospf_opaque_functab
*functab
;
863 for (ALL_LIST_ELEMENTS (funclist
, node
, nnode
, functab
))
864 if (functab
->ism_change_hook
!= NULL
)
865 (* functab
->ism_change_hook
)(oi
, old_status
);
871 opaque_lsa_nsm_change_callback (struct list
*funclist
,
872 struct ospf_neighbor
*nbr
, int old_status
)
874 struct listnode
*node
, *nnode
;
875 struct ospf_opaque_functab
*functab
;
877 for (ALL_LIST_ELEMENTS (funclist
, node
, nnode
, functab
))
878 if (functab
->nsm_change_hook
!= NULL
)
879 (* functab
->nsm_change_hook
)(nbr
, old_status
);
884 opaque_lsa_config_write_router_callback (struct list
*funclist
,
887 struct listnode
*node
, *nnode
;
888 struct ospf_opaque_functab
*functab
;
890 for (ALL_LIST_ELEMENTS (funclist
, node
, nnode
, functab
))
891 if (functab
->config_write_router
!= NULL
)
892 (* functab
->config_write_router
)(vty
);
897 opaque_lsa_config_write_if_callback (struct list
*funclist
,
898 struct vty
*vty
, struct interface
*ifp
)
900 struct listnode
*node
, *nnode
;
901 struct ospf_opaque_functab
*functab
;
903 for (ALL_LIST_ELEMENTS (funclist
, node
, nnode
, functab
))
904 if (functab
->config_write_if
!= NULL
)
905 (* functab
->config_write_if
)(vty
, ifp
);
910 opaque_lsa_config_write_debug_callback (struct list
*funclist
, struct vty
*vty
)
912 struct listnode
*node
, *nnode
;
913 struct ospf_opaque_functab
*functab
;
915 for (ALL_LIST_ELEMENTS (funclist
, node
, nnode
, functab
))
916 if (functab
->config_write_debug
!= NULL
)
917 (* functab
->config_write_debug
)(vty
);
922 opaque_lsa_originate_callback (struct list
*funclist
, void *lsa_type_dependent
)
924 struct listnode
*node
, *nnode
;
925 struct ospf_opaque_functab
*functab
;
928 for (ALL_LIST_ELEMENTS (funclist
, node
, nnode
, functab
))
929 if (functab
->lsa_originator
!= NULL
)
930 if ((* functab
->lsa_originator
)(lsa_type_dependent
) != 0)
938 new_lsa_callback (struct list
*funclist
, struct ospf_lsa
*lsa
)
940 struct listnode
*node
, *nnode
;
941 struct ospf_opaque_functab
*functab
;
944 /* This function handles ALL types of LSAs, not only opaque ones. */
945 for (ALL_LIST_ELEMENTS (funclist
, node
, nnode
, functab
))
946 if (functab
->new_lsa_hook
!= NULL
)
947 if ((* functab
->new_lsa_hook
)(lsa
) != 0)
955 del_lsa_callback (struct list
*funclist
, struct ospf_lsa
*lsa
)
957 struct listnode
*node
, *nnode
;
958 struct ospf_opaque_functab
*functab
;
961 /* This function handles ALL types of LSAs, not only opaque ones. */
962 for (ALL_LIST_ELEMENTS (funclist
, node
, nnode
, functab
))
963 if (functab
->del_lsa_hook
!= NULL
)
964 if ((* functab
->del_lsa_hook
)(lsa
) != 0)
971 /*------------------------------------------------------------------------*
972 * Followings are glue functions to call Opaque-LSA specific processing.
973 *------------------------------------------------------------------------*/
976 ospf_opaque_new_if (struct interface
*ifp
)
978 struct list
*funclist
;
981 funclist
= ospf_opaque_wildcard_funclist
;
982 if (opaque_lsa_new_if_callback (funclist
, ifp
) != 0)
985 funclist
= ospf_opaque_type9_funclist
;
986 if (opaque_lsa_new_if_callback (funclist
, ifp
) != 0)
989 funclist
= ospf_opaque_type10_funclist
;
990 if (opaque_lsa_new_if_callback (funclist
, ifp
) != 0)
993 funclist
= ospf_opaque_type11_funclist
;
994 if (opaque_lsa_new_if_callback (funclist
, ifp
) != 0)
1003 ospf_opaque_del_if (struct interface
*ifp
)
1005 struct list
*funclist
;
1008 funclist
= ospf_opaque_wildcard_funclist
;
1009 if (opaque_lsa_del_if_callback (funclist
, ifp
) != 0)
1012 funclist
= ospf_opaque_type9_funclist
;
1013 if (opaque_lsa_del_if_callback (funclist
, ifp
) != 0)
1016 funclist
= ospf_opaque_type10_funclist
;
1017 if (opaque_lsa_del_if_callback (funclist
, ifp
) != 0)
1020 funclist
= ospf_opaque_type11_funclist
;
1021 if (opaque_lsa_del_if_callback (funclist
, ifp
) != 0)
1030 ospf_opaque_ism_change (struct ospf_interface
*oi
, int old_status
)
1032 struct list
*funclist
;
1034 funclist
= ospf_opaque_wildcard_funclist
;
1035 opaque_lsa_ism_change_callback (funclist
, oi
, old_status
);
1037 funclist
= ospf_opaque_type9_funclist
;
1038 opaque_lsa_ism_change_callback (funclist
, oi
, old_status
);
1040 funclist
= ospf_opaque_type10_funclist
;
1041 opaque_lsa_ism_change_callback (funclist
, oi
, old_status
);
1043 funclist
= ospf_opaque_type11_funclist
;
1044 opaque_lsa_ism_change_callback (funclist
, oi
, old_status
);
1050 ospf_opaque_nsm_change (struct ospf_neighbor
*nbr
, int old_state
)
1053 struct list
*funclist
;
1055 if ((top
= oi_to_top (nbr
->oi
)) == NULL
)
1058 if (old_state
!= NSM_Full
&& nbr
->state
== NSM_Full
)
1060 if (CHECK_FLAG (nbr
->options
, OSPF_OPTION_O
))
1062 if (! CHECK_FLAG (top
->opaque
, OPAQUE_OPERATION_READY_BIT
))
1064 if (IS_DEBUG_OSPF_EVENT
)
1065 zlog_debug ("Opaque-LSA: Now get operational!");
1067 SET_FLAG (top
->opaque
, OPAQUE_OPERATION_READY_BIT
);
1070 ospf_opaque_lsa_originate_schedule (nbr
->oi
, NULL
);
1074 if (old_state
== NSM_Full
&& nbr
->state
!= NSM_Full
)
1078 * If no more opaque-capable full-state neighbor remains in the
1079 * flooding scope which corresponds to Opaque-LSA type, periodic
1080 * LS flooding should be stopped.
1086 funclist
= ospf_opaque_wildcard_funclist
;
1087 opaque_lsa_nsm_change_callback (funclist
, nbr
, old_state
);
1089 funclist
= ospf_opaque_type9_funclist
;
1090 opaque_lsa_nsm_change_callback (funclist
, nbr
, old_state
);
1092 funclist
= ospf_opaque_type10_funclist
;
1093 opaque_lsa_nsm_change_callback (funclist
, nbr
, old_state
);
1095 funclist
= ospf_opaque_type11_funclist
;
1096 opaque_lsa_nsm_change_callback (funclist
, nbr
, old_state
);
1103 ospf_opaque_config_write_router (struct vty
*vty
, struct ospf
*ospf
)
1105 struct list
*funclist
;
1107 if (CHECK_FLAG (ospf
->config
, OSPF_OPAQUE_CAPABLE
))
1108 vty_out (vty
, " capability opaque%s", VTY_NEWLINE
);
1110 funclist
= ospf_opaque_wildcard_funclist
;
1111 opaque_lsa_config_write_router_callback (funclist
, vty
);
1113 funclist
= ospf_opaque_type9_funclist
;
1114 opaque_lsa_config_write_router_callback (funclist
, vty
);
1116 funclist
= ospf_opaque_type10_funclist
;
1117 opaque_lsa_config_write_router_callback (funclist
, vty
);
1119 funclist
= ospf_opaque_type11_funclist
;
1120 opaque_lsa_config_write_router_callback (funclist
, vty
);
1126 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
);
1146 ospf_opaque_config_write_debug (struct vty
*vty
)
1148 struct list
*funclist
;
1150 funclist
= ospf_opaque_wildcard_funclist
;
1151 opaque_lsa_config_write_debug_callback (funclist
, vty
);
1153 funclist
= ospf_opaque_type9_funclist
;
1154 opaque_lsa_config_write_debug_callback (funclist
, vty
);
1156 funclist
= ospf_opaque_type10_funclist
;
1157 opaque_lsa_config_write_debug_callback (funclist
, vty
);
1159 funclist
= ospf_opaque_type11_funclist
;
1160 opaque_lsa_config_write_debug_callback (funclist
, vty
);
1166 show_opaque_info_detail (struct vty
*vty
, struct ospf_lsa
*lsa
)
1168 struct lsa_header
*lsah
= (struct lsa_header
*) lsa
->data
;
1169 u_int32_t lsid
= ntohl (lsah
->id
.s_addr
);
1170 u_char opaque_type
= GET_OPAQUE_TYPE (lsid
);
1171 u_int32_t opaque_id
= GET_OPAQUE_ID (lsid
);
1172 struct ospf_opaque_functab
*functab
;
1174 /* Switch output functionality by vty address. */
1177 vty_out (vty
, " Opaque-Type %u (%s)%s", opaque_type
,
1178 ospf_opaque_type_name (opaque_type
), VTY_NEWLINE
);
1179 vty_out (vty
, " Opaque-ID 0x%x%s", opaque_id
, VTY_NEWLINE
);
1181 vty_out (vty
, " Opaque-Info: %u octets of data%s%s",
1182 ntohs (lsah
->length
) - OSPF_LSA_HEADER_SIZE
,
1183 VALID_OPAQUE_INFO_LEN(lsah
) ? "" : "(Invalid length?)",
1188 zlog_debug (" Opaque-Type %u (%s)", opaque_type
,
1189 ospf_opaque_type_name (opaque_type
));
1190 zlog_debug (" Opaque-ID 0x%x", opaque_id
);
1192 zlog_debug (" Opaque-Info: %u octets of data%s",
1193 ntohs (lsah
->length
) - OSPF_LSA_HEADER_SIZE
,
1194 VALID_OPAQUE_INFO_LEN(lsah
) ? "" : "(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
);
1206 ospf_opaque_lsa_dump (struct stream
*s
, u_int16_t length
)
1208 struct ospf_lsa lsa
;
1210 lsa
.data
= (struct lsa_header
*) STREAM_PNT (s
);
1211 show_opaque_info_detail (NULL
, &lsa
);
1216 ospf_opaque_lsa_install_hook (struct ospf_lsa
*lsa
)
1218 struct list
*funclist
;
1222 * Some Opaque-LSA user may want to monitor every LSA installation
1223 * into the LSDB, regardless with target LSA type.
1225 funclist
= ospf_opaque_wildcard_funclist
;
1226 if (new_lsa_callback (funclist
, lsa
) != 0)
1229 funclist
= ospf_opaque_type9_funclist
;
1230 if (new_lsa_callback (funclist
, lsa
) != 0)
1233 funclist
= ospf_opaque_type10_funclist
;
1234 if (new_lsa_callback (funclist
, lsa
) != 0)
1237 funclist
= ospf_opaque_type11_funclist
;
1238 if (new_lsa_callback (funclist
, lsa
) != 0)
1247 ospf_opaque_lsa_delete_hook (struct ospf_lsa
*lsa
)
1249 struct list
*funclist
;
1253 * Some Opaque-LSA user may want to monitor every LSA deletion
1254 * from the LSDB, regardless with target LSA type.
1256 funclist
= ospf_opaque_wildcard_funclist
;
1257 if (del_lsa_callback (funclist
, lsa
) != 0)
1260 funclist
= ospf_opaque_type9_funclist
;
1261 if (del_lsa_callback (funclist
, lsa
) != 0)
1264 funclist
= ospf_opaque_type10_funclist
;
1265 if (del_lsa_callback (funclist
, lsa
) != 0)
1268 funclist
= ospf_opaque_type11_funclist
;
1269 if (del_lsa_callback (funclist
, lsa
) != 0)
1277 /*------------------------------------------------------------------------*
1278 * Followings are Opaque-LSA origination/refresh management functions.
1279 *------------------------------------------------------------------------*/
1281 static int ospf_opaque_type9_lsa_originate (struct thread
*t
);
1282 static int ospf_opaque_type10_lsa_originate (struct thread
*t
);
1283 static int ospf_opaque_type11_lsa_originate (struct thread
*t
);
1284 static void ospf_opaque_lsa_reoriginate_resume (struct list
*listtop
, void *arg
);
1287 ospf_opaque_lsa_originate_schedule (struct ospf_interface
*oi
, int *delay0
)
1290 struct ospf_area
*area
;
1291 struct listnode
*node
, *nnode
;
1292 struct opaque_info_per_type
*oipt
;
1295 if ((top
= oi_to_top (oi
)) == NULL
|| (area
= oi
->area
) == NULL
)
1297 zlog_warn ("ospf_opaque_lsa_originate_schedule: Invalid argument?");
1301 /* It may not a right time to schedule origination now. */
1302 if (! CHECK_FLAG (top
->opaque
, OPAQUE_OPERATION_READY_BIT
))
1304 if (IS_DEBUG_OSPF_EVENT
)
1305 zlog_debug ("ospf_opaque_lsa_originate_schedule: Not operational.");
1306 goto out
; /* This is not an error. */
1308 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top
->opaque
))
1310 if (IS_DEBUG_OSPF_EVENT
)
1311 zlog_debug ("ospf_opaque_lsa_originate_schedule: Under blockade.");
1312 goto out
; /* This is not an error, too. */
1319 * There might be some entries that have been waiting for triggering
1320 * of per opaque-type re-origination get resumed.
1322 ospf_opaque_lsa_reoriginate_resume ( oi
->opaque_lsa_self
, (void *) oi
);
1323 ospf_opaque_lsa_reoriginate_resume (area
->opaque_lsa_self
, (void *) area
);
1324 ospf_opaque_lsa_reoriginate_resume ( top
->opaque_lsa_self
, (void *) top
);
1327 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1329 if (! list_isempty (ospf_opaque_type9_funclist
)
1330 && list_isempty (oi
->opaque_lsa_self
)
1331 && oi
->t_opaque_lsa_self
== NULL
)
1333 if (IS_DEBUG_OSPF_EVENT
)
1334 zlog_debug ("Schedule Type-9 Opaque-LSA origination in %d sec later.", delay
);
1335 oi
->t_opaque_lsa_self
=
1336 thread_add_timer (master
, ospf_opaque_type9_lsa_originate
, oi
, delay
);
1337 delay
+= OSPF_MIN_LS_INTERVAL
;
1340 if (! list_isempty (ospf_opaque_type10_funclist
)
1341 && list_isempty (area
->opaque_lsa_self
)
1342 && area
->t_opaque_lsa_self
== NULL
)
1345 * One AREA may contain multiple OIs, but above 2nd and 3rd
1346 * conditions prevent from scheduling the originate function
1349 if (IS_DEBUG_OSPF_EVENT
)
1350 zlog_debug ("Schedule Type-10 Opaque-LSA origination in %d sec later.", delay
);
1351 area
->t_opaque_lsa_self
=
1352 thread_add_timer (master
, ospf_opaque_type10_lsa_originate
,
1354 delay
+= OSPF_MIN_LS_INTERVAL
;
1357 if (! list_isempty (ospf_opaque_type11_funclist
)
1358 && list_isempty (top
->opaque_lsa_self
)
1359 && top
->t_opaque_lsa_self
== NULL
)
1362 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1363 * conditions prevent from scheduling the originate function
1366 if (IS_DEBUG_OSPF_EVENT
)
1367 zlog_debug ("Schedule Type-11 Opaque-LSA origination in %d sec later.", delay
);
1368 top
->t_opaque_lsa_self
=
1369 thread_add_timer (master
, ospf_opaque_type11_lsa_originate
,
1371 delay
+= OSPF_MIN_LS_INTERVAL
;
1375 * Following section treats a special situation that this node's
1376 * opaque capability has changed as "ON -> OFF -> ON".
1378 if (! list_isempty (ospf_opaque_type9_funclist
)
1379 && ! list_isempty (oi
->opaque_lsa_self
))
1381 for (ALL_LIST_ELEMENTS (oi
->opaque_lsa_self
, node
, nnode
, oipt
))
1384 * removed the test for
1385 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1386 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1389 if (oipt
->t_opaque_lsa_self
!= NULL
/* Waiting for a thread call. */
1390 || oipt
->status
== PROC_SUSPEND
) /* Cannot originate now. */
1393 ospf_opaque_lsa_reoriginate_schedule ((void *) oi
,
1394 OSPF_OPAQUE_LINK_LSA
, oipt
->opaque_type
);
1398 if (! list_isempty (ospf_opaque_type10_funclist
)
1399 && ! list_isempty (area
->opaque_lsa_self
))
1401 for (ALL_LIST_ELEMENTS (area
->opaque_lsa_self
, node
, nnode
, oipt
))
1404 * removed the test for
1405 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1406 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1409 if (oipt
->t_opaque_lsa_self
!= NULL
/* Waiting for a thread call. */
1410 || oipt
->status
== PROC_SUSPEND
) /* Cannot originate now. */
1413 ospf_opaque_lsa_reoriginate_schedule ((void *) area
,
1414 OSPF_OPAQUE_AREA_LSA
, oipt
->opaque_type
);
1418 if (! list_isempty (ospf_opaque_type11_funclist
)
1419 && ! list_isempty (top
->opaque_lsa_self
))
1421 for (ALL_LIST_ELEMENTS (top
->opaque_lsa_self
, node
, nnode
, oipt
))
1424 * removed the test for
1425 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1426 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1429 if (oipt
->t_opaque_lsa_self
!= NULL
/* Waiting for a thread call. */
1430 || oipt
->status
== PROC_SUSPEND
) /* Cannot originate now. */
1433 ospf_opaque_lsa_reoriginate_schedule ((void *) top
,
1434 OSPF_OPAQUE_AS_LSA
, oipt
->opaque_type
);
1446 ospf_opaque_type9_lsa_originate (struct thread
*t
)
1448 struct ospf_interface
*oi
;
1451 oi
= THREAD_ARG (t
);
1452 oi
->t_opaque_lsa_self
= NULL
;
1454 if (IS_DEBUG_OSPF_EVENT
)
1455 zlog_debug ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
1458 rc
= opaque_lsa_originate_callback (ospf_opaque_type9_funclist
, oi
);
1464 ospf_opaque_type10_lsa_originate (struct thread
*t
)
1466 struct ospf_area
*area
;
1469 area
= THREAD_ARG (t
);
1470 area
->t_opaque_lsa_self
= NULL
;
1472 if (IS_DEBUG_OSPF_EVENT
)
1473 zlog_debug ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
1474 inet_ntoa (area
->area_id
));
1476 rc
= opaque_lsa_originate_callback (ospf_opaque_type10_funclist
, area
);
1482 ospf_opaque_type11_lsa_originate (struct thread
*t
)
1487 top
= THREAD_ARG (t
);
1488 top
->t_opaque_lsa_self
= NULL
;
1490 if (IS_DEBUG_OSPF_EVENT
)
1491 zlog_debug ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
1493 rc
= opaque_lsa_originate_callback (ospf_opaque_type11_funclist
, top
);
1499 ospf_opaque_lsa_reoriginate_resume (struct list
*listtop
, void *arg
)
1501 struct listnode
*node
, *nnode
;
1502 struct opaque_info_per_type
*oipt
;
1503 struct ospf_opaque_functab
*functab
;
1505 if (listtop
== NULL
)
1509 * Pickup oipt entries those which in SUSPEND status, and give
1510 * them a chance to start re-origination now.
1512 for (ALL_LIST_ELEMENTS (listtop
, node
, nnode
, oipt
))
1514 if (oipt
->status
!= PROC_SUSPEND
)
1517 oipt
->status
= PROC_NORMAL
;
1519 if ((functab
= oipt
->functab
) == NULL
1520 || functab
->lsa_originator
== NULL
)
1523 if ((* functab
->lsa_originator
)(arg
) != 0)
1525 zlog_warn ("ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", oipt
->opaque_type
);
1535 ospf_opaque_lsa_install (struct ospf_lsa
*lsa
, int rt_recalc
)
1537 struct ospf_lsa
*new = NULL
;
1538 struct opaque_info_per_type
*oipt
;
1539 struct opaque_info_per_id
*oipi
;
1542 /* Don't take "rt_recalc" into consideration for now. *//* XXX */
1544 if (! IS_LSA_SELF (lsa
))
1546 new = lsa
; /* Don't touch this LSA. */
1550 if (IS_DEBUG_OSPF (lsa
, LSA_INSTALL
))
1551 zlog_debug ("Install Type-%u Opaque-LSA: [opaque-type=%u, opaque-id=%x]", lsa
->data
->type
, GET_OPAQUE_TYPE (ntohl (lsa
->data
->id
.s_addr
)), GET_OPAQUE_ID (ntohl (lsa
->data
->id
.s_addr
)));
1553 /* Replace the existing lsa with the new one. */
1554 if ((oipt
= lookup_opaque_info_by_type (lsa
)) != NULL
1555 && (oipi
= lookup_opaque_info_by_id (oipt
, lsa
)) != NULL
)
1557 ospf_lsa_unlock (&oipi
->lsa
);
1558 oipi
->lsa
= ospf_lsa_lock (lsa
);
1560 /* Register the new lsa entry and get its control info. */
1562 if ((oipi
= register_opaque_lsa (lsa
)) == NULL
)
1564 zlog_warn ("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1569 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1570 * for periodic refresh of self-originated Opaque-LSAs.
1572 switch (lsa
->data
->type
)
1574 case OSPF_OPAQUE_LINK_LSA
:
1575 if ((top
= oi_to_top (lsa
->oi
)) == NULL
)
1577 /* Above conditions must have passed. */
1578 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1582 case OSPF_OPAQUE_AREA_LSA
:
1583 if (lsa
->area
== NULL
|| (top
= lsa
->area
->ospf
) == NULL
)
1585 /* Above conditions must have passed. */
1586 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1590 case OSPF_OPAQUE_AS_LSA
:
1591 top
= ospf_lookup ();
1592 if (lsa
->area
!= NULL
&& (top
= lsa
->area
->ospf
) == NULL
)
1594 /* Above conditions must have passed. */
1595 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1600 zlog_warn ("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", lsa
->data
->type
);
1604 ospf_refresher_register_lsa (top
, lsa
);
1612 ospf_opaque_lsa_refresh (struct ospf_lsa
*lsa
)
1615 struct ospf_opaque_functab
*functab
;
1617 ospf
= ospf_lookup ();
1619 if ((functab
= ospf_opaque_functab_lookup (lsa
)) == NULL
1620 || functab
->lsa_refresher
== NULL
)
1623 * Though this LSA seems to have originated on this node, the
1624 * handling module for this "lsa-type and opaque-type" was
1625 * already deleted sometime ago.
1626 * Anyway, this node still has a responsibility to flush this
1627 * LSA from the routing domain.
1629 if (IS_DEBUG_OSPF_EVENT
)
1630 zlog_debug ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa
->data
->type
, inet_ntoa (lsa
->data
->id
));
1632 lsa
->data
->ls_age
= htons (OSPF_LSA_MAXAGE
);
1633 ospf_lsa_maxage (ospf
, lsa
);
1636 (* functab
->lsa_refresher
)(lsa
);
1641 /*------------------------------------------------------------------------*
1642 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1643 * triggered by external interventions (vty session, signaling, etc).
1644 *------------------------------------------------------------------------*/
1646 #define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
1648 (T) = thread_add_timer (master, (F), (L), (V))
1650 static struct ospf_lsa
*pseudo_lsa (struct ospf_interface
*oi
, struct ospf_area
*area
, u_char lsa_type
, u_char opaque_type
);
1651 static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread
*t
);
1652 static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread
*t
);
1653 static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread
*t
);
1654 static int ospf_opaque_lsa_refresh_timer (struct thread
*t
);
1657 ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent
,
1658 u_char lsa_type
, u_char opaque_type
)
1661 struct ospf_area dummy
, *area
= NULL
;
1662 struct ospf_interface
*oi
= NULL
;
1664 struct ospf_lsa
*lsa
;
1665 struct opaque_info_per_type
*oipt
;
1666 int (*func
) (struct thread
* t
) = NULL
;
1671 case OSPF_OPAQUE_LINK_LSA
:
1672 if ((oi
= (struct ospf_interface
*) lsa_type_dependent
) == NULL
)
1674 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1675 " Type-9 Opaque-LSA: Invalid parameter?");
1678 if ((top
= oi_to_top (oi
)) == NULL
)
1680 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1684 if (!list_isempty (ospf_opaque_type9_funclist
)
1685 && list_isempty (oi
->opaque_lsa_self
)
1686 && oi
->t_opaque_lsa_self
!= NULL
)
1688 zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u):"
1689 " Common origination for OI(%s) has already started",
1690 opaque_type
, IF_NAME (oi
));
1693 func
= ospf_opaque_type9_lsa_reoriginate_timer
;
1695 case OSPF_OPAQUE_AREA_LSA
:
1696 if ((area
= (struct ospf_area
*) lsa_type_dependent
) == NULL
)
1698 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1699 " Type-10 Opaque-LSA: Invalid parameter?");
1702 if ((top
= area
->ospf
) == NULL
)
1704 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1705 " AREA(%s) -> TOP?", inet_ntoa (area
->area_id
));
1708 if (!list_isempty (ospf_opaque_type10_funclist
)
1709 && list_isempty (area
->opaque_lsa_self
)
1710 && area
->t_opaque_lsa_self
!= NULL
)
1712 zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u):"
1713 " Common origination for AREA(%s) has already started",
1714 opaque_type
, inet_ntoa (area
->area_id
));
1717 func
= ospf_opaque_type10_lsa_reoriginate_timer
;
1719 case OSPF_OPAQUE_AS_LSA
:
1720 if ((top
= (struct ospf
*) lsa_type_dependent
) == NULL
)
1722 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1723 " Type-11 Opaque-LSA: Invalid parameter?");
1726 if (!list_isempty (ospf_opaque_type11_funclist
)
1727 && list_isempty (top
->opaque_lsa_self
)
1728 && top
->t_opaque_lsa_self
!= NULL
)
1730 zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u):"
1731 " Common origination has already started", opaque_type
);
1735 /* Fake "area" to pass "ospf" to a lookup function later. */
1739 func
= ospf_opaque_type11_lsa_reoriginate_timer
;
1742 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1743 " Unexpected LSA-type(%u)",
1748 /* It may not a right time to schedule reorigination now. */
1749 if (!CHECK_FLAG (top
->opaque
, OPAQUE_OPERATION_READY_BIT
))
1751 if (IS_DEBUG_OSPF_EVENT
)
1752 zlog_debug ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
1753 goto out
; /* This is not an error. */
1755 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top
->opaque
))
1757 if (IS_DEBUG_OSPF_EVENT
)
1758 zlog_debug ("ospf_opaque_lsa_reoriginate_schedule: Under blockade.");
1759 goto out
; /* This is not an error, too. */
1762 /* Generate a dummy lsa to be passed for a lookup function. */
1763 lsa
= pseudo_lsa (oi
, area
, lsa_type
, opaque_type
);
1765 if ((oipt
= lookup_opaque_info_by_type (lsa
)) == NULL
)
1767 struct ospf_opaque_functab
*functab
;
1768 if ((functab
= ospf_opaque_functab_lookup (lsa
)) == NULL
)
1770 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1771 " No associated function?: lsa_type(%u),"
1773 lsa_type
, opaque_type
);
1776 if ((oipt
= register_opaque_info_per_type (functab
, lsa
)) == NULL
)
1778 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1779 " Cannot get a control info?: lsa_type(%u),"
1781 lsa_type
, opaque_type
);
1786 if (oipt
->t_opaque_lsa_self
!= NULL
)
1788 if (IS_DEBUG_OSPF_EVENT
)
1789 zlog_debug ("Type-%u Opaque-LSA has already scheduled to"
1790 " RE-ORIGINATE: [opaque-type=%u]",
1791 lsa_type
, GET_OPAQUE_TYPE (ntohl (lsa
->data
->id
.s_addr
)));
1796 * Different from initial origination time, in which various conditions
1797 * (opaque capability, neighbor status etc) are assured by caller of
1798 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1799 * it is highly possible that these conditions might not be satisfied
1800 * at the time of re-origination function is to be called.
1802 delay
= OSPF_MIN_LS_INTERVAL
; /* XXX */
1804 if (IS_DEBUG_OSPF_EVENT
)
1805 zlog_debug ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
1806 " sec later: [opaque-type=%u]",
1808 GET_OPAQUE_TYPE (ntohl (lsa
->data
->id
.s_addr
)));
1810 OSPF_OPAQUE_TIMER_ON (oipt
->t_opaque_lsa_self
, func
, oipt
, delay
);
1816 static struct ospf_lsa
*
1817 pseudo_lsa (struct ospf_interface
*oi
, struct ospf_area
*area
,
1818 u_char lsa_type
, u_char opaque_type
)
1820 static struct ospf_lsa lsa
= { 0 };
1821 static struct lsa_header lsah
= { 0 };
1828 lsah
.type
= lsa_type
;
1829 tmp
= SET_OPAQUE_LSID (opaque_type
, 0); /* Opaque-ID is unused here. */
1830 lsah
.id
.s_addr
= htonl (tmp
);
1836 ospf_opaque_type9_lsa_reoriginate_timer (struct thread
*t
)
1838 struct opaque_info_per_type
*oipt
;
1839 struct ospf_opaque_functab
*functab
;
1841 struct ospf_interface
*oi
;
1844 oipt
= THREAD_ARG (t
);
1845 oipt
->t_opaque_lsa_self
= NULL
;
1847 if ((functab
= oipt
->functab
) == NULL
1848 || functab
->lsa_originator
== NULL
)
1850 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1854 oi
= (struct ospf_interface
*) oipt
->owner
;
1855 if ((top
= oi_to_top (oi
)) == NULL
)
1857 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1861 if (! CHECK_FLAG (top
->config
, OSPF_OPAQUE_CAPABLE
)
1862 || ! ospf_if_is_enable (oi
)
1863 || ospf_nbr_count_opaque_capable (oi
) == 0)
1865 if (IS_DEBUG_OSPF_EVENT
)
1866 zlog_debug ("Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...", oipt
->opaque_type
);
1868 oipt
->status
= PROC_SUSPEND
;
1873 if (IS_DEBUG_OSPF_EVENT
)
1874 zlog_debug ("Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)", oipt
->opaque_type
, IF_NAME (oi
));
1876 rc
= (* functab
->lsa_originator
)(oi
);
1882 ospf_opaque_type10_lsa_reoriginate_timer (struct thread
*t
)
1884 struct opaque_info_per_type
*oipt
;
1885 struct ospf_opaque_functab
*functab
;
1886 struct listnode
*node
, *nnode
;
1888 struct ospf_area
*area
;
1889 struct ospf_interface
*oi
;
1892 oipt
= THREAD_ARG (t
);
1893 oipt
->t_opaque_lsa_self
= NULL
;
1895 if ((functab
= oipt
->functab
) == NULL
1896 || functab
->lsa_originator
== NULL
)
1898 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1902 area
= (struct ospf_area
*) oipt
->owner
;
1903 if (area
== NULL
|| (top
= area
->ospf
) == NULL
)
1905 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1909 /* There must be at least one "opaque-capable, full-state" neighbor. */
1911 for (ALL_LIST_ELEMENTS (area
->oiflist
, node
, nnode
, oi
))
1913 if ((n
= ospf_nbr_count_opaque_capable (oi
)) > 0)
1917 if (n
== 0 || ! CHECK_FLAG (top
->config
, OSPF_OPAQUE_CAPABLE
))
1919 if (IS_DEBUG_OSPF_EVENT
)
1920 zlog_debug ("Suspend re-origination of Type-10 Opaque-LSAs"
1921 " (opaque-type=%u) for a while...",
1924 oipt
->status
= PROC_SUSPEND
;
1929 if (IS_DEBUG_OSPF_EVENT
)
1930 zlog_debug ("Timer[Type10-LSA]: Re-originate Opaque-LSAs"
1931 " (opaque-type=%u) for Area %s",
1932 oipt
->opaque_type
, inet_ntoa (area
->area_id
));
1934 rc
= (* functab
->lsa_originator
)(area
);
1940 ospf_opaque_type11_lsa_reoriginate_timer (struct thread
*t
)
1942 struct opaque_info_per_type
*oipt
;
1943 struct ospf_opaque_functab
*functab
;
1947 oipt
= THREAD_ARG (t
);
1948 oipt
->t_opaque_lsa_self
= NULL
;
1950 if ((functab
= oipt
->functab
) == NULL
1951 || functab
->lsa_originator
== NULL
)
1953 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer:"
1954 " No associated function?");
1958 if ((top
= (struct ospf
*) oipt
->owner
) == NULL
)
1960 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1964 if (! CHECK_FLAG (top
->config
, OSPF_OPAQUE_CAPABLE
))
1966 if (IS_DEBUG_OSPF_EVENT
)
1967 zlog_debug ("Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...", oipt
->opaque_type
);
1969 oipt
->status
= PROC_SUSPEND
;
1974 if (IS_DEBUG_OSPF_EVENT
)
1975 zlog_debug ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt
->opaque_type
);
1977 rc
= (* functab
->lsa_originator
)(top
);
1983 ospf_opaque_lsa_refresh_schedule (struct ospf_lsa
*lsa0
)
1985 struct opaque_info_per_type
*oipt
;
1986 struct opaque_info_per_id
*oipi
;
1987 struct ospf_lsa
*lsa
;
1990 if ((oipt
= lookup_opaque_info_by_type (lsa0
)) == NULL
1991 || (oipi
= lookup_opaque_info_by_id (oipt
, lsa0
)) == NULL
)
1993 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
1997 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
1998 if ((lsa
= oipi
->lsa
) == NULL
)
2000 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
2004 if (oipi
->t_opaque_lsa_self
!= NULL
)
2006 if (IS_DEBUG_OSPF_EVENT
)
2007 zlog_debug ("Type-%u Opaque-LSA has already scheduled to REFRESH: [opaque-type=%u, opaque-id=%x]", lsa
->data
->type
, GET_OPAQUE_TYPE (ntohl (lsa
->data
->id
.s_addr
)), GET_OPAQUE_ID (ntohl (lsa
->data
->id
.s_addr
)));
2011 /* Delete this lsa from neighbor retransmit-list. */
2012 switch (lsa
->data
->type
)
2014 case OSPF_OPAQUE_LINK_LSA
:
2015 case OSPF_OPAQUE_AREA_LSA
:
2016 ospf_ls_retransmit_delete_nbr_area (lsa
->area
, lsa
);
2018 case OSPF_OPAQUE_AS_LSA
:
2019 ospf_ls_retransmit_delete_nbr_as (lsa0
->area
->ospf
, lsa
);
2022 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa
->data
->type
);
2026 delay
= ospf_lsa_refresh_delay (lsa
);
2028 if (IS_DEBUG_OSPF_EVENT
)
2029 zlog_debug ("Schedule Type-%u Opaque-LSA to REFRESH in %d sec later: [opaque-type=%u, opaque-id=%x]", lsa
->data
->type
, delay
, GET_OPAQUE_TYPE (ntohl (lsa
->data
->id
.s_addr
)), GET_OPAQUE_ID (ntohl (lsa
->data
->id
.s_addr
)));
2031 OSPF_OPAQUE_TIMER_ON (oipi
->t_opaque_lsa_self
,
2032 ospf_opaque_lsa_refresh_timer
, oipi
, delay
);
2038 ospf_opaque_lsa_refresh_timer (struct thread
*t
)
2040 struct opaque_info_per_id
*oipi
;
2041 struct ospf_opaque_functab
*functab
;
2042 struct ospf_lsa
*lsa
;
2044 if (IS_DEBUG_OSPF_EVENT
)
2045 zlog_debug ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
2047 oipi
= THREAD_ARG (t
);
2048 oipi
->t_opaque_lsa_self
= NULL
;
2050 if ((lsa
= oipi
->lsa
) != NULL
)
2051 if ((functab
= oipi
->opqctl_type
->functab
) != NULL
)
2052 if (functab
->lsa_refresher
!= NULL
)
2053 (* functab
->lsa_refresher
)(lsa
);
2059 ospf_opaque_lsa_flush_schedule (struct ospf_lsa
*lsa0
)
2061 struct opaque_info_per_type
*oipt
;
2062 struct opaque_info_per_id
*oipi
;
2063 struct ospf_lsa
*lsa
;
2065 if ((oipt
= lookup_opaque_info_by_type (lsa0
)) == NULL
2066 || (oipi
= lookup_opaque_info_by_id (oipt
, lsa0
)) == NULL
)
2068 zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2072 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2073 if ((lsa
= oipi
->lsa
) == NULL
)
2075 zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
2079 /* Delete this lsa from neighbor retransmit-list. */
2080 switch (lsa
->data
->type
)
2082 case OSPF_OPAQUE_LINK_LSA
:
2083 case OSPF_OPAQUE_AREA_LSA
:
2084 ospf_ls_retransmit_delete_nbr_area (lsa
->area
, lsa
);
2086 case OSPF_OPAQUE_AS_LSA
:
2087 ospf_ls_retransmit_delete_nbr_as (lsa0
->area
->ospf
, lsa
);
2090 zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa
->data
->type
);
2094 /* Dequeue listnode entry from the list. */
2095 listnode_delete (oipt
->id_list
, oipi
);
2097 /* Avoid misjudgement in the next lookup. */
2098 if (listcount (oipt
->id_list
) == 0)
2099 oipt
->id_list
->head
= oipt
->id_list
->tail
= NULL
;
2101 /* Disassociate internal control information with the given lsa. */
2102 free_opaque_info_per_id ((void *) oipi
);
2104 /* Force given lsa's age to MaxAge. */
2105 lsa
->data
->ls_age
= htons (OSPF_LSA_MAXAGE
);
2107 if (IS_DEBUG_OSPF_EVENT
)
2108 zlog_debug ("Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]", lsa
->data
->type
, GET_OPAQUE_TYPE (ntohl (lsa
->data
->id
.s_addr
)), GET_OPAQUE_ID (ntohl (lsa
->data
->id
.s_addr
)));
2110 /* This lsa will be flushed and removed eventually. */
2111 ospf_lsa_maxage (lsa0
->area
->ospf
, lsa
);
2117 /*------------------------------------------------------------------------*
2118 * Followings are control functions to block origination after restart.
2119 *------------------------------------------------------------------------*/
2121 static void ospf_opaque_exclude_lsa_from_lsreq (struct route_table
*nbrs
, struct ospf_neighbor
*inbr
, struct ospf_lsa
*lsa
);
2122 static void ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface
*oi
);
2123 static void ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area
*area
);
2124 static void ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf
*top
);
2125 static unsigned long ospf_opaque_nrxmt_self (struct route_table
*nbrs
, int lsa_type
);
2128 ospf_opaque_adjust_lsreq (struct ospf_neighbor
*nbr
, struct list
*lsas
)
2131 struct ospf_area
*area
;
2132 struct ospf_interface
*oi
;
2133 struct listnode
*node1
, *nnode1
;
2134 struct listnode
*node2
, *nnode2
;
2135 struct ospf_lsa
*lsa
;
2137 if ((top
= oi_to_top (nbr
->oi
)) == NULL
)
2141 * If an instance of self-originated Opaque-LSA is found in the given
2142 * LSA list, and it is not installed to LSDB yet, exclude it from the
2143 * list "nbr->ls_req". In this way, it is assured that an LSReq message,
2144 * which might be sent in the process of flooding, will not request for
2145 * the LSA to be flushed immediately; otherwise, depending on timing,
2146 * an LSUpd message will carry instances of target LSAs with MaxAge,
2147 * while other LSUpd message might carry old LSA instances (non-MaxAge).
2148 * Obviously, the latter would trigger miserable situations that repeat
2149 * installation and removal of unwanted LSAs indefinitely.
2151 for (ALL_LIST_ELEMENTS (lsas
, node1
, nnode1
, lsa
))
2153 /* Filter out unwanted LSAs. */
2154 if (! IS_OPAQUE_LSA (lsa
->data
->type
))
2156 if (! IPV4_ADDR_SAME (&lsa
->data
->adv_router
, &top
->router_id
))
2160 * Don't touch an LSA which has MaxAge; two possible cases.
2162 * 1) This LSA has originally flushed by myself (received LSUpd
2163 * message's router-id is equal to my router-id), and flooded
2164 * back by an opaque-capable router.
2166 * 2) This LSA has expired in an opaque-capable router and thus
2167 * flushed by the router.
2169 if (IS_LSA_MAXAGE (lsa
))
2172 /* If the LSA has installed in the LSDB, nothing to do here. */
2173 if (ospf_lsa_lookup_by_header (nbr
->oi
->area
, lsa
->data
) != NULL
)
2176 /* Ok, here we go. */
2177 switch (lsa
->data
->type
)
2179 case OSPF_OPAQUE_LINK_LSA
:
2181 ospf_opaque_exclude_lsa_from_lsreq (oi
->nbrs
, nbr
, lsa
);
2183 case OSPF_OPAQUE_AREA_LSA
:
2184 area
= nbr
->oi
->area
;
2185 for (ALL_LIST_ELEMENTS (area
->oiflist
, node2
, nnode2
, oi
))
2186 ospf_opaque_exclude_lsa_from_lsreq (oi
->nbrs
, nbr
, lsa
);
2188 case OSPF_OPAQUE_AS_LSA
:
2189 for (ALL_LIST_ELEMENTS (top
->oiflist
, node2
, nnode2
, oi
))
2190 ospf_opaque_exclude_lsa_from_lsreq (oi
->nbrs
, nbr
, lsa
);
2202 ospf_opaque_exclude_lsa_from_lsreq (struct route_table
*nbrs
,
2203 struct ospf_neighbor
*inbr
,
2204 struct ospf_lsa
*lsa
)
2206 struct route_node
*rn
;
2207 struct ospf_neighbor
*onbr
;
2208 struct ospf_lsa
*ls_req
;
2210 for (rn
= route_top (nbrs
); rn
; rn
= route_next (rn
))
2212 if ((onbr
= rn
->info
) == NULL
)
2216 if ((ls_req
= ospf_ls_request_lookup (onbr
, lsa
)) == NULL
)
2219 if (IS_DEBUG_OSPF_EVENT
)
2220 zlog_debug ("LSA[%s]: Exclude this entry from LSReq to send.", dump_lsa_key (lsa
));
2222 ospf_ls_request_delete (onbr
, ls_req
);
2223 /* ospf_check_nbr_loading (onbr);*//* XXX */
2230 ospf_opaque_self_originated_lsa_received (struct ospf_neighbor
*nbr
,
2231 struct ospf_lsa
*lsa
)
2236 if ((top
= oi_to_top (nbr
->oi
)) == NULL
)
2239 before
= IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top
->opaque
);
2242 * Since these LSA entries are not yet installed into corresponding
2243 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2245 lsa
->data
->ls_age
= htons (OSPF_LSA_MAXAGE
);
2246 switch (lsa
->data
->type
)
2248 case OSPF_OPAQUE_LINK_LSA
:
2249 SET_FLAG (top
->opaque
, OPAQUE_BLOCK_TYPE_09_LSA_BIT
);
2250 ospf_flood_through_area (nbr
->oi
->area
, NULL
/*inbr*/, lsa
);
2252 case OSPF_OPAQUE_AREA_LSA
:
2253 SET_FLAG (top
->opaque
, OPAQUE_BLOCK_TYPE_10_LSA_BIT
);
2254 ospf_flood_through_area (nbr
->oi
->area
, NULL
/*inbr*/, lsa
);
2256 case OSPF_OPAQUE_AS_LSA
:
2257 SET_FLAG (top
->opaque
, OPAQUE_BLOCK_TYPE_11_LSA_BIT
);
2258 ospf_flood_through_as (top
, NULL
/*inbr*/, lsa
);
2261 zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa
->data
->type
);
2265 ospf_lsa_discard (lsa
); /* List "lsas" will be deleted by caller. */
2267 if (before
== 0 && IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top
->opaque
))
2269 if (IS_DEBUG_OSPF_EVENT
)
2270 zlog_debug ("Block Opaque-LSA origination: OFF -> ON");
2275 ospf_opaque_ls_ack_received (struct ospf_neighbor
*nbr
, struct ospf_lsa
*lsa
)
2279 struct ospf_interface
*oi
;
2280 struct listnode
*node
, *nnode
;
2282 if ((top
= oi_to_top (nbr
->oi
)) == NULL
)
2285 if (!IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top
->opaque
))
2288 switch (lsa
->data
->type
)
2290 case OSPF_OPAQUE_LINK_LSA
:
2291 if (CHECK_FLAG (top
->opaque
, OPAQUE_BLOCK_TYPE_09_LSA_BIT
))
2292 ospf_opaque_type9_lsa_rxmt_nbr_check (nbr
->oi
);
2293 /* Callback function... */
2295 case OSPF_OPAQUE_AREA_LSA
:
2296 if (CHECK_FLAG (top
->opaque
, OPAQUE_BLOCK_TYPE_10_LSA_BIT
))
2297 ospf_opaque_type10_lsa_rxmt_nbr_check (nbr
->oi
->area
);
2298 /* Callback function... */
2300 case OSPF_OPAQUE_AS_LSA
:
2301 if (CHECK_FLAG (top
->opaque
, OPAQUE_BLOCK_TYPE_11_LSA_BIT
))
2302 ospf_opaque_type11_lsa_rxmt_nbr_check (top
);
2303 /* Callback function... */
2306 zlog_warn ("ospf_opaque_ls_ack_received: Unexpected LSA-type(%u)", lsa
->data
->type
);
2310 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top
->opaque
))
2312 if (IS_DEBUG_OSPF_EVENT
)
2313 zlog_debug ("Block Opaque-LSA origination: ON -> OFF");
2314 return; /* Blocking still in progress. */
2317 if (! CHECK_FLAG (top
->config
, OSPF_OPAQUE_CAPABLE
))
2318 return; /* Opaque capability condition must have changed. */
2320 /* Ok, let's start origination of Opaque-LSAs. */
2321 delay
= OSPF_MIN_LS_INTERVAL
;
2323 for (ALL_LIST_ELEMENTS (top
->oiflist
, node
, nnode
, oi
))
2325 if (! ospf_if_is_enable (oi
)
2326 || ospf_nbr_count_opaque_capable (oi
) == 0)
2329 ospf_opaque_lsa_originate_schedule (oi
, &delay
);
2336 ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface
*oi
)
2340 n
= ospf_opaque_nrxmt_self (oi
->nbrs
, OSPF_OPAQUE_LINK_LSA
);
2343 if (IS_DEBUG_OSPF_EVENT
)
2344 zlog_debug ("Self-originated type-9 Opaque-LSAs: OI(%s): Flush completed", IF_NAME (oi
));
2346 UNSET_FLAG (oi
->area
->ospf
->opaque
, OPAQUE_BLOCK_TYPE_09_LSA_BIT
);
2352 ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area
*area
)
2354 struct listnode
*node
;
2355 struct ospf_interface
*oi
;
2356 unsigned long n
= 0;
2358 for (ALL_LIST_ELEMENTS_RO (area
->oiflist
, node
, oi
))
2360 if (area
->area_id
.s_addr
!= OSPF_AREA_BACKBONE
2361 && oi
->type
== OSPF_IFTYPE_VIRTUALLINK
)
2364 n
= ospf_opaque_nrxmt_self (oi
->nbrs
, OSPF_OPAQUE_AREA_LSA
);
2371 if (IS_DEBUG_OSPF_EVENT
)
2372 zlog_debug ("Self-originated type-10 Opaque-LSAs: AREA(%s): Flush completed", inet_ntoa (area
->area_id
));
2374 UNSET_FLAG (area
->ospf
->opaque
, OPAQUE_BLOCK_TYPE_10_LSA_BIT
);
2381 ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf
*top
)
2383 struct listnode
*node
;
2384 struct ospf_interface
*oi
;
2385 unsigned long n
= 0;
2387 for (ALL_LIST_ELEMENTS_RO (top
->oiflist
, node
, oi
))
2391 case OSPF_IFTYPE_VIRTUALLINK
:
2397 n
= ospf_opaque_nrxmt_self (oi
->nbrs
, OSPF_OPAQUE_AS_LSA
);
2404 if (IS_DEBUG_OSPF_EVENT
)
2405 zlog_debug ("Self-originated type-11 Opaque-LSAs: Flush completed");
2407 UNSET_FLAG (top
->opaque
, OPAQUE_BLOCK_TYPE_11_LSA_BIT
);
2414 static unsigned long
2415 ospf_opaque_nrxmt_self (struct route_table
*nbrs
, int lsa_type
)
2417 struct route_node
*rn
;
2418 struct ospf_neighbor
*nbr
;
2420 unsigned long n
= 0;
2422 for (rn
= route_top (nbrs
); rn
; rn
= route_next (rn
))
2424 if ((nbr
= rn
->info
) == NULL
)
2426 if ((top
= oi_to_top (nbr
->oi
)) == NULL
)
2428 if (IPV4_ADDR_SAME (&nbr
->router_id
, &top
->router_id
))
2430 n
+= ospf_ls_retransmit_count_self (nbr
, lsa_type
);
2436 /*------------------------------------------------------------------------*
2437 * Followings are util functions; probably be used by Opaque-LSAs only...
2438 *------------------------------------------------------------------------*/
2441 htonf (float *src
, float *dst
)
2445 memcpy (&lu1
, src
, sizeof (u_int32_t
));
2447 memcpy (dst
, &lu2
, sizeof (u_int32_t
));
2452 ntohf (float *src
, float *dst
)
2456 memcpy (&lu1
, src
, sizeof (u_int32_t
));
2458 memcpy (dst
, &lu2
, sizeof (u_int32_t
));
2463 oi_to_top (struct ospf_interface
*oi
)
2465 struct ospf
*top
= NULL
;
2466 struct ospf_area
*area
;
2468 if (oi
== NULL
|| (area
= oi
->area
) == NULL
|| (top
= area
->ospf
) == NULL
)
2469 zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");
2474 #endif /* HAVE_OPAQUE_LSA */