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 #endif /* SUPPORT_OSPF_API */
74 static void ospf_opaque_register_vty (void);
75 static void ospf_opaque_funclist_init (void);
76 static void ospf_opaque_funclist_term (void);
77 static void free_opaque_info_per_type (void *val
);
78 static void free_opaque_info_per_id (void *val
);
79 static int ospf_opaque_lsa_install_hook (struct ospf_lsa
*lsa
);
80 static int ospf_opaque_lsa_delete_hook (struct ospf_lsa
*lsa
);
83 ospf_opaque_init (void)
85 ospf_opaque_register_vty ();
86 ospf_opaque_funclist_init ();
89 if (ospf_mpls_te_init () != 0)
91 #endif /* HAVE_OSPF_TE */
93 #ifdef SUPPORT_OSPF_API
94 if (ospf_apiserver_init () != 0)
96 #endif /* SUPPORT_OSPF_API */
102 ospf_opaque_term (void)
105 ospf_mpls_te_term ();
106 #endif /* HAVE_OSPF_TE */
108 #ifdef SUPPORT_OSPF_API
109 ospf_apiserver_term ();
110 #endif /* SUPPORT_OSPF_API */
112 ospf_opaque_funclist_term ();
117 ospf_opaque_type9_lsa_init (struct ospf_interface
*oi
)
119 if (oi
->opaque_lsa_self
!= NULL
)
120 list_delete (oi
->opaque_lsa_self
);
122 oi
->opaque_lsa_self
= list_new ();
123 oi
->opaque_lsa_self
->del
= free_opaque_info_per_type
;
124 oi
->t_opaque_lsa_self
= NULL
;
129 ospf_opaque_type9_lsa_term (struct ospf_interface
*oi
)
131 OSPF_TIMER_OFF (oi
->t_opaque_lsa_self
);
132 if (oi
->opaque_lsa_self
!= NULL
)
133 list_delete (oi
->opaque_lsa_self
);
134 oi
->opaque_lsa_self
= NULL
;
139 ospf_opaque_type10_lsa_init (struct ospf_area
*area
)
141 if (area
->opaque_lsa_self
!= NULL
)
142 list_delete (area
->opaque_lsa_self
);
144 area
->opaque_lsa_self
= list_new ();
145 area
->opaque_lsa_self
->del
= free_opaque_info_per_type
;
146 area
->t_opaque_lsa_self
= NULL
;
148 #ifdef MONITOR_LSDB_CHANGE
149 area
->lsdb
->new_lsa_hook
= ospf_opaque_lsa_install_hook
;
150 area
->lsdb
->del_lsa_hook
= ospf_opaque_lsa_delete_hook
;
151 #endif /* MONITOR_LSDB_CHANGE */
156 ospf_opaque_type10_lsa_term (struct ospf_area
*area
)
158 #ifdef MONITOR_LSDB_CHANGE
159 area
->lsdb
->new_lsa_hook
=
160 area
->lsdb
->del_lsa_hook
= NULL
;
161 #endif /* MONITOR_LSDB_CHANGE */
163 OSPF_TIMER_OFF (area
->t_opaque_lsa_self
);
164 if (area
->opaque_lsa_self
!= NULL
)
165 list_delete (area
->opaque_lsa_self
);
166 area
->opaque_lsa_self
= NULL
;
171 ospf_opaque_type11_lsa_init (struct ospf
*top
)
173 if (top
->opaque_lsa_self
!= NULL
)
174 list_delete (top
->opaque_lsa_self
);
176 top
->opaque_lsa_self
= list_new ();
177 top
->opaque_lsa_self
->del
= free_opaque_info_per_type
;
178 top
->t_opaque_lsa_self
= NULL
;
180 #ifdef MONITOR_LSDB_CHANGE
181 top
->lsdb
->new_lsa_hook
= ospf_opaque_lsa_install_hook
;
182 top
->lsdb
->del_lsa_hook
= ospf_opaque_lsa_delete_hook
;
183 #endif /* MONITOR_LSDB_CHANGE */
188 ospf_opaque_type11_lsa_term (struct ospf
*top
)
190 #ifdef MONITOR_LSDB_CHANGE
191 top
->lsdb
->new_lsa_hook
=
192 top
->lsdb
->del_lsa_hook
= NULL
;
193 #endif /* MONITOR_LSDB_CHANGE */
195 OSPF_TIMER_OFF (top
->t_opaque_lsa_self
);
196 if (top
->opaque_lsa_self
!= NULL
)
197 list_delete (top
->opaque_lsa_self
);
198 top
->opaque_lsa_self
= NULL
;
203 ospf_opaque_type_name (u_char opaque_type
)
205 const char *name
= "Unknown";
209 case OPAQUE_TYPE_WILDCARD
: /* This is a special assignment! */
212 case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA
:
213 name
= "Traffic Engineering LSA";
215 case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC
:
216 name
= "Sycamore optical topology description";
218 case OPAQUE_TYPE_GRACE_LSA
:
222 if (OPAQUE_TYPE_RANGE_UNASSIGNED (opaque_type
))
224 else if (OPAQUE_TYPE_RANGE_RESERVED (opaque_type
))
225 name
= "Private/Experimental";
231 /*------------------------------------------------------------------------*
232 * Followings are management functions to store user specified callbacks.
233 *------------------------------------------------------------------------*/
235 struct opaque_info_per_type
; /* Forward declaration. */
237 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 void (* 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 static list ospf_opaque_wildcard_funclist
; /* Handle LSA-9/10/11 altogether. */
257 static list ospf_opaque_type9_funclist
;
258 static list ospf_opaque_type10_funclist
;
259 static list ospf_opaque_type11_funclist
;
262 ospf_opaque_del_functab (void *val
)
264 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB
, val
);
269 ospf_opaque_funclist_init (void)
273 funclist
= ospf_opaque_wildcard_funclist
= list_new ();
274 funclist
->del
= ospf_opaque_del_functab
;
276 funclist
= ospf_opaque_type9_funclist
= list_new ();
277 funclist
->del
= ospf_opaque_del_functab
;
279 funclist
= ospf_opaque_type10_funclist
= list_new ();
280 funclist
->del
= ospf_opaque_del_functab
;
282 funclist
= ospf_opaque_type11_funclist
= list_new ();
283 funclist
->del
= ospf_opaque_del_functab
;
288 ospf_opaque_funclist_term (void)
292 funclist
= ospf_opaque_wildcard_funclist
;
293 list_delete (funclist
);
295 funclist
= ospf_opaque_type9_funclist
;
296 list_delete (funclist
);
298 funclist
= ospf_opaque_type10_funclist
;
299 list_delete (funclist
);
301 funclist
= ospf_opaque_type11_funclist
;
302 list_delete (funclist
);
307 ospf_get_opaque_funclist (u_char lsa_type
)
309 list funclist
= NULL
;
313 case OPAQUE_TYPE_WILDCARD
:
315 * This is an ugly trick to handle type-9/10/11 LSA altogether.
316 * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor
317 * an officially assigned opaque-type.
318 * Though it is possible that the value might be officially used
319 * in the future, we use it internally as a special label, for now.
321 funclist
= ospf_opaque_wildcard_funclist
;
323 case OSPF_OPAQUE_LINK_LSA
:
324 funclist
= ospf_opaque_type9_funclist
;
326 case OSPF_OPAQUE_AREA_LSA
:
327 funclist
= ospf_opaque_type10_funclist
;
329 case OSPF_OPAQUE_AS_LSA
:
330 funclist
= ospf_opaque_type11_funclist
;
333 zlog_warn ("ospf_get_opaque_funclist: Unexpected LSA-type(%u)", lsa_type
);
340 ospf_register_opaque_functab (
343 int (* new_if_hook
)(struct interface
*ifp
),
344 int (* del_if_hook
)(struct interface
*ifp
),
345 void (* ism_change_hook
)(struct ospf_interface
*oi
, int old_status
),
346 void (* nsm_change_hook
)(struct ospf_neighbor
*nbr
, int old_status
),
347 void (* config_write_router
)(struct vty
*vty
),
348 void (* config_write_if
)(struct vty
*vty
, struct interface
*ifp
),
349 void (* config_write_debug
)(struct vty
*vty
),
350 void (* show_opaque_info
)(struct vty
*vty
, struct ospf_lsa
*lsa
),
351 int (* lsa_originator
)(void *arg
),
352 void (* lsa_refresher
)(struct ospf_lsa
*lsa
),
353 int (* new_lsa_hook
)(struct ospf_lsa
*lsa
),
354 int (* del_lsa_hook
)(struct ospf_lsa
*lsa
))
357 struct ospf_opaque_functab
*new;
360 if ((funclist
= ospf_get_opaque_funclist (lsa_type
)) == NULL
)
362 zlog_warn ("ospf_register_opaque_functab: Cannot get funclist for Type-%u LSAs?", lsa_type
);
368 struct ospf_opaque_functab
*functab
;
370 for (node
= listhead (funclist
); node
; nextnode (node
))
371 if ((functab
= getdata (node
)) != NULL
)
372 if (functab
->opaque_type
== opaque_type
)
374 zlog_warn ("ospf_register_opaque_functab: Duplicated entry?: lsa_type(%u), opaque_type(%u)", lsa_type
, opaque_type
);
379 if ((new = XCALLOC (MTYPE_OSPF_OPAQUE_FUNCTAB
,
380 sizeof (struct ospf_opaque_functab
))) == NULL
)
382 zlog_warn ("ospf_register_opaque_functab: XMALLOC: %s", strerror (errno
));
386 new->opaque_type
= opaque_type
;
388 new->new_if_hook
= new_if_hook
;
389 new->del_if_hook
= del_if_hook
;
390 new->ism_change_hook
= ism_change_hook
;
391 new->nsm_change_hook
= nsm_change_hook
;
392 new->config_write_router
= config_write_router
;
393 new->config_write_if
= config_write_if
;
394 new->config_write_debug
= config_write_debug
;
395 new->show_opaque_info
= show_opaque_info
;
396 new->lsa_originator
= lsa_originator
;
397 new->lsa_refresher
= lsa_refresher
;
398 new->new_lsa_hook
= new_lsa_hook
;
399 new->del_lsa_hook
= del_lsa_hook
;
401 listnode_add (funclist
, new);
409 ospf_delete_opaque_functab (u_char lsa_type
, u_char opaque_type
)
413 struct ospf_opaque_functab
*functab
;
415 if ((funclist
= ospf_get_opaque_funclist (lsa_type
)) != NULL
)
416 for (node
= listhead (funclist
); node
; nextnode (node
))
418 if ((functab
= getdata (node
)) != NULL
419 && functab
->opaque_type
== opaque_type
)
421 /* Cleanup internal control information, if it still remains. */
422 if (functab
->oipt
!= NULL
)
423 free_opaque_info_per_type (functab
->oipt
);
425 /* Dequeue listnode entry from the list. */
426 listnode_delete (funclist
, functab
);
428 /* Avoid misjudgement in the next lookup. */
429 if (listcount (funclist
) == 0)
430 funclist
->head
= funclist
->tail
= NULL
;
432 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB
, functab
);
440 static struct ospf_opaque_functab
*
441 ospf_opaque_functab_lookup (struct ospf_lsa
*lsa
)
445 struct ospf_opaque_functab
*functab
;
446 u_char key
= GET_OPAQUE_TYPE (ntohl (lsa
->data
->id
.s_addr
));
448 if ((funclist
= ospf_get_opaque_funclist (lsa
->data
->type
)) != NULL
)
449 for (node
= listhead (funclist
); node
; nextnode (node
))
450 if ((functab
= getdata (node
)) != NULL
)
451 if (functab
->opaque_type
== key
)
457 /*------------------------------------------------------------------------*
458 * Followings are management functions for self-originated LSA entries.
459 *------------------------------------------------------------------------*/
462 * Opaque-LSA control information per opaque-type.
463 * Single Opaque-Type may have multiple instances; each of them will be
464 * identified by their opaque-id.
466 struct opaque_info_per_type
471 enum { PROC_NORMAL
, PROC_SUSPEND
} status
;
474 * Thread for (re-)origination scheduling for this opaque-type.
476 * Initial origination of Opaque-LSAs is controlled by generic
477 * Opaque-LSA handling module so that same opaque-type entries are
478 * called all at once when certain conditions are met.
479 * However, there might be cases that some Opaque-LSA clients need
480 * to (re-)originate their own Opaque-LSAs out-of-sync with others.
481 * This thread is prepared for that specific purpose.
483 struct thread
*t_opaque_lsa_self
;
486 * Backpointer to an "owner" which is LSA-type dependent.
487 * type-9: struct ospf_interface
488 * type-10: struct ospf_area
489 * type-11: struct ospf
493 /* Collection of callback functions for this opaque-type. */
494 struct ospf_opaque_functab
*functab
;
496 /* List of Opaque-LSA control informations per opaque-id. */
500 /* Opaque-LSA control information per opaque-id. */
501 struct opaque_info_per_id
505 /* Thread for refresh/flush scheduling for this opaque-type/id. */
506 struct thread
*t_opaque_lsa_self
;
508 /* Backpointer to Opaque-LSA control information per opaque-type. */
509 struct opaque_info_per_type
*opqctl_type
;
511 /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
512 struct ospf_lsa
*lsa
;
515 static struct opaque_info_per_type
*register_opaque_info_per_type (struct ospf_opaque_functab
*functab
, struct ospf_lsa
*new);
516 static struct opaque_info_per_type
*lookup_opaque_info_by_type (struct ospf_lsa
*lsa
);
517 static struct opaque_info_per_id
*register_opaque_info_per_id (struct opaque_info_per_type
*oipt
, struct ospf_lsa
*new);
518 static struct opaque_info_per_id
*lookup_opaque_info_by_id (struct opaque_info_per_type
*oipt
, struct ospf_lsa
*lsa
);
519 static struct opaque_info_per_id
*register_opaque_lsa (struct ospf_lsa
*new);
522 static struct opaque_info_per_type
*
523 register_opaque_info_per_type (struct ospf_opaque_functab
*functab
,
524 struct ospf_lsa
*new)
527 struct opaque_info_per_type
*oipt
;
529 if ((oipt
= XCALLOC (MTYPE_OPAQUE_INFO_PER_TYPE
,
530 sizeof (struct opaque_info_per_type
))) == NULL
)
532 zlog_warn ("register_opaque_info_per_type: XMALLOC: %s", strerror (errno
));
536 switch (new->data
->type
)
538 case OSPF_OPAQUE_LINK_LSA
:
539 oipt
->owner
= new->oi
;
540 listnode_add (new->oi
->opaque_lsa_self
, oipt
);
542 case OSPF_OPAQUE_AREA_LSA
:
543 oipt
->owner
= new->area
;
544 listnode_add (new->area
->opaque_lsa_self
, oipt
);
546 case OSPF_OPAQUE_AS_LSA
:
547 top
= ospf_lookup ();
548 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
);
558 zlog_warn ("register_opaque_info_per_type: Unexpected LSA-type(%u)", new->data
->type
);
559 free_opaque_info_per_type ((void *) oipt
);
561 goto out
; /* This case may not exist. */
564 oipt
->lsa_type
= new->data
->type
;
565 oipt
->opaque_type
= GET_OPAQUE_TYPE (ntohl (new->data
->id
.s_addr
));
566 oipt
->status
= PROC_NORMAL
;
567 oipt
->t_opaque_lsa_self
= NULL
;
568 oipt
->functab
= functab
;
569 functab
->oipt
= oipt
;
570 oipt
->id_list
= list_new ();
571 oipt
->id_list
->del
= free_opaque_info_per_id
;
578 free_opaque_info_per_type (void *val
)
580 struct opaque_info_per_type
*oipt
= (struct opaque_info_per_type
*) val
;
581 struct opaque_info_per_id
*oipi
;
582 struct ospf_lsa
*lsa
;
585 /* Control information per opaque-id may still exist. */
586 for (node
= listhead (oipt
->id_list
); node
; nextnode (node
))
588 if ((oipi
= getdata (node
)) == NULL
)
590 if ((lsa
= oipi
->lsa
) == NULL
)
592 if (IS_LSA_MAXAGE (lsa
))
594 ospf_opaque_lsa_flush_schedule (lsa
);
597 /* Remove "oipt" from its owner's self-originated LSA list. */
598 switch (oipt
->lsa_type
)
600 case OSPF_OPAQUE_LINK_LSA
:
602 struct ospf_interface
*oi
= (struct ospf_interface
*)(oipt
->owner
);
603 listnode_delete (oi
->opaque_lsa_self
, oipt
);
606 case OSPF_OPAQUE_AREA_LSA
:
608 struct ospf_area
*area
= (struct ospf_area
*)(oipt
->owner
);
609 listnode_delete (area
->opaque_lsa_self
, oipt
);
612 case OSPF_OPAQUE_AS_LSA
:
614 struct ospf
*top
= (struct ospf
*)(oipt
->owner
);
615 listnode_delete (top
->opaque_lsa_self
, oipt
);
619 zlog_warn ("free_opaque_info_per_type: Unexpected LSA-type(%u)", oipt
->lsa_type
);
620 break; /* This case may not exist. */
623 OSPF_TIMER_OFF (oipt
->t_opaque_lsa_self
);
624 list_delete (oipt
->id_list
);
625 XFREE (MTYPE_OPAQUE_INFO_PER_TYPE
, oipt
);
629 static struct opaque_info_per_type
*
630 lookup_opaque_info_by_type (struct ospf_lsa
*lsa
)
633 struct ospf_area
*area
;
634 struct ospf_interface
*oi
;
637 struct opaque_info_per_type
*oipt
= NULL
;
638 u_char key
= GET_OPAQUE_TYPE (ntohl (lsa
->data
->id
.s_addr
));
640 switch (lsa
->data
->type
)
642 case OSPF_OPAQUE_LINK_LSA
:
643 if ((oi
= lsa
->oi
) != NULL
)
644 listtop
= oi
->opaque_lsa_self
;
646 zlog_warn ("Type-9 Opaque-LSA: Reference to OI is missing?");
648 case OSPF_OPAQUE_AREA_LSA
:
649 if ((area
= lsa
->area
) != NULL
)
650 listtop
= area
->opaque_lsa_self
;
652 zlog_warn ("Type-10 Opaque-LSA: Reference to AREA is missing?");
654 case OSPF_OPAQUE_AS_LSA
:
655 top
= ospf_lookup ();
656 if ((area
= lsa
->area
) != NULL
&& (top
= area
->ospf
) == NULL
)
658 zlog_warn ("Type-11 Opaque-LSA: Reference to OSPF is missing?");
659 break; /* Unlikely to happen. */
661 listtop
= top
->opaque_lsa_self
;
664 zlog_warn ("lookup_opaque_info_by_type: Unexpected LSA-type(%u)", lsa
->data
->type
);
669 for (node
= listhead (listtop
); node
; nextnode (node
))
670 if ((oipt
= getdata (node
)) != NULL
)
671 if (oipt
->opaque_type
== key
)
677 static struct opaque_info_per_id
*
678 register_opaque_info_per_id (struct opaque_info_per_type
*oipt
,
679 struct ospf_lsa
*new)
681 struct opaque_info_per_id
*oipi
;
683 if ((oipi
= XCALLOC (MTYPE_OPAQUE_INFO_PER_ID
,
684 sizeof (struct opaque_info_per_id
))) == NULL
)
686 zlog_warn ("register_opaque_info_per_id: XMALLOC: %s", strerror (errno
));
689 oipi
->opaque_id
= GET_OPAQUE_ID (ntohl (new->data
->id
.s_addr
));
690 oipi
->t_opaque_lsa_self
= NULL
;
691 oipi
->opqctl_type
= oipt
;
692 oipi
->lsa
= ospf_lsa_lock (new);
694 listnode_add (oipt
->id_list
, oipi
);
701 free_opaque_info_per_id (void *val
)
703 struct opaque_info_per_id
*oipi
= (struct opaque_info_per_id
*) val
;
705 OSPF_TIMER_OFF (oipi
->t_opaque_lsa_self
);
706 if (oipi
->lsa
!= NULL
)
707 ospf_lsa_unlock (oipi
->lsa
);
708 XFREE (MTYPE_OPAQUE_INFO_PER_ID
, oipi
);
712 static struct opaque_info_per_id
*
713 lookup_opaque_info_by_id (struct opaque_info_per_type
*oipt
,
714 struct ospf_lsa
*lsa
)
717 struct opaque_info_per_id
*oipi
;
718 u_int32_t key
= GET_OPAQUE_ID (ntohl (lsa
->data
->id
.s_addr
));
720 for (node
= listhead (oipt
->id_list
); node
; nextnode (node
))
721 if ((oipi
= getdata (node
)) != NULL
)
722 if (oipi
->opaque_id
== key
)
728 static struct opaque_info_per_id
*
729 register_opaque_lsa (struct ospf_lsa
*new)
731 struct ospf_opaque_functab
*functab
;
732 struct opaque_info_per_type
*oipt
;
733 struct opaque_info_per_id
*oipi
= NULL
;
735 if ((functab
= ospf_opaque_functab_lookup (new)) == NULL
)
738 if ((oipt
= lookup_opaque_info_by_type (new)) == NULL
739 && (oipt
= register_opaque_info_per_type (functab
, new)) == NULL
)
742 if ((oipi
= register_opaque_info_per_id (oipt
, new)) == NULL
)
749 /*------------------------------------------------------------------------*
750 * Followings are (vty) configuration functions for Opaque-LSAs handling.
751 *------------------------------------------------------------------------*/
753 DEFUN (capability_opaque
,
754 capability_opaque_cmd
,
756 "Enable specific OSPF feature\n"
759 struct ospf
*ospf
= (struct ospf
*) vty
->index
;
761 /* Turn on the "master switch" of opaque-lsa capability. */
762 if (!CHECK_FLAG (ospf
->config
, OSPF_OPAQUE_CAPABLE
))
764 if (IS_DEBUG_OSPF_EVENT
)
765 zlog_info ("Opaque capability: OFF -> ON");
767 SET_FLAG (ospf
->config
, OSPF_OPAQUE_CAPABLE
);
768 ospf_renegotiate_optional_capabilities (ospf
);
773 ALIAS (capability_opaque
,
774 ospf_opaque_capable_cmd
,
776 "OSPF specific commands\n"
777 "Enable the Opaque-LSA capability (rfc2370)\n")
779 DEFUN (no_capability_opaque
,
780 no_capability_opaque_cmd
,
781 "no capability opaque",
783 "Enable specific OSPF feature\n"
786 struct ospf
*ospf
= (struct ospf
*) vty
->index
;
788 /* Turn off the "master switch" of opaque-lsa capability. */
789 if (CHECK_FLAG (ospf
->config
, OSPF_OPAQUE_CAPABLE
))
791 if (IS_DEBUG_OSPF_EVENT
)
792 zlog_info ("Opaque capability: ON -> OFF");
794 UNSET_FLAG (ospf
->config
, OSPF_OPAQUE_CAPABLE
);
795 ospf_renegotiate_optional_capabilities (ospf
);
800 ALIAS (no_capability_opaque
,
801 no_ospf_opaque_capable_cmd
,
802 "no ospf opaque-lsa",
804 "OSPF specific commands\n"
805 "Disable the Opaque-LSA capability (rfc2370)\n")
808 ospf_opaque_register_vty (void)
810 install_element (OSPF_NODE
, &capability_opaque_cmd
);
811 install_element (OSPF_NODE
, &no_capability_opaque_cmd
);
812 install_element (OSPF_NODE
, &ospf_opaque_capable_cmd
);
813 install_element (OSPF_NODE
, &no_ospf_opaque_capable_cmd
);
817 /*------------------------------------------------------------------------*
818 * Followings are collection of user-registered function callers.
819 *------------------------------------------------------------------------*/
822 opaque_lsa_new_if_callback (list funclist
, struct interface
*ifp
)
825 struct ospf_opaque_functab
*functab
;
828 for (node
= listhead (funclist
); node
; nextnode (node
))
829 if ((functab
= getdata (node
)) != NULL
)
830 if (functab
->new_if_hook
!= NULL
)
831 if ((* functab
->new_if_hook
)(ifp
) != 0)
839 opaque_lsa_del_if_callback (list funclist
, struct interface
*ifp
)
842 struct ospf_opaque_functab
*functab
;
845 for (node
= listhead (funclist
); node
; nextnode (node
))
846 if ((functab
= getdata (node
)) != NULL
)
847 if (functab
->del_if_hook
!= NULL
)
848 if ((* functab
->del_if_hook
)(ifp
) != 0)
856 opaque_lsa_ism_change_callback (list funclist
,
857 struct ospf_interface
*oi
, int old_status
)
860 struct ospf_opaque_functab
*functab
;
862 for (node
= listhead (funclist
); node
; nextnode (node
))
863 if ((functab
= getdata (node
)) != NULL
)
864 if (functab
->ism_change_hook
!= NULL
)
865 (* functab
->ism_change_hook
)(oi
, old_status
);
870 opaque_lsa_nsm_change_callback (list funclist
,
871 struct ospf_neighbor
*nbr
, int old_status
)
874 struct ospf_opaque_functab
*functab
;
876 for (node
= listhead (funclist
); node
; nextnode (node
))
877 if ((functab
= getdata (node
)) != NULL
)
878 if (functab
->nsm_change_hook
!= NULL
)
879 (* functab
->nsm_change_hook
)(nbr
, old_status
);
884 opaque_lsa_config_write_router_callback (list funclist
, struct vty
*vty
)
887 struct ospf_opaque_functab
*functab
;
889 for (node
= listhead (funclist
); node
; nextnode (node
))
890 if ((functab
= getdata (node
)) != NULL
)
891 if (functab
->config_write_router
!= NULL
)
892 (* functab
->config_write_router
)(vty
);
897 opaque_lsa_config_write_if_callback (list funclist
,
898 struct vty
*vty
, struct interface
*ifp
)
901 struct ospf_opaque_functab
*functab
;
903 for (node
= listhead (funclist
); node
; nextnode (node
))
904 if ((functab
= getdata (node
)) != NULL
)
905 if (functab
->config_write_if
!= NULL
)
906 (* functab
->config_write_if
)(vty
, ifp
);
911 opaque_lsa_config_write_debug_callback (list funclist
, struct vty
*vty
)
914 struct ospf_opaque_functab
*functab
;
916 for (node
= listhead (funclist
); node
; nextnode (node
))
917 if ((functab
= getdata (node
)) != NULL
)
918 if (functab
->config_write_debug
!= NULL
)
919 (* functab
->config_write_debug
)(vty
);
924 opaque_lsa_originate_callback (list funclist
, void *lsa_type_dependent
)
927 struct ospf_opaque_functab
*functab
;
930 for (node
= listhead (funclist
); node
; nextnode (node
))
931 if ((functab
= getdata (node
)) != NULL
)
932 if (functab
->lsa_originator
!= NULL
)
933 if ((* functab
->lsa_originator
)(lsa_type_dependent
) != 0)
941 new_lsa_callback (list funclist
, struct ospf_lsa
*lsa
)
944 struct ospf_opaque_functab
*functab
;
947 /* This function handles ALL types of LSAs, not only opaque ones. */
948 for (node
= listhead (funclist
); node
; nextnode (node
))
949 if ((functab
= getdata (node
)) != NULL
)
950 if (functab
->new_lsa_hook
!= NULL
)
951 if ((* functab
->new_lsa_hook
)(lsa
) != 0)
959 del_lsa_callback (list funclist
, struct ospf_lsa
*lsa
)
962 struct ospf_opaque_functab
*functab
;
965 /* This function handles ALL types of LSAs, not only opaque ones. */
966 for (node
= listhead (funclist
); node
; nextnode (node
))
967 if ((functab
= getdata (node
)) != NULL
)
968 if (functab
->del_lsa_hook
!= NULL
)
969 if ((* functab
->del_lsa_hook
)(lsa
) != 0)
976 /*------------------------------------------------------------------------*
977 * Followings are glue functions to call Opaque-LSA specific processing.
978 *------------------------------------------------------------------------*/
981 ospf_opaque_new_if (struct interface
*ifp
)
986 funclist
= ospf_opaque_wildcard_funclist
;
987 if (opaque_lsa_new_if_callback (funclist
, ifp
) != 0)
990 funclist
= ospf_opaque_type9_funclist
;
991 if (opaque_lsa_new_if_callback (funclist
, ifp
) != 0)
994 funclist
= ospf_opaque_type10_funclist
;
995 if (opaque_lsa_new_if_callback (funclist
, ifp
) != 0)
998 funclist
= ospf_opaque_type11_funclist
;
999 if (opaque_lsa_new_if_callback (funclist
, ifp
) != 0)
1008 ospf_opaque_del_if (struct interface
*ifp
)
1013 funclist
= ospf_opaque_wildcard_funclist
;
1014 if (opaque_lsa_del_if_callback (funclist
, ifp
) != 0)
1017 funclist
= ospf_opaque_type9_funclist
;
1018 if (opaque_lsa_del_if_callback (funclist
, ifp
) != 0)
1021 funclist
= ospf_opaque_type10_funclist
;
1022 if (opaque_lsa_del_if_callback (funclist
, ifp
) != 0)
1025 funclist
= ospf_opaque_type11_funclist
;
1026 if (opaque_lsa_del_if_callback (funclist
, ifp
) != 0)
1035 ospf_opaque_ism_change (struct ospf_interface
*oi
, int old_status
)
1039 funclist
= ospf_opaque_wildcard_funclist
;
1040 opaque_lsa_ism_change_callback (funclist
, oi
, old_status
);
1042 funclist
= ospf_opaque_type9_funclist
;
1043 opaque_lsa_ism_change_callback (funclist
, oi
, old_status
);
1045 funclist
= ospf_opaque_type10_funclist
;
1046 opaque_lsa_ism_change_callback (funclist
, oi
, old_status
);
1048 funclist
= ospf_opaque_type11_funclist
;
1049 opaque_lsa_ism_change_callback (funclist
, oi
, old_status
);
1055 ospf_opaque_nsm_change (struct ospf_neighbor
*nbr
, int old_state
)
1060 if ((top
= oi_to_top (nbr
->oi
)) == NULL
)
1063 if (old_state
!= NSM_Full
&& nbr
->state
== NSM_Full
)
1065 if (CHECK_FLAG (nbr
->options
, OSPF_OPTION_O
))
1067 if (! CHECK_FLAG (top
->opaque
, OPAQUE_OPERATION_READY_BIT
))
1069 if (IS_DEBUG_OSPF_EVENT
)
1070 zlog_info ("Opaque-LSA: Now get operational!");
1072 SET_FLAG (top
->opaque
, OPAQUE_OPERATION_READY_BIT
);
1075 ospf_opaque_lsa_originate_schedule (nbr
->oi
, NULL
);
1079 if (old_state
== NSM_Full
&& nbr
->state
!= NSM_Full
)
1083 * If no more opaque-capable full-state neighbor remains in the
1084 * flooding scope which corresponds to Opaque-LSA type, periodic
1085 * LS flooding should be stopped.
1091 funclist
= ospf_opaque_wildcard_funclist
;
1092 opaque_lsa_nsm_change_callback (funclist
, nbr
, old_state
);
1094 funclist
= ospf_opaque_type9_funclist
;
1095 opaque_lsa_nsm_change_callback (funclist
, nbr
, old_state
);
1097 funclist
= ospf_opaque_type10_funclist
;
1098 opaque_lsa_nsm_change_callback (funclist
, nbr
, old_state
);
1100 funclist
= ospf_opaque_type11_funclist
;
1101 opaque_lsa_nsm_change_callback (funclist
, nbr
, old_state
);
1108 ospf_opaque_config_write_router (struct vty
*vty
, struct ospf
*ospf
)
1112 if (CHECK_FLAG (ospf
->config
, OSPF_OPAQUE_CAPABLE
))
1113 vty_out (vty
, " capability opaque%s", VTY_NEWLINE
);
1115 funclist
= ospf_opaque_wildcard_funclist
;
1116 opaque_lsa_config_write_router_callback (funclist
, vty
);
1118 funclist
= ospf_opaque_type9_funclist
;
1119 opaque_lsa_config_write_router_callback (funclist
, vty
);
1121 funclist
= ospf_opaque_type10_funclist
;
1122 opaque_lsa_config_write_router_callback (funclist
, vty
);
1124 funclist
= ospf_opaque_type11_funclist
;
1125 opaque_lsa_config_write_router_callback (funclist
, vty
);
1131 ospf_opaque_config_write_if (struct vty
*vty
, struct interface
*ifp
)
1135 funclist
= ospf_opaque_wildcard_funclist
;
1136 opaque_lsa_config_write_if_callback (funclist
, vty
, ifp
);
1138 funclist
= ospf_opaque_type9_funclist
;
1139 opaque_lsa_config_write_if_callback (funclist
, vty
, ifp
);
1141 funclist
= ospf_opaque_type10_funclist
;
1142 opaque_lsa_config_write_if_callback (funclist
, vty
, ifp
);
1144 funclist
= ospf_opaque_type11_funclist
;
1145 opaque_lsa_config_write_if_callback (funclist
, vty
, ifp
);
1151 ospf_opaque_config_write_debug (struct vty
*vty
)
1155 funclist
= ospf_opaque_wildcard_funclist
;
1156 opaque_lsa_config_write_debug_callback (funclist
, vty
);
1158 funclist
= ospf_opaque_type9_funclist
;
1159 opaque_lsa_config_write_debug_callback (funclist
, vty
);
1161 funclist
= ospf_opaque_type10_funclist
;
1162 opaque_lsa_config_write_debug_callback (funclist
, vty
);
1164 funclist
= ospf_opaque_type11_funclist
;
1165 opaque_lsa_config_write_debug_callback (funclist
, vty
);
1171 show_opaque_info_detail (struct vty
*vty
, struct ospf_lsa
*lsa
)
1173 struct lsa_header
*lsah
= (struct lsa_header
*) lsa
->data
;
1174 u_int32_t lsid
= ntohl (lsah
->id
.s_addr
);
1175 u_char opaque_type
= GET_OPAQUE_TYPE (lsid
);
1176 u_int32_t opaque_id
= GET_OPAQUE_ID (lsid
);
1177 struct ospf_opaque_functab
*functab
;
1179 /* Switch output functionality by vty address. */
1182 vty_out (vty
, " Opaque-Type %u (%s)%s", opaque_type
,
1183 ospf_opaque_type_name (opaque_type
), VTY_NEWLINE
);
1184 vty_out (vty
, " Opaque-ID 0x%x%s", opaque_id
, VTY_NEWLINE
);
1186 vty_out (vty
, " Opaque-Info: %u octets of data%s%s",
1187 ntohs (lsah
->length
) - OSPF_LSA_HEADER_SIZE
,
1188 VALID_OPAQUE_INFO_LEN(lsah
) ? "" : "(Invalid length?)",
1193 zlog_info (" Opaque-Type %u (%s)", opaque_type
,
1194 ospf_opaque_type_name (opaque_type
));
1195 zlog_info (" Opaque-ID 0x%x", opaque_id
);
1197 zlog_info (" Opaque-Info: %u octets of data%s",
1198 ntohs (lsah
->length
) - OSPF_LSA_HEADER_SIZE
,
1199 VALID_OPAQUE_INFO_LEN(lsah
) ? "" : "(Invalid length?)");
1202 /* Call individual output functions. */
1203 if ((functab
= ospf_opaque_functab_lookup (lsa
)) != NULL
)
1204 if (functab
->show_opaque_info
!= NULL
)
1205 (* functab
->show_opaque_info
)(vty
, lsa
);
1211 ospf_opaque_lsa_dump (struct stream
*s
, u_int16_t length
)
1213 struct ospf_lsa lsa
;
1215 lsa
.data
= (struct lsa_header
*) STREAM_PNT (s
);
1216 show_opaque_info_detail (NULL
, &lsa
);
1221 ospf_opaque_lsa_install_hook (struct ospf_lsa
*lsa
)
1227 * Some Opaque-LSA user may want to monitor every LSA installation
1228 * into the LSDB, regardless with target LSA type.
1230 funclist
= ospf_opaque_wildcard_funclist
;
1231 if (new_lsa_callback (funclist
, lsa
) != 0)
1234 funclist
= ospf_opaque_type9_funclist
;
1235 if (new_lsa_callback (funclist
, lsa
) != 0)
1238 funclist
= ospf_opaque_type10_funclist
;
1239 if (new_lsa_callback (funclist
, lsa
) != 0)
1242 funclist
= ospf_opaque_type11_funclist
;
1243 if (new_lsa_callback (funclist
, lsa
) != 0)
1252 ospf_opaque_lsa_delete_hook (struct ospf_lsa
*lsa
)
1258 * Some Opaque-LSA user may want to monitor every LSA deletion
1259 * from the LSDB, regardless with target LSA type.
1261 funclist
= ospf_opaque_wildcard_funclist
;
1262 if (del_lsa_callback (funclist
, lsa
) != 0)
1265 funclist
= ospf_opaque_type9_funclist
;
1266 if (del_lsa_callback (funclist
, lsa
) != 0)
1269 funclist
= ospf_opaque_type10_funclist
;
1270 if (del_lsa_callback (funclist
, lsa
) != 0)
1273 funclist
= ospf_opaque_type11_funclist
;
1274 if (del_lsa_callback (funclist
, lsa
) != 0)
1282 /*------------------------------------------------------------------------*
1283 * Followings are Opaque-LSA origination/refresh management functions.
1284 *------------------------------------------------------------------------*/
1286 static int ospf_opaque_type9_lsa_originate (struct thread
*t
);
1287 static int ospf_opaque_type10_lsa_originate (struct thread
*t
);
1288 static int ospf_opaque_type11_lsa_originate (struct thread
*t
);
1289 static void ospf_opaque_lsa_reoriginate_resume (list listtop
, void *arg
);
1292 ospf_opaque_lsa_originate_schedule (struct ospf_interface
*oi
, int *delay0
)
1295 struct ospf_area
*area
;
1297 struct opaque_info_per_type
*oipt
;
1300 if ((top
= oi_to_top (oi
)) == NULL
|| (area
= oi
->area
) == NULL
)
1302 zlog_warn ("ospf_opaque_lsa_originate_schedule: Invalid argument?");
1306 /* It may not a right time to schedule origination now. */
1307 if (! CHECK_FLAG (top
->opaque
, OPAQUE_OPERATION_READY_BIT
))
1309 if (IS_DEBUG_OSPF_EVENT
)
1310 zlog_info ("ospf_opaque_lsa_originate_schedule: Not operational.");
1311 goto out
; /* This is not an error. */
1313 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top
->opaque
))
1315 if (IS_DEBUG_OSPF_EVENT
)
1316 zlog_info ("ospf_opaque_lsa_originate_schedule: Under blockade.");
1317 goto out
; /* This is not an error, too. */
1324 * There might be some entries that have been waiting for triggering
1325 * of per opaque-type re-origination get resumed.
1327 ospf_opaque_lsa_reoriginate_resume ( oi
->opaque_lsa_self
, (void *) oi
);
1328 ospf_opaque_lsa_reoriginate_resume (area
->opaque_lsa_self
, (void *) area
);
1329 ospf_opaque_lsa_reoriginate_resume ( top
->opaque_lsa_self
, (void *) top
);
1332 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1334 if (! list_isempty (ospf_opaque_type9_funclist
)
1335 && list_isempty (oi
->opaque_lsa_self
)
1336 && oi
->t_opaque_lsa_self
== NULL
)
1338 if (IS_DEBUG_OSPF_EVENT
)
1339 zlog_info ("Schedule Type-9 Opaque-LSA origination in %d sec later.", delay
);
1340 oi
->t_opaque_lsa_self
=
1341 thread_add_timer (master
, ospf_opaque_type9_lsa_originate
, oi
, delay
);
1342 delay
+= OSPF_MIN_LS_INTERVAL
;
1345 if (! list_isempty (ospf_opaque_type10_funclist
)
1346 && list_isempty (area
->opaque_lsa_self
)
1347 && area
->t_opaque_lsa_self
== NULL
)
1350 * One AREA may contain multiple OIs, but above 2nd and 3rd
1351 * conditions prevent from scheduling the originate function
1354 if (IS_DEBUG_OSPF_EVENT
)
1355 zlog_info ("Schedule Type-10 Opaque-LSA origination in %d sec later.", delay
);
1356 area
->t_opaque_lsa_self
=
1357 thread_add_timer (master
, ospf_opaque_type10_lsa_originate
,
1359 delay
+= OSPF_MIN_LS_INTERVAL
;
1362 if (! list_isempty (ospf_opaque_type11_funclist
)
1363 && list_isempty (top
->opaque_lsa_self
)
1364 && top
->t_opaque_lsa_self
== NULL
)
1367 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1368 * conditions prevent from scheduling the originate function
1371 if (IS_DEBUG_OSPF_EVENT
)
1372 zlog_info ("Schedule Type-11 Opaque-LSA origination in %d sec later.", delay
);
1373 top
->t_opaque_lsa_self
=
1374 thread_add_timer (master
, ospf_opaque_type11_lsa_originate
,
1376 delay
+= OSPF_MIN_LS_INTERVAL
;
1380 * Following section treats a special situation that this node's
1381 * opaque capability has changed as "ON -> OFF -> ON".
1383 if (! list_isempty (ospf_opaque_type9_funclist
)
1384 && ! list_isempty (oi
->opaque_lsa_self
))
1386 for (node
= listhead (oi
->opaque_lsa_self
); node
; nextnode (node
))
1388 if ((oipt
= getdata (node
)) == NULL
/* Something wrong? */
1389 || oipt
->t_opaque_lsa_self
!= NULL
/* Waiting for a thread call. */
1390 || oipt
->status
== PROC_SUSPEND
/* Cannot originate now. */
1391 || ! list_isempty (oipt
->id_list
)) /* Handler is already active. */
1394 ospf_opaque_lsa_reoriginate_schedule ((void *) oi
,
1395 OSPF_OPAQUE_LINK_LSA
, oipt
->opaque_type
);
1399 if (! list_isempty (ospf_opaque_type10_funclist
)
1400 && ! list_isempty (area
->opaque_lsa_self
))
1402 for (node
= listhead (area
->opaque_lsa_self
); node
; nextnode (node
))
1404 if ((oipt
= getdata (node
)) == NULL
/* Something wrong? */
1405 || oipt
->t_opaque_lsa_self
!= NULL
/* Waiting for a thread call. */
1406 || oipt
->status
== PROC_SUSPEND
/* Cannot originate now. */
1407 || ! list_isempty (oipt
->id_list
)) /* Handler is already active. */
1410 ospf_opaque_lsa_reoriginate_schedule ((void *) area
,
1411 OSPF_OPAQUE_AREA_LSA
, oipt
->opaque_type
);
1415 if (! list_isempty (ospf_opaque_type11_funclist
)
1416 && ! list_isempty (top
->opaque_lsa_self
))
1418 for (node
= listhead (top
->opaque_lsa_self
); node
; nextnode (node
))
1420 if ((oipt
= getdata (node
)) == NULL
/* Something wrong? */
1421 || oipt
->t_opaque_lsa_self
!= NULL
/* Waiting for a thread call. */
1422 || oipt
->status
== PROC_SUSPEND
/* Cannot originate now. */
1423 || ! list_isempty (oipt
->id_list
)) /* Handler is already active. */
1426 ospf_opaque_lsa_reoriginate_schedule ((void *) top
,
1427 OSPF_OPAQUE_AS_LSA
, oipt
->opaque_type
);
1439 ospf_opaque_type9_lsa_originate (struct thread
*t
)
1441 struct ospf_interface
*oi
;
1444 oi
= THREAD_ARG (t
);
1445 oi
->t_opaque_lsa_self
= NULL
;
1447 if (IS_DEBUG_OSPF_EVENT
)
1448 zlog_info ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
1451 rc
= opaque_lsa_originate_callback (ospf_opaque_type9_funclist
, oi
);
1457 ospf_opaque_type10_lsa_originate (struct thread
*t
)
1459 struct ospf_area
*area
;
1462 area
= THREAD_ARG (t
);
1463 area
->t_opaque_lsa_self
= NULL
;
1465 if (IS_DEBUG_OSPF_EVENT
)
1466 zlog_info ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
1467 inet_ntoa (area
->area_id
));
1469 rc
= opaque_lsa_originate_callback (ospf_opaque_type10_funclist
, area
);
1475 ospf_opaque_type11_lsa_originate (struct thread
*t
)
1480 top
= THREAD_ARG (t
);
1481 top
->t_opaque_lsa_self
= NULL
;
1483 if (IS_DEBUG_OSPF_EVENT
)
1484 zlog_info ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
1486 rc
= opaque_lsa_originate_callback (ospf_opaque_type11_funclist
, top
);
1492 ospf_opaque_lsa_reoriginate_resume (list listtop
, void *arg
)
1495 struct opaque_info_per_type
*oipt
;
1496 struct ospf_opaque_functab
*functab
;
1498 if (listtop
== NULL
)
1502 * Pickup oipt entries those which in SUSPEND status, and give
1503 * them a chance to start re-origination now.
1505 for (node
= listhead (listtop
); node
; nextnode (node
))
1507 if ((oipt
= getdata (node
)) == NULL
1508 || oipt
->status
!= PROC_SUSPEND
)
1511 oipt
->status
= PROC_NORMAL
;
1513 if ((functab
= oipt
->functab
) == NULL
1514 || functab
->lsa_originator
== NULL
)
1517 if ((* functab
->lsa_originator
)(arg
) != 0)
1519 zlog_warn ("ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", oipt
->opaque_type
);
1529 ospf_opaque_lsa_install (struct ospf_lsa
*lsa
, int rt_recalc
)
1531 struct ospf_lsa
*new = NULL
;
1532 struct opaque_info_per_type
*oipt
;
1533 struct opaque_info_per_id
*oipi
;
1536 /* Don't take "rt_recalc" into consideration for now. *//* XXX */
1538 if (! IS_LSA_SELF (lsa
))
1540 new = lsa
; /* Don't touch this LSA. */
1544 if (IS_DEBUG_OSPF (lsa
, LSA_INSTALL
))
1545 zlog_info ("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
)));
1547 /* Replace the existing lsa with the new one. */
1548 if ((oipt
= lookup_opaque_info_by_type (lsa
)) != NULL
1549 && (oipi
= lookup_opaque_info_by_id (oipt
, lsa
)) != NULL
)
1551 ospf_lsa_unlock (oipi
->lsa
);
1552 oipi
->lsa
= ospf_lsa_lock (lsa
);
1554 /* Register the new lsa entry and get its control info. */
1556 if ((oipi
= register_opaque_lsa (lsa
)) == NULL
)
1558 zlog_warn ("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1563 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1564 * for periodic refresh of self-originated Opaque-LSAs.
1566 switch (lsa
->data
->type
)
1568 case OSPF_OPAQUE_LINK_LSA
:
1569 if ((top
= oi_to_top (lsa
->oi
)) == NULL
)
1571 /* Above conditions must have passed. */
1572 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1576 case OSPF_OPAQUE_AREA_LSA
:
1577 if (lsa
->area
== NULL
|| (top
= lsa
->area
->ospf
) == NULL
)
1579 /* Above conditions must have passed. */
1580 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1584 case OSPF_OPAQUE_AS_LSA
:
1585 top
= ospf_lookup ();
1586 if (lsa
->area
!= NULL
&& (top
= lsa
->area
->ospf
) == NULL
)
1588 /* Above conditions must have passed. */
1589 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1594 zlog_warn ("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", lsa
->data
->type
);
1598 ospf_refresher_register_lsa (top
, lsa
);
1606 ospf_opaque_lsa_refresh (struct ospf_lsa
*lsa
)
1609 struct ospf_opaque_functab
*functab
;
1611 ospf
= ospf_lookup ();
1613 if ((functab
= ospf_opaque_functab_lookup (lsa
)) == NULL
1614 || functab
->lsa_refresher
== NULL
)
1617 * Though this LSA seems to have originated on this node, the
1618 * handling module for this "lsa-type and opaque-type" was
1619 * already deleted sometime ago.
1620 * Anyway, this node still has a responsibility to flush this
1621 * LSA from the routing domain.
1623 if (IS_DEBUG_OSPF_EVENT
)
1624 zlog_info ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa
->data
->type
, inet_ntoa (lsa
->data
->id
));
1626 lsa
->data
->ls_age
= htons (OSPF_LSA_MAXAGE
);
1627 ospf_lsa_maxage (ospf
, lsa
);
1630 (* functab
->lsa_refresher
)(lsa
);
1635 /*------------------------------------------------------------------------*
1636 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1637 * triggered by external interventions (vty session, signaling, etc).
1638 *------------------------------------------------------------------------*/
1640 #define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
1642 (T) = thread_add_timer (master, (F), (L), (V))
1644 static struct ospf_lsa
*pseudo_lsa (struct ospf_interface
*oi
, struct ospf_area
*area
, u_char lsa_type
, u_char opaque_type
);
1645 static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread
*t
);
1646 static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread
*t
);
1647 static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread
*t
);
1648 static int ospf_opaque_lsa_refresh_timer (struct thread
*t
);
1651 ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent
,
1652 u_char lsa_type
, u_char opaque_type
)
1655 struct ospf_area dummy
, *area
= NULL
;
1656 struct ospf_interface
*oi
= NULL
;
1658 struct ospf_lsa
*lsa
;
1659 struct opaque_info_per_type
*oipt
;
1660 int (* func
)(struct thread
*t
) = NULL
;
1665 case OSPF_OPAQUE_LINK_LSA
:
1666 if ((oi
= (struct ospf_interface
*) lsa_type_dependent
) == NULL
)
1668 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Type-9 Opaque-LSA: Invalid parameter?");
1671 if ((top
= oi_to_top (oi
)) == NULL
)
1673 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?", IF_NAME (oi
));
1676 if (! list_isempty (ospf_opaque_type9_funclist
)
1677 && list_isempty (oi
->opaque_lsa_self
)
1678 && oi
->t_opaque_lsa_self
!= NULL
)
1680 zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u): Common origination for OI(%s) has already started", opaque_type
, IF_NAME (oi
));
1683 func
= ospf_opaque_type9_lsa_reoriginate_timer
;
1685 case OSPF_OPAQUE_AREA_LSA
:
1686 if ((area
= (struct ospf_area
*) lsa_type_dependent
) == NULL
)
1688 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Type-10 Opaque-LSA: Invalid parameter?");
1691 if ((top
= area
->ospf
) == NULL
)
1693 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: AREA(%s) -> TOP?", inet_ntoa (area
->area_id
));
1696 if (! list_isempty (ospf_opaque_type10_funclist
)
1697 && list_isempty (area
->opaque_lsa_self
)
1698 && area
->t_opaque_lsa_self
!= NULL
)
1700 zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u): Common origination for AREA(%s) has already started", opaque_type
, inet_ntoa (area
->area_id
));
1703 func
= ospf_opaque_type10_lsa_reoriginate_timer
;
1705 case OSPF_OPAQUE_AS_LSA
:
1706 if ((top
= (struct ospf
*) lsa_type_dependent
) == NULL
)
1708 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Type-11 Opaque-LSA: Invalid parameter?");
1711 if (! list_isempty (ospf_opaque_type11_funclist
)
1712 && list_isempty (top
->opaque_lsa_self
)
1713 && top
->t_opaque_lsa_self
!= NULL
)
1715 zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u): Common origination has already started", opaque_type
);
1719 /* Fake "area" to pass "ospf" to a lookup function later. */
1723 func
= ospf_opaque_type11_lsa_reoriginate_timer
;
1726 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Unexpected LSA-type(%u)", lsa_type
);
1730 /* It may not a right time to schedule reorigination now. */
1731 if (! CHECK_FLAG (top
->opaque
, OPAQUE_OPERATION_READY_BIT
))
1733 if (IS_DEBUG_OSPF_EVENT
)
1734 zlog_info ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
1735 goto out
; /* This is not an error. */
1737 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top
->opaque
))
1739 if (IS_DEBUG_OSPF_EVENT
)
1740 zlog_info ("ospf_opaque_lsa_reoriginate_schedule: Under blockade.");
1741 goto out
; /* This is not an error, too. */
1744 /* Generate a dummy lsa to be passed for a lookup function. */
1745 lsa
= pseudo_lsa (oi
, area
, lsa_type
, opaque_type
);
1747 if ((oipt
= lookup_opaque_info_by_type (lsa
)) == NULL
)
1749 struct ospf_opaque_functab
*functab
;
1750 if ((functab
= ospf_opaque_functab_lookup (lsa
)) == NULL
)
1752 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: No associated function?: lsa_type(%u), opaque_type(%u)", lsa_type
, opaque_type
);
1755 if ((oipt
= register_opaque_info_per_type (functab
, lsa
)) == NULL
)
1757 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Cannot get a control info?: lsa_type(%u), opaque_type(%u)", lsa_type
, opaque_type
);
1762 if (oipt
->t_opaque_lsa_self
!= NULL
)
1764 if (IS_DEBUG_OSPF_EVENT
)
1765 zlog_info ("Type-%u Opaque-LSA has already scheduled to RE-ORIGINATE: [opaque-type=%u]", lsa_type
, GET_OPAQUE_TYPE (ntohl (lsa
->data
->id
.s_addr
)));
1770 * Different from initial origination time, in which various conditions
1771 * (opaque capability, neighbor status etc) are assured by caller of
1772 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1773 * it is highly possible that these conditions might not be satisfied
1774 * at the time of re-origination function is to be called.
1776 delay
= OSPF_MIN_LS_INTERVAL
; /* XXX */
1778 if (IS_DEBUG_OSPF_EVENT
)
1779 zlog_info ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d sec later: [opaque-type=%u]", lsa_type
, delay
, GET_OPAQUE_TYPE (ntohl (lsa
->data
->id
.s_addr
)));
1781 OSPF_OPAQUE_TIMER_ON (oipt
->t_opaque_lsa_self
, func
, oipt
, delay
);
1787 static struct ospf_lsa
*
1788 pseudo_lsa (struct ospf_interface
*oi
, struct ospf_area
*area
,
1789 u_char lsa_type
, u_char opaque_type
)
1791 static struct ospf_lsa lsa
= { 0 };
1792 static struct lsa_header lsah
= { 0 };
1799 lsah
.type
= lsa_type
;
1800 tmp
= SET_OPAQUE_LSID (opaque_type
, 0); /* Opaque-ID is unused here. */
1801 lsah
.id
.s_addr
= htonl (tmp
);
1807 ospf_opaque_type9_lsa_reoriginate_timer (struct thread
*t
)
1809 struct opaque_info_per_type
*oipt
;
1810 struct ospf_opaque_functab
*functab
;
1812 struct ospf_interface
*oi
;
1815 oipt
= THREAD_ARG (t
);
1816 oipt
->t_opaque_lsa_self
= NULL
;
1818 if ((functab
= oipt
->functab
) == NULL
1819 || functab
->lsa_originator
== NULL
)
1821 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1825 oi
= (struct ospf_interface
*) oipt
->owner
;
1826 if ((top
= oi_to_top (oi
)) == NULL
)
1828 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1832 if (! CHECK_FLAG (top
->config
, OSPF_OPAQUE_CAPABLE
)
1833 || ! ospf_if_is_enable (oi
)
1834 || ospf_nbr_count_opaque_capable (oi
) == 0)
1836 if (IS_DEBUG_OSPF_EVENT
)
1837 zlog_info ("Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...", oipt
->opaque_type
);
1839 oipt
->status
= PROC_SUSPEND
;
1844 if (IS_DEBUG_OSPF_EVENT
)
1845 zlog_info ("Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)", oipt
->opaque_type
, IF_NAME (oi
));
1847 rc
= (* functab
->lsa_originator
)(oi
);
1853 ospf_opaque_type10_lsa_reoriginate_timer (struct thread
*t
)
1855 struct opaque_info_per_type
*oipt
;
1856 struct ospf_opaque_functab
*functab
;
1859 struct ospf_area
*area
;
1860 struct ospf_interface
*oi
;
1863 oipt
= THREAD_ARG (t
);
1864 oipt
->t_opaque_lsa_self
= NULL
;
1866 if ((functab
= oipt
->functab
) == NULL
1867 || functab
->lsa_originator
== NULL
)
1869 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1873 area
= (struct ospf_area
*) oipt
->owner
;
1874 if (area
== NULL
|| (top
= area
->ospf
) == NULL
)
1876 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1880 /* There must be at least one "opaque-capable, full-state" neighbor. */
1882 for (node
= listhead (area
->oiflist
); node
; nextnode (node
))
1884 if ((oi
= getdata (node
)) == NULL
)
1886 if ((n
= ospf_nbr_count_opaque_capable (oi
)) > 0)
1890 if (n
== 0 || ! CHECK_FLAG (top
->config
, OSPF_OPAQUE_CAPABLE
))
1892 if (IS_DEBUG_OSPF_EVENT
)
1893 zlog_info ("Suspend re-origination of Type-10 Opaque-LSAs (opaque-type=%u) for a while...", oipt
->opaque_type
);
1895 oipt
->status
= PROC_SUSPEND
;
1900 if (IS_DEBUG_OSPF_EVENT
)
1901 zlog_info ("Timer[Type10-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for Area %s", oipt
->opaque_type
, inet_ntoa (area
->area_id
));
1903 rc
= (* functab
->lsa_originator
)(area
);
1909 ospf_opaque_type11_lsa_reoriginate_timer (struct thread
*t
)
1911 struct opaque_info_per_type
*oipt
;
1912 struct ospf_opaque_functab
*functab
;
1916 oipt
= THREAD_ARG (t
);
1917 oipt
->t_opaque_lsa_self
= NULL
;
1919 if ((functab
= oipt
->functab
) == NULL
1920 || functab
->lsa_originator
== NULL
)
1922 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: No associated function?");
1926 if ((top
= (struct ospf
*) oipt
->owner
) == NULL
)
1928 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1932 if (! CHECK_FLAG (top
->config
, OSPF_OPAQUE_CAPABLE
))
1934 if (IS_DEBUG_OSPF_EVENT
)
1935 zlog_info ("Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...", oipt
->opaque_type
);
1937 oipt
->status
= PROC_SUSPEND
;
1942 if (IS_DEBUG_OSPF_EVENT
)
1943 zlog_info ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt
->opaque_type
);
1945 rc
= (* functab
->lsa_originator
)(top
);
1950 extern int ospf_lsa_refresh_delay (struct ospf_lsa
*); /* ospf_lsa.c */
1953 ospf_opaque_lsa_refresh_schedule (struct ospf_lsa
*lsa0
)
1955 struct ospf
*ospf
= ospf
;
1956 struct opaque_info_per_type
*oipt
;
1957 struct opaque_info_per_id
*oipi
;
1958 struct ospf_lsa
*lsa
;
1961 ospf
= ospf_lookup ();
1963 if ((oipt
= lookup_opaque_info_by_type (lsa0
)) == NULL
1964 || (oipi
= lookup_opaque_info_by_id (oipt
, lsa0
)) == NULL
)
1966 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
1970 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
1971 if ((lsa
= oipi
->lsa
) == NULL
)
1973 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
1977 if (oipi
->t_opaque_lsa_self
!= NULL
)
1979 if (IS_DEBUG_OSPF_EVENT
)
1980 zlog_info ("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
)));
1984 /* Delete this lsa from neighbor retransmit-list. */
1985 switch (lsa
->data
->type
)
1987 case OSPF_OPAQUE_LINK_LSA
:
1988 case OSPF_OPAQUE_AREA_LSA
:
1989 ospf_ls_retransmit_delete_nbr_area (lsa
->area
, lsa
);
1991 case OSPF_OPAQUE_AS_LSA
:
1992 ospf_ls_retransmit_delete_nbr_as (ospf
, lsa
);
1995 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa
->data
->type
);
1999 delay
= ospf_lsa_refresh_delay (lsa
);
2001 if (IS_DEBUG_OSPF_EVENT
)
2002 zlog_info ("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
)));
2004 OSPF_OPAQUE_TIMER_ON (oipi
->t_opaque_lsa_self
,
2005 ospf_opaque_lsa_refresh_timer
, oipi
, delay
);
2011 ospf_opaque_lsa_refresh_timer (struct thread
*t
)
2013 struct opaque_info_per_id
*oipi
;
2014 struct ospf_opaque_functab
*functab
;
2015 struct ospf_lsa
*lsa
;
2017 if (IS_DEBUG_OSPF_EVENT
)
2018 zlog_info ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
2020 oipi
= THREAD_ARG (t
);
2021 oipi
->t_opaque_lsa_self
= NULL
;
2023 if ((lsa
= oipi
->lsa
) != NULL
)
2024 if ((functab
= oipi
->opqctl_type
->functab
) != NULL
)
2025 if (functab
->lsa_refresher
!= NULL
)
2026 (* functab
->lsa_refresher
)(lsa
);
2032 ospf_opaque_lsa_flush_schedule (struct ospf_lsa
*lsa0
)
2034 struct ospf
*ospf
= ospf
;
2035 struct opaque_info_per_type
*oipt
;
2036 struct opaque_info_per_id
*oipi
;
2037 struct ospf_lsa
*lsa
;
2039 ospf
= ospf_lookup ();
2041 if ((oipt
= lookup_opaque_info_by_type (lsa0
)) == NULL
2042 || (oipi
= lookup_opaque_info_by_id (oipt
, lsa0
)) == NULL
)
2044 zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2048 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2049 if ((lsa
= oipi
->lsa
) == NULL
)
2051 zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
2055 /* Delete this lsa from neighbor retransmit-list. */
2056 switch (lsa
->data
->type
)
2058 case OSPF_OPAQUE_LINK_LSA
:
2059 case OSPF_OPAQUE_AREA_LSA
:
2060 ospf_ls_retransmit_delete_nbr_area (lsa
->area
, lsa
);
2062 case OSPF_OPAQUE_AS_LSA
:
2063 ospf_ls_retransmit_delete_nbr_as (ospf
, lsa
);
2066 zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa
->data
->type
);
2070 /* Dequeue listnode entry from the list. */
2071 listnode_delete (oipt
->id_list
, oipi
);
2073 /* Avoid misjudgement in the next lookup. */
2074 if (listcount (oipt
->id_list
) == 0)
2075 oipt
->id_list
->head
= oipt
->id_list
->tail
= NULL
;
2077 /* Disassociate internal control information with the given lsa. */
2079 free_opaque_info_per_id ((void *) oipi
);
2081 /* Force given lsa's age to MaxAge. */
2082 lsa
->data
->ls_age
= htons (OSPF_LSA_MAXAGE
);
2084 if (IS_DEBUG_OSPF_EVENT
)
2085 zlog_info ("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
)));
2087 /* This lsa will be flushed and removed eventually. */
2088 ospf_lsa_maxage (ospf
, lsa
);
2094 /*------------------------------------------------------------------------*
2095 * Followings are control functions to block origination after restart.
2096 *------------------------------------------------------------------------*/
2098 static void ospf_opaque_exclude_lsa_from_lsreq (struct route_table
*nbrs
, struct ospf_neighbor
*inbr
, struct ospf_lsa
*lsa
);
2099 static void ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface
*oi
);
2100 static void ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area
*area
);
2101 static void ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf
*top
);
2102 static unsigned long ospf_opaque_nrxmt_self (struct route_table
*nbrs
, int lsa_type
);
2105 ospf_opaque_adjust_lsreq (struct ospf_neighbor
*nbr
, list lsas
)
2108 struct ospf_area
*area
;
2109 struct ospf_interface
*oi
;
2110 listnode node1
, node2
;
2111 struct ospf_lsa
*lsa
;
2113 if ((top
= oi_to_top (nbr
->oi
)) == NULL
)
2117 * If an instance of self-originated Opaque-LSA is found in the given
2118 * LSA list, and it is not installed to LSDB yet, exclude it from the
2119 * list "nbr->ls_req". In this way, it is assured that an LSReq message,
2120 * which might be sent in the process of flooding, will not request for
2121 * the LSA to be flushed immediately; otherwise, depending on timing,
2122 * an LSUpd message will carry instances of target LSAs with MaxAge,
2123 * while other LSUpd message might carry old LSA instances (non-MaxAge).
2124 * Obviously, the latter would trigger miserable situations that repeat
2125 * installation and removal of unwanted LSAs indefinitely.
2127 for (node1
= listhead (lsas
); node1
; nextnode (node1
))
2129 if ((lsa
= getdata (node1
)) == NULL
)
2132 /* Filter out unwanted LSAs. */
2133 if (! IS_OPAQUE_LSA (lsa
->data
->type
))
2135 if (! IPV4_ADDR_SAME (&lsa
->data
->adv_router
, &top
->router_id
))
2139 * Don't touch an LSA which has MaxAge; two possible cases.
2141 * 1) This LSA has originally flushed by myself (received LSUpd
2142 * message's router-id is equal to my router-id), and flooded
2143 * back by an opaque-capable router.
2145 * 2) This LSA has expired in an opaque-capable router and thus
2146 * flushed by the router.
2148 if (IS_LSA_MAXAGE (lsa
))
2151 /* If the LSA has installed in the LSDB, nothing to do here. */
2152 if (ospf_lsa_lookup_by_header (nbr
->oi
->area
, lsa
->data
) != NULL
)
2155 /* Ok, here we go. */
2156 switch (lsa
->data
->type
)
2158 case OSPF_OPAQUE_LINK_LSA
:
2160 ospf_opaque_exclude_lsa_from_lsreq (oi
->nbrs
, nbr
, lsa
);
2162 case OSPF_OPAQUE_AREA_LSA
:
2163 area
= nbr
->oi
->area
;
2164 for (node2
= listhead (area
->oiflist
); node2
; nextnode (node2
))
2166 if ((oi
= getdata (node2
)) == NULL
)
2168 ospf_opaque_exclude_lsa_from_lsreq (oi
->nbrs
, nbr
, lsa
);
2171 case OSPF_OPAQUE_AS_LSA
:
2172 for (node2
= listhead (top
->oiflist
); node2
; nextnode (node2
))
2174 if ((oi
= getdata (node2
)) == NULL
)
2176 ospf_opaque_exclude_lsa_from_lsreq (oi
->nbrs
, nbr
, lsa
);
2189 ospf_opaque_exclude_lsa_from_lsreq (struct route_table
*nbrs
,
2190 struct ospf_neighbor
*inbr
,
2191 struct ospf_lsa
*lsa
)
2193 struct route_node
*rn
;
2194 struct ospf_neighbor
*onbr
;
2195 struct ospf_lsa
*ls_req
;
2197 for (rn
= route_top (nbrs
); rn
; rn
= route_next (rn
))
2199 if ((onbr
= rn
->info
) == NULL
)
2203 if ((ls_req
= ospf_ls_request_lookup (onbr
, lsa
)) == NULL
)
2206 if (IS_DEBUG_OSPF_EVENT
)
2207 zlog_info ("LSA[%s]: Exclude this entry from LSReq to send.", dump_lsa_key (lsa
));
2209 ospf_ls_request_delete (onbr
, ls_req
);
2210 /* ospf_check_nbr_loading (onbr);*//* XXX */
2217 ospf_opaque_self_originated_lsa_received (struct ospf_neighbor
*nbr
, list lsas
)
2220 listnode node
, next
;
2221 struct ospf_lsa
*lsa
;
2224 if ((top
= oi_to_top (nbr
->oi
)) == NULL
)
2227 before
= IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top
->opaque
);
2229 for (node
= listhead (lsas
); node
; node
= next
)
2233 if ((lsa
= getdata (node
)) == NULL
)
2236 listnode_delete (lsas
, lsa
);
2239 * Since these LSA entries are not yet installed into corresponding
2240 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2242 lsa
->data
->ls_age
= htons (OSPF_LSA_MAXAGE
);
2243 switch (lsa
->data
->type
)
2245 case OSPF_OPAQUE_LINK_LSA
:
2246 SET_FLAG (top
->opaque
, OPAQUE_BLOCK_TYPE_09_LSA_BIT
);
2247 ospf_flood_through_area (nbr
->oi
->area
, NULL
/*inbr*/, lsa
);
2249 case OSPF_OPAQUE_AREA_LSA
:
2250 SET_FLAG (top
->opaque
, OPAQUE_BLOCK_TYPE_10_LSA_BIT
);
2251 ospf_flood_through_area (nbr
->oi
->area
, NULL
/*inbr*/, lsa
);
2253 case OSPF_OPAQUE_AS_LSA
:
2254 SET_FLAG (top
->opaque
, OPAQUE_BLOCK_TYPE_11_LSA_BIT
);
2255 ospf_flood_through_as (top
, NULL
/*inbr*/, lsa
);
2258 zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa
->data
->type
);
2262 ospf_lsa_discard (lsa
); /* List "lsas" will be deleted by caller. */
2265 if (before
== 0 && IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top
->opaque
))
2267 if (IS_DEBUG_OSPF_EVENT
)
2268 zlog_info ("Block Opaque-LSA origination: OFF -> ON");
2276 ospf_opaque_ls_ack_received (struct ospf_neighbor
*nbr
, list acks
)
2280 struct ospf_lsa
*lsa
;
2281 char type9_lsa_rcv
= 0, type10_lsa_rcv
= 0, type11_lsa_rcv
= 0;
2283 if ((top
= oi_to_top (nbr
->oi
)) == NULL
)
2286 for (node
= listhead (acks
); node
; nextnode (node
))
2288 if ((lsa
= getdata (node
)) == NULL
)
2291 switch (lsa
->data
->type
)
2293 case OSPF_OPAQUE_LINK_LSA
:
2295 /* Callback function... */
2297 case OSPF_OPAQUE_AREA_LSA
:
2299 /* Callback function... */
2301 case OSPF_OPAQUE_AS_LSA
:
2303 /* Callback function... */
2306 zlog_warn ("ospf_opaque_ls_ack_received: Unexpected LSA-type(%u)", lsa
->data
->type
);
2311 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top
->opaque
))
2314 struct ospf_interface
*oi
;
2317 && CHECK_FLAG (top
->opaque
, OPAQUE_BLOCK_TYPE_09_LSA_BIT
))
2318 ospf_opaque_type9_lsa_rxmt_nbr_check (nbr
->oi
);
2321 && CHECK_FLAG (top
->opaque
, OPAQUE_BLOCK_TYPE_10_LSA_BIT
))
2322 ospf_opaque_type10_lsa_rxmt_nbr_check (nbr
->oi
->area
);
2325 && CHECK_FLAG (top
->opaque
, OPAQUE_BLOCK_TYPE_11_LSA_BIT
))
2326 ospf_opaque_type11_lsa_rxmt_nbr_check (top
);
2328 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top
->opaque
))
2329 goto out
; /* Blocking still in progress. */
2331 if (IS_DEBUG_OSPF_EVENT
)
2332 zlog_info ("Block Opaque-LSA origination: ON -> OFF");
2334 if (! CHECK_FLAG (top
->config
, OSPF_OPAQUE_CAPABLE
))
2335 goto out
; /* Opaque capability condition must have changed. */
2337 /* Ok, let's start origination of Opaque-LSAs. */
2338 delay
= OSPF_MIN_LS_INTERVAL
;
2339 for (node
= listhead (top
->oiflist
); node
; nextnode (node
))
2341 if ((oi
= getdata (node
)) == NULL
)
2344 if (! ospf_if_is_enable (oi
)
2345 || ospf_nbr_count_opaque_capable (oi
) == 0)
2348 ospf_opaque_lsa_originate_schedule (oi
, &delay
);
2357 ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface
*oi
)
2361 n
= ospf_opaque_nrxmt_self (oi
->nbrs
, OSPF_OPAQUE_LINK_LSA
);
2364 if (IS_DEBUG_OSPF_EVENT
)
2365 zlog_info ("Self-originated type-9 Opaque-LSAs: OI(%s): Flush completed", IF_NAME (oi
));
2367 UNSET_FLAG (oi
->area
->ospf
->opaque
, OPAQUE_BLOCK_TYPE_09_LSA_BIT
);
2373 ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area
*area
)
2376 struct ospf_interface
*oi
;
2377 unsigned long n
= 0;
2379 for (node
= listhead (area
->oiflist
); node
; nextnode (node
))
2381 if ((oi
= getdata (node
)) == NULL
)
2384 if (area
->area_id
.s_addr
!= OSPF_AREA_BACKBONE
2385 && oi
->type
== OSPF_IFTYPE_VIRTUALLINK
)
2388 n
= ospf_opaque_nrxmt_self (oi
->nbrs
, OSPF_OPAQUE_AREA_LSA
);
2395 if (IS_DEBUG_OSPF_EVENT
)
2396 zlog_info ("Self-originated type-10 Opaque-LSAs: AREA(%s): Flush completed", inet_ntoa (area
->area_id
));
2398 UNSET_FLAG (area
->ospf
->opaque
, OPAQUE_BLOCK_TYPE_10_LSA_BIT
);
2405 ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf
*top
)
2408 struct ospf_interface
*oi
;
2409 unsigned long n
= 0;
2411 for (node
= listhead (top
->oiflist
); node
; nextnode (node
))
2413 if ((oi
= getdata (node
)) == NULL
)
2418 case OSPF_IFTYPE_VIRTUALLINK
:
2424 n
= ospf_opaque_nrxmt_self (oi
->nbrs
, OSPF_OPAQUE_AS_LSA
);
2431 if (IS_DEBUG_OSPF_EVENT
)
2432 zlog_info ("Self-originated type-11 Opaque-LSAs: Flush completed");
2434 UNSET_FLAG (top
->opaque
, OPAQUE_BLOCK_TYPE_11_LSA_BIT
);
2441 static unsigned long
2442 ospf_opaque_nrxmt_self (struct route_table
*nbrs
, int lsa_type
)
2444 struct route_node
*rn
;
2445 struct ospf_neighbor
*nbr
;
2447 unsigned long n
= 0;
2449 for (rn
= route_top (nbrs
); rn
; rn
= route_next (rn
))
2451 if ((nbr
= rn
->info
) == NULL
)
2453 if ((top
= oi_to_top (nbr
->oi
)) == NULL
)
2455 if (IPV4_ADDR_SAME (&nbr
->router_id
, &top
->router_id
))
2457 n
+= ospf_ls_retransmit_count_self (nbr
, lsa_type
);
2463 /*------------------------------------------------------------------------*
2464 * Followings are util functions; probably be used by Opaque-LSAs only...
2465 *------------------------------------------------------------------------*/
2468 htonf (float *src
, float *dst
)
2472 memcpy (&lu1
, src
, sizeof (u_int32_t
));
2474 memcpy (dst
, &lu2
, sizeof (u_int32_t
));
2479 ntohf (float *src
, float *dst
)
2483 memcpy (&lu1
, src
, sizeof (u_int32_t
));
2485 memcpy (dst
, &lu2
, sizeof (u_int32_t
));
2490 oi_to_top (struct ospf_interface
*oi
)
2492 struct ospf
*top
= NULL
;
2493 struct ospf_area
*area
;
2495 if (oi
== NULL
|| (area
= oi
->area
) == NULL
|| (top
= area
->ospf
) == NULL
)
2496 zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");
2501 #endif /* HAVE_OPAQUE_LSA */