blob: 0b6ac4cb7b8f88d782791f420c5a98cb3c48c8a5 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
2 * This is an implementation of rfc2370.
3 * Copyright (C) 2001 KDD R&D Laboratories, Inc.
4 * http://www.kddlabs.co.jp/
5 *
6 * This file is part of GNU Zebra.
7 *
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
11 * later version.
12 *
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.
17 *
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
21 * 02111-1307, USA.
22 */
23
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
28
29#include <zebra.h>
30#ifdef HAVE_OPAQUE_LSA
31
32#include "linklist.h"
33#include "prefix.h"
34#include "if.h"
35#include "table.h"
36#include "memory.h"
37#include "command.h"
38#include "vty.h"
39#include "stream.h"
40#include "log.h"
41#include "thread.h"
42#include "hash.h"
43#include "sockunion.h" /* for inet_aton() */
44
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"
60
61/*------------------------------------------------------------------------*
62 * Followings are initialize/terminate functions for Opaque-LSAs handling.
63 *------------------------------------------------------------------------*/
64
65#ifdef HAVE_OSPF_TE
66#include "ospfd/ospf_te.h"
67#endif /* HAVE_OSPF_TE */
68
paul283ae332003-03-17 01:16:55 +000069#ifdef SUPPORT_OSPF_API
70int ospf_apiserver_init (void);
71void ospf_apiserver_term (void);
hassof4d58ce2004-10-12 06:13:54 +000072/* Init apiserver? It's disabled by default. */
73int ospf_apiserver_enable;
paul283ae332003-03-17 01:16:55 +000074#endif /* SUPPORT_OSPF_API */
75
paul718e3742002-12-13 20:15:29 +000076static void ospf_opaque_register_vty (void);
77static void ospf_opaque_funclist_init (void);
78static void ospf_opaque_funclist_term (void);
79static void free_opaque_info_per_type (void *val);
80static void free_opaque_info_per_id (void *val);
81static int ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa);
82static int ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa);
83
84void
85ospf_opaque_init (void)
86{
87 ospf_opaque_register_vty ();
88 ospf_opaque_funclist_init ();
89
90#ifdef HAVE_OSPF_TE
91 if (ospf_mpls_te_init () != 0)
92 exit (1);
93#endif /* HAVE_OSPF_TE */
94
paul283ae332003-03-17 01:16:55 +000095#ifdef SUPPORT_OSPF_API
hassoc3abdb72004-10-11 16:27:03 +000096 if ((ospf_apiserver_enable) && (ospf_apiserver_init () != 0))
paul283ae332003-03-17 01:16:55 +000097 exit (1);
98#endif /* SUPPORT_OSPF_API */
99
paul718e3742002-12-13 20:15:29 +0000100 return;
101}
102
103void
104ospf_opaque_term (void)
105{
106#ifdef HAVE_OSPF_TE
107 ospf_mpls_te_term ();
108#endif /* HAVE_OSPF_TE */
109
paul283ae332003-03-17 01:16:55 +0000110#ifdef SUPPORT_OSPF_API
111 ospf_apiserver_term ();
112#endif /* SUPPORT_OSPF_API */
113
paul718e3742002-12-13 20:15:29 +0000114 ospf_opaque_funclist_term ();
115 return;
116}
117
118int
119ospf_opaque_type9_lsa_init (struct ospf_interface *oi)
120{
121 if (oi->opaque_lsa_self != NULL)
122 list_delete (oi->opaque_lsa_self);
123
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;
127 return 0;
128}
129
130void
131ospf_opaque_type9_lsa_term (struct ospf_interface *oi)
132{
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;
137 return;
138}
139
140int
141ospf_opaque_type10_lsa_init (struct ospf_area *area)
142{
143 if (area->opaque_lsa_self != NULL)
144 list_delete (area->opaque_lsa_self);
145
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;
149
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 */
154 return 0;
155}
156
157void
158ospf_opaque_type10_lsa_term (struct ospf_area *area)
159{
160#ifdef MONITOR_LSDB_CHANGE
161 area->lsdb->new_lsa_hook =
162 area->lsdb->del_lsa_hook = NULL;
163#endif /* MONITOR_LSDB_CHANGE */
164
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;
169 return;
170}
171
172int
173ospf_opaque_type11_lsa_init (struct ospf *top)
174{
175 if (top->opaque_lsa_self != NULL)
176 list_delete (top->opaque_lsa_self);
177
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;
181
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 */
186 return 0;
187}
188
189void
190ospf_opaque_type11_lsa_term (struct ospf *top)
191{
192#ifdef MONITOR_LSDB_CHANGE
193 top->lsdb->new_lsa_hook =
194 top->lsdb->del_lsa_hook = NULL;
195#endif /* MONITOR_LSDB_CHANGE */
196
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;
201 return;
202}
203
204static const char *
205ospf_opaque_type_name (u_char opaque_type)
206{
207 const char *name = "Unknown";
208
209 switch (opaque_type)
210 {
211 case OPAQUE_TYPE_WILDCARD: /* This is a special assignment! */
212 name = "Wildcard";
213 break;
214 case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA:
215 name = "Traffic Engineering LSA";
216 break;
217 case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC:
218 name = "Sycamore optical topology description";
219 break;
220 case OPAQUE_TYPE_GRACE_LSA:
221 name = "Grace-LSA";
222 break;
223 default:
224 if (OPAQUE_TYPE_RANGE_UNASSIGNED (opaque_type))
225 name = "Unassigned";
gdtf4436f72004-12-09 14:49:51 +0000226 /* XXX warning: comparison is always true due to limited range of data type */
paul718e3742002-12-13 20:15:29 +0000227 else if (OPAQUE_TYPE_RANGE_RESERVED (opaque_type))
228 name = "Private/Experimental";
229 break;
230 }
231 return name;
232}
233
234/*------------------------------------------------------------------------*
235 * Followings are management functions to store user specified callbacks.
236 *------------------------------------------------------------------------*/
237
238struct opaque_info_per_type; /* Forward declaration. */
239
240struct ospf_opaque_functab
241{
242 u_char opaque_type;
243 struct opaque_info_per_type *oipt;
244
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);
257};
258
paul87d6f872004-09-24 08:01:38 +0000259/* Handle LSA-9/10/11 altogether. */
260static struct list *ospf_opaque_wildcard_funclist;
261static struct list *ospf_opaque_type9_funclist;
262static struct list *ospf_opaque_type10_funclist;
263static struct list *ospf_opaque_type11_funclist;
paul718e3742002-12-13 20:15:29 +0000264
265static void
266ospf_opaque_del_functab (void *val)
267{
268 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, val);
269 return;
270}
271
272static void
273ospf_opaque_funclist_init (void)
274{
paul87d6f872004-09-24 08:01:38 +0000275 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000276
paul09e4efd2003-01-18 00:12:02 +0000277 funclist = ospf_opaque_wildcard_funclist = list_new ();
278 funclist->del = ospf_opaque_del_functab;
279
paul718e3742002-12-13 20:15:29 +0000280 funclist = ospf_opaque_type9_funclist = list_new ();
281 funclist->del = ospf_opaque_del_functab;
282
283 funclist = ospf_opaque_type10_funclist = list_new ();
284 funclist->del = ospf_opaque_del_functab;
285
286 funclist = ospf_opaque_type11_funclist = list_new ();
287 funclist->del = ospf_opaque_del_functab;
288 return;
289}
290
291static void
292ospf_opaque_funclist_term (void)
293{
paul87d6f872004-09-24 08:01:38 +0000294 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000295
paul09e4efd2003-01-18 00:12:02 +0000296 funclist = ospf_opaque_wildcard_funclist;
297 list_delete (funclist);
298
paul718e3742002-12-13 20:15:29 +0000299 funclist = ospf_opaque_type9_funclist;
300 list_delete (funclist);
301
302 funclist = ospf_opaque_type10_funclist;
303 list_delete (funclist);
304
305 funclist = ospf_opaque_type11_funclist;
306 list_delete (funclist);
307 return;
308}
309
paul87d6f872004-09-24 08:01:38 +0000310static struct list *
paul718e3742002-12-13 20:15:29 +0000311ospf_get_opaque_funclist (u_char lsa_type)
312{
paul87d6f872004-09-24 08:01:38 +0000313 struct list *funclist = NULL;
paul718e3742002-12-13 20:15:29 +0000314
315 switch (lsa_type)
316 {
paul09e4efd2003-01-18 00:12:02 +0000317 case OPAQUE_TYPE_WILDCARD:
318 /* XXX
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.
324 */
325 funclist = ospf_opaque_wildcard_funclist;
326 break;
paul718e3742002-12-13 20:15:29 +0000327 case OSPF_OPAQUE_LINK_LSA:
328 funclist = ospf_opaque_type9_funclist;
329 break;
330 case OSPF_OPAQUE_AREA_LSA:
331 funclist = ospf_opaque_type10_funclist;
332 break;
333 case OSPF_OPAQUE_AS_LSA:
334 funclist = ospf_opaque_type11_funclist;
335 break;
336 default:
337 zlog_warn ("ospf_get_opaque_funclist: Unexpected LSA-type(%u)", lsa_type);
338 break;
339 }
340 return funclist;
341}
342
paul87d6f872004-09-24 08:01:38 +0000343/* XXX: such a huge argument list can /not/ be healthy... */
paul718e3742002-12-13 20:15:29 +0000344int
345ospf_register_opaque_functab (
346 u_char lsa_type,
347 u_char opaque_type,
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))
360{
paul87d6f872004-09-24 08:01:38 +0000361 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000362 struct ospf_opaque_functab *new;
363 int rc = -1;
364
365 if ((funclist = ospf_get_opaque_funclist (lsa_type)) == NULL)
366 {
paul87d6f872004-09-24 08:01:38 +0000367 zlog_warn ("ospf_register_opaque_functab: Cannot get funclist"
368 " for Type-%u LSAs?",
369 lsa_type);
paul718e3742002-12-13 20:15:29 +0000370 goto out;
371 }
372 else
373 {
paul1eb8ef22005-04-07 07:30:20 +0000374 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000375 struct ospf_opaque_functab *functab;
paul87d6f872004-09-24 08:01:38 +0000376
paul1eb8ef22005-04-07 07:30:20 +0000377 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000378 if (functab->opaque_type == opaque_type)
379 {
380 zlog_warn ("ospf_register_opaque_functab: Duplicated entry?:"
381 " lsa_type(%u), opaque_type(%u)",
382 lsa_type, opaque_type);
383 goto out;
384 }
paul718e3742002-12-13 20:15:29 +0000385 }
386
387 if ((new = XCALLOC (MTYPE_OSPF_OPAQUE_FUNCTAB,
388 sizeof (struct ospf_opaque_functab))) == NULL)
389 {
paul87d6f872004-09-24 08:01:38 +0000390 zlog_warn ("ospf_register_opaque_functab: XMALLOC: %s",
ajs6099b3b2004-11-20 02:06:59 +0000391 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000392 goto out;
393 }
394
395 new->opaque_type = opaque_type;
396 new->oipt = NULL;
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;
409
410 listnode_add (funclist, new);
411 rc = 0;
412
413out:
414 return rc;
415}
416
417void
418ospf_delete_opaque_functab (u_char lsa_type, u_char opaque_type)
419{
paul87d6f872004-09-24 08:01:38 +0000420 struct list *funclist;
paul1eb8ef22005-04-07 07:30:20 +0000421 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000422 struct ospf_opaque_functab *functab;
423
424 if ((funclist = ospf_get_opaque_funclist (lsa_type)) != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000425 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul718e3742002-12-13 20:15:29 +0000426 {
paul1eb8ef22005-04-07 07:30:20 +0000427 if (functab->opaque_type == opaque_type)
paul718e3742002-12-13 20:15:29 +0000428 {
429 /* Cleanup internal control information, if it still remains. */
430 if (functab->oipt != NULL)
431 free_opaque_info_per_type (functab->oipt);
432
433 /* Dequeue listnode entry from the list. */
434 listnode_delete (funclist, functab);
435
436 /* Avoid misjudgement in the next lookup. */
437 if (listcount (funclist) == 0)
438 funclist->head = funclist->tail = NULL;
439
440 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, functab);
paul87d6f872004-09-24 08:01:38 +0000441 break;
paul718e3742002-12-13 20:15:29 +0000442 }
443 }
paul87d6f872004-09-24 08:01:38 +0000444
paul718e3742002-12-13 20:15:29 +0000445 return;
446}
447
448static struct ospf_opaque_functab *
449ospf_opaque_functab_lookup (struct ospf_lsa *lsa)
450{
paul87d6f872004-09-24 08:01:38 +0000451 struct list *funclist;
452 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000453 struct ospf_opaque_functab *functab;
454 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
455
456 if ((funclist = ospf_get_opaque_funclist (lsa->data->type)) != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000457 for (ALL_LIST_ELEMENTS_RO (funclist, node, functab))
paul87d6f872004-09-24 08:01:38 +0000458 if (functab->opaque_type == key)
459 return functab;
paul718e3742002-12-13 20:15:29 +0000460
461 return NULL;
462}
463
464/*------------------------------------------------------------------------*
465 * Followings are management functions for self-originated LSA entries.
466 *------------------------------------------------------------------------*/
467
468/*
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.
472 */
473struct opaque_info_per_type
474{
paul09e4efd2003-01-18 00:12:02 +0000475 u_char lsa_type;
paul718e3742002-12-13 20:15:29 +0000476 u_char opaque_type;
477
478 enum { PROC_NORMAL, PROC_SUSPEND } status;
479
480 /*
481 * Thread for (re-)origination scheduling for this opaque-type.
482 *
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.
489 */
490 struct thread *t_opaque_lsa_self;
491
492 /*
paul09e4efd2003-01-18 00:12:02 +0000493 * Backpointer to an "owner" which is LSA-type dependent.
paul718e3742002-12-13 20:15:29 +0000494 * type-9: struct ospf_interface
495 * type-10: struct ospf_area
496 * type-11: struct ospf
497 */
498 void *owner;
499
500 /* Collection of callback functions for this opaque-type. */
501 struct ospf_opaque_functab *functab;
502
503 /* List of Opaque-LSA control informations per opaque-id. */
paul87d6f872004-09-24 08:01:38 +0000504 struct list *id_list;
paul718e3742002-12-13 20:15:29 +0000505};
506
507/* Opaque-LSA control information per opaque-id. */
508struct opaque_info_per_id
509{
510 u_int32_t opaque_id;
511
512 /* Thread for refresh/flush scheduling for this opaque-type/id. */
513 struct thread *t_opaque_lsa_self;
514
515 /* Backpointer to Opaque-LSA control information per opaque-type. */
516 struct opaque_info_per_type *opqctl_type;
517
518 /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
519 struct ospf_lsa *lsa;
520};
521
522static struct opaque_info_per_type *register_opaque_info_per_type (struct ospf_opaque_functab *functab, struct ospf_lsa *new);
523static struct opaque_info_per_type *lookup_opaque_info_by_type (struct ospf_lsa *lsa);
524static struct opaque_info_per_id *register_opaque_info_per_id (struct opaque_info_per_type *oipt, struct ospf_lsa *new);
525static struct opaque_info_per_id *lookup_opaque_info_by_id (struct opaque_info_per_type *oipt, struct ospf_lsa *lsa);
526static struct opaque_info_per_id *register_opaque_lsa (struct ospf_lsa *new);
527
528
529static struct opaque_info_per_type *
530register_opaque_info_per_type (struct ospf_opaque_functab *functab,
531 struct ospf_lsa *new)
532{
533 struct ospf *top;
534 struct opaque_info_per_type *oipt;
535
536 if ((oipt = XCALLOC (MTYPE_OPAQUE_INFO_PER_TYPE,
537 sizeof (struct opaque_info_per_type))) == NULL)
538 {
ajs6099b3b2004-11-20 02:06:59 +0000539 zlog_warn ("register_opaque_info_per_type: XMALLOC: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000540 goto out;
541 }
542
543 switch (new->data->type)
544 {
545 case OSPF_OPAQUE_LINK_LSA:
546 oipt->owner = new->oi;
547 listnode_add (new->oi->opaque_lsa_self, oipt);
548 break;
549 case OSPF_OPAQUE_AREA_LSA:
550 oipt->owner = new->area;
551 listnode_add (new->area->opaque_lsa_self, oipt);
552 break;
553 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +0000554 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000555 if (new->area != NULL && (top = new->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +0000556 {
557 free_opaque_info_per_type ((void *) oipt);
558 oipt = NULL;
559 goto out; /* This case may not exist. */
560 }
561 oipt->owner = top;
562 listnode_add (top->opaque_lsa_self, oipt);
563 break;
564 default:
paul09e4efd2003-01-18 00:12:02 +0000565 zlog_warn ("register_opaque_info_per_type: Unexpected LSA-type(%u)", new->data->type);
paul718e3742002-12-13 20:15:29 +0000566 free_opaque_info_per_type ((void *) oipt);
567 oipt = NULL;
568 goto out; /* This case may not exist. */
569 }
570
paul09e4efd2003-01-18 00:12:02 +0000571 oipt->lsa_type = new->data->type;
paul718e3742002-12-13 20:15:29 +0000572 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;
579
580out:
581 return oipt;
582}
583
584static void
585free_opaque_info_per_type (void *val)
586{
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;
paul1eb8ef22005-04-07 07:30:20 +0000590 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000591
592 /* Control information per opaque-id may still exist. */
paul1eb8ef22005-04-07 07:30:20 +0000593 for (ALL_LIST_ELEMENTS (oipt->id_list, node, nnode, oipi))
paul718e3742002-12-13 20:15:29 +0000594 {
paul718e3742002-12-13 20:15:29 +0000595 if ((lsa = oipi->lsa) == NULL)
596 continue;
597 if (IS_LSA_MAXAGE (lsa))
598 continue;
599 ospf_opaque_lsa_flush_schedule (lsa);
600 }
601
paul09e4efd2003-01-18 00:12:02 +0000602 /* Remove "oipt" from its owner's self-originated LSA list. */
603 switch (oipt->lsa_type)
604 {
605 case OSPF_OPAQUE_LINK_LSA:
606 {
607 struct ospf_interface *oi = (struct ospf_interface *)(oipt->owner);
608 listnode_delete (oi->opaque_lsa_self, oipt);
609 break;
610 }
611 case OSPF_OPAQUE_AREA_LSA:
612 {
613 struct ospf_area *area = (struct ospf_area *)(oipt->owner);
614 listnode_delete (area->opaque_lsa_self, oipt);
615 break;
616 }
617 case OSPF_OPAQUE_AS_LSA:
618 {
619 struct ospf *top = (struct ospf *)(oipt->owner);
620 listnode_delete (top->opaque_lsa_self, oipt);
621 break;
622 }
623 default:
624 zlog_warn ("free_opaque_info_per_type: Unexpected LSA-type(%u)", oipt->lsa_type);
625 break; /* This case may not exist. */
626 }
627
paul718e3742002-12-13 20:15:29 +0000628 OSPF_TIMER_OFF (oipt->t_opaque_lsa_self);
629 list_delete (oipt->id_list);
630 XFREE (MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
631 return;
632}
633
634static struct opaque_info_per_type *
635lookup_opaque_info_by_type (struct ospf_lsa *lsa)
636{
637 struct ospf *top;
638 struct ospf_area *area;
639 struct ospf_interface *oi;
paul87d6f872004-09-24 08:01:38 +0000640 struct list *listtop = NULL;
paul1eb8ef22005-04-07 07:30:20 +0000641 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000642 struct opaque_info_per_type *oipt = NULL;
643 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
644
645 switch (lsa->data->type)
646 {
647 case OSPF_OPAQUE_LINK_LSA:
648 if ((oi = lsa->oi) != NULL)
649 listtop = oi->opaque_lsa_self;
650 else
651 zlog_warn ("Type-9 Opaque-LSA: Reference to OI is missing?");
652 break;
653 case OSPF_OPAQUE_AREA_LSA:
654 if ((area = lsa->area) != NULL)
655 listtop = area->opaque_lsa_self;
656 else
657 zlog_warn ("Type-10 Opaque-LSA: Reference to AREA is missing?");
658 break;
659 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +0000660 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000661 if ((area = lsa->area) != NULL && (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +0000662 {
663 zlog_warn ("Type-11 Opaque-LSA: Reference to OSPF is missing?");
664 break; /* Unlikely to happen. */
665 }
666 listtop = top->opaque_lsa_self;
667 break;
668 default:
669 zlog_warn ("lookup_opaque_info_by_type: Unexpected LSA-type(%u)", lsa->data->type);
670 break;
671 }
672
673 if (listtop != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000674 for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt))
paul87d6f872004-09-24 08:01:38 +0000675 if (oipt->opaque_type == key)
676 return oipt;
paul718e3742002-12-13 20:15:29 +0000677
678 return NULL;
679}
680
681static struct opaque_info_per_id *
682register_opaque_info_per_id (struct opaque_info_per_type *oipt,
683 struct ospf_lsa *new)
684{
685 struct opaque_info_per_id *oipi;
686
687 if ((oipi = XCALLOC (MTYPE_OPAQUE_INFO_PER_ID,
688 sizeof (struct opaque_info_per_id))) == NULL)
689 {
ajs6099b3b2004-11-20 02:06:59 +0000690 zlog_warn ("register_opaque_info_per_id: XMALLOC: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000691 goto out;
692 }
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);
697
698 listnode_add (oipt->id_list, oipi);
699
700out:
701 return oipi;
702}
703
704static void
705free_opaque_info_per_id (void *val)
706{
707 struct opaque_info_per_id *oipi = (struct opaque_info_per_id *) val;
708
709 OSPF_TIMER_OFF (oipi->t_opaque_lsa_self);
710 if (oipi->lsa != NULL)
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000711 ospf_lsa_unlock (&oipi->lsa);
paul718e3742002-12-13 20:15:29 +0000712 XFREE (MTYPE_OPAQUE_INFO_PER_ID, oipi);
713 return;
714}
715
716static struct opaque_info_per_id *
717lookup_opaque_info_by_id (struct opaque_info_per_type *oipt,
718 struct ospf_lsa *lsa)
719{
paul1eb8ef22005-04-07 07:30:20 +0000720 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000721 struct opaque_info_per_id *oipi;
722 u_int32_t key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
723
paul1eb8ef22005-04-07 07:30:20 +0000724 for (ALL_LIST_ELEMENTS (oipt->id_list, node, nnode, oipi))
paul87d6f872004-09-24 08:01:38 +0000725 if (oipi->opaque_id == key)
726 return oipi;
paul718e3742002-12-13 20:15:29 +0000727
728 return NULL;
729}
730
731static struct opaque_info_per_id *
732register_opaque_lsa (struct ospf_lsa *new)
733{
734 struct ospf_opaque_functab *functab;
735 struct opaque_info_per_type *oipt;
736 struct opaque_info_per_id *oipi = NULL;
737
738 if ((functab = ospf_opaque_functab_lookup (new)) == NULL)
739 goto out;
740
741 if ((oipt = lookup_opaque_info_by_type (new)) == NULL
742 && (oipt = register_opaque_info_per_type (functab, new)) == NULL)
743 goto out;
744
745 if ((oipi = register_opaque_info_per_id (oipt, new)) == NULL)
746 goto out;
747
748out:
749 return oipi;
750}
751
752/*------------------------------------------------------------------------*
753 * Followings are (vty) configuration functions for Opaque-LSAs handling.
754 *------------------------------------------------------------------------*/
755
756DEFUN (capability_opaque,
757 capability_opaque_cmd,
758 "capability opaque",
759 "Enable specific OSPF feature\n"
760 "Opaque LSA\n")
761{
762 struct ospf *ospf = (struct ospf *) vty->index;
763
764 /* Turn on the "master switch" of opaque-lsa capability. */
765 if (!CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
766 {
767 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000768 zlog_debug ("Opaque capability: OFF -> ON");
paul718e3742002-12-13 20:15:29 +0000769
770 SET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
771 ospf_renegotiate_optional_capabilities (ospf);
772 }
773 return CMD_SUCCESS;
774}
775
776ALIAS (capability_opaque,
777 ospf_opaque_capable_cmd,
778 "ospf opaque-lsa",
779 "OSPF specific commands\n"
780 "Enable the Opaque-LSA capability (rfc2370)\n")
781
782DEFUN (no_capability_opaque,
783 no_capability_opaque_cmd,
784 "no capability opaque",
785 NO_STR
786 "Enable specific OSPF feature\n"
787 "Opaque LSA\n")
788{
789 struct ospf *ospf = (struct ospf *) vty->index;
790
791 /* Turn off the "master switch" of opaque-lsa capability. */
792 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
793 {
794 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000795 zlog_debug ("Opaque capability: ON -> OFF");
paul718e3742002-12-13 20:15:29 +0000796
797 UNSET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
798 ospf_renegotiate_optional_capabilities (ospf);
799 }
800 return CMD_SUCCESS;
801}
802
803ALIAS (no_capability_opaque,
804 no_ospf_opaque_capable_cmd,
805 "no ospf opaque-lsa",
806 NO_STR
807 "OSPF specific commands\n"
808 "Disable the Opaque-LSA capability (rfc2370)\n")
809
810static void
811ospf_opaque_register_vty (void)
812{
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);
817 return;
818}
819
820/*------------------------------------------------------------------------*
821 * Followings are collection of user-registered function callers.
822 *------------------------------------------------------------------------*/
823
824static int
paul87d6f872004-09-24 08:01:38 +0000825opaque_lsa_new_if_callback (struct list *funclist, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000826{
paul1eb8ef22005-04-07 07:30:20 +0000827 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000828 struct ospf_opaque_functab *functab;
829 int rc = -1;
830
paul1eb8ef22005-04-07 07:30:20 +0000831 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000832 if (functab->new_if_hook != NULL)
833 if ((* functab->new_if_hook)(ifp) != 0)
834 goto out;
paul718e3742002-12-13 20:15:29 +0000835 rc = 0;
836out:
837 return rc;
838}
839
840static int
paul87d6f872004-09-24 08:01:38 +0000841opaque_lsa_del_if_callback (struct list *funclist, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000842{
paul1eb8ef22005-04-07 07:30:20 +0000843 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000844 struct ospf_opaque_functab *functab;
845 int rc = -1;
846
paul1eb8ef22005-04-07 07:30:20 +0000847 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000848 if (functab->del_if_hook != NULL)
849 if ((* functab->del_if_hook)(ifp) != 0)
850 goto out;
paul718e3742002-12-13 20:15:29 +0000851 rc = 0;
852out:
853 return rc;
854}
855
856static void
paul87d6f872004-09-24 08:01:38 +0000857opaque_lsa_ism_change_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000858 struct ospf_interface *oi, int old_status)
859{
paul1eb8ef22005-04-07 07:30:20 +0000860 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000861 struct ospf_opaque_functab *functab;
862
paul1eb8ef22005-04-07 07:30:20 +0000863 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000864 if (functab->ism_change_hook != NULL)
865 (* functab->ism_change_hook)(oi, old_status);
866
paul718e3742002-12-13 20:15:29 +0000867 return;
868}
869
870static void
paul87d6f872004-09-24 08:01:38 +0000871opaque_lsa_nsm_change_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000872 struct ospf_neighbor *nbr, int old_status)
873{
paul1eb8ef22005-04-07 07:30:20 +0000874 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000875 struct ospf_opaque_functab *functab;
876
paul1eb8ef22005-04-07 07:30:20 +0000877 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000878 if (functab->nsm_change_hook != NULL)
879 (* functab->nsm_change_hook)(nbr, old_status);
paul718e3742002-12-13 20:15:29 +0000880 return;
881}
882
883static void
paul87d6f872004-09-24 08:01:38 +0000884opaque_lsa_config_write_router_callback (struct list *funclist,
885 struct vty *vty)
paul718e3742002-12-13 20:15:29 +0000886{
paul1eb8ef22005-04-07 07:30:20 +0000887 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000888 struct ospf_opaque_functab *functab;
889
paul1eb8ef22005-04-07 07:30:20 +0000890 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000891 if (functab->config_write_router != NULL)
892 (* functab->config_write_router)(vty);
paul718e3742002-12-13 20:15:29 +0000893 return;
894}
895
896static void
paul87d6f872004-09-24 08:01:38 +0000897opaque_lsa_config_write_if_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000898 struct vty *vty, struct interface *ifp)
899{
paul1eb8ef22005-04-07 07:30:20 +0000900 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000901 struct ospf_opaque_functab *functab;
902
paul1eb8ef22005-04-07 07:30:20 +0000903 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000904 if (functab->config_write_if != NULL)
905 (* functab->config_write_if)(vty, ifp);
paul718e3742002-12-13 20:15:29 +0000906 return;
907}
908
909static void
paul87d6f872004-09-24 08:01:38 +0000910opaque_lsa_config_write_debug_callback (struct list *funclist, struct vty *vty)
paul718e3742002-12-13 20:15:29 +0000911{
paul1eb8ef22005-04-07 07:30:20 +0000912 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000913 struct ospf_opaque_functab *functab;
914
paul1eb8ef22005-04-07 07:30:20 +0000915 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000916 if (functab->config_write_debug != NULL)
917 (* functab->config_write_debug)(vty);
paul718e3742002-12-13 20:15:29 +0000918 return;
919}
920
921static int
paul87d6f872004-09-24 08:01:38 +0000922opaque_lsa_originate_callback (struct list *funclist, void *lsa_type_dependent)
paul718e3742002-12-13 20:15:29 +0000923{
paul1eb8ef22005-04-07 07:30:20 +0000924 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000925 struct ospf_opaque_functab *functab;
926 int rc = -1;
927
paul1eb8ef22005-04-07 07:30:20 +0000928 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000929 if (functab->lsa_originator != NULL)
930 if ((* functab->lsa_originator)(lsa_type_dependent) != 0)
931 goto out;
paul718e3742002-12-13 20:15:29 +0000932 rc = 0;
933out:
934 return rc;
935}
936
937static int
paul87d6f872004-09-24 08:01:38 +0000938new_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000939{
paul1eb8ef22005-04-07 07:30:20 +0000940 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000941 struct ospf_opaque_functab *functab;
942 int rc = -1;
943
944 /* This function handles ALL types of LSAs, not only opaque ones. */
paul1eb8ef22005-04-07 07:30:20 +0000945 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000946 if (functab->new_lsa_hook != NULL)
947 if ((* functab->new_lsa_hook)(lsa) != 0)
948 goto out;
paul718e3742002-12-13 20:15:29 +0000949 rc = 0;
950out:
951 return rc;
952}
953
954static int
paul87d6f872004-09-24 08:01:38 +0000955del_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000956{
paul1eb8ef22005-04-07 07:30:20 +0000957 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000958 struct ospf_opaque_functab *functab;
959 int rc = -1;
960
961 /* This function handles ALL types of LSAs, not only opaque ones. */
paul1eb8ef22005-04-07 07:30:20 +0000962 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000963 if (functab->del_lsa_hook != NULL)
964 if ((* functab->del_lsa_hook)(lsa) != 0)
965 goto out;
paul718e3742002-12-13 20:15:29 +0000966 rc = 0;
967out:
968 return rc;
969}
970
971/*------------------------------------------------------------------------*
972 * Followings are glue functions to call Opaque-LSA specific processing.
973 *------------------------------------------------------------------------*/
974
975int
976ospf_opaque_new_if (struct interface *ifp)
977{
paul87d6f872004-09-24 08:01:38 +0000978 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000979 int rc = -1;
980
paul09e4efd2003-01-18 00:12:02 +0000981 funclist = ospf_opaque_wildcard_funclist;
982 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
983 goto out;
984
paul718e3742002-12-13 20:15:29 +0000985 funclist = ospf_opaque_type9_funclist;
986 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
987 goto out;
988
989 funclist = ospf_opaque_type10_funclist;
990 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
991 goto out;
992
993 funclist = ospf_opaque_type11_funclist;
994 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
995 goto out;
996
997 rc = 0;
998out:
999 return rc;
1000}
1001
1002int
1003ospf_opaque_del_if (struct interface *ifp)
1004{
paul87d6f872004-09-24 08:01:38 +00001005 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001006 int rc = -1;
1007
paul09e4efd2003-01-18 00:12:02 +00001008 funclist = ospf_opaque_wildcard_funclist;
1009 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1010 goto out;
1011
paul718e3742002-12-13 20:15:29 +00001012 funclist = ospf_opaque_type9_funclist;
1013 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1014 goto out;
1015
1016 funclist = ospf_opaque_type10_funclist;
1017 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1018 goto out;
1019
1020 funclist = ospf_opaque_type11_funclist;
1021 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1022 goto out;
1023
1024 rc = 0;
1025out:
1026 return rc;
1027}
1028
1029void
1030ospf_opaque_ism_change (struct ospf_interface *oi, int old_status)
1031{
paul87d6f872004-09-24 08:01:38 +00001032 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001033
paul09e4efd2003-01-18 00:12:02 +00001034 funclist = ospf_opaque_wildcard_funclist;
1035 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1036
paul718e3742002-12-13 20:15:29 +00001037 funclist = ospf_opaque_type9_funclist;
1038 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1039
1040 funclist = ospf_opaque_type10_funclist;
1041 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1042
1043 funclist = ospf_opaque_type11_funclist;
1044 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1045
1046 return;
1047}
1048
1049void
1050ospf_opaque_nsm_change (struct ospf_neighbor *nbr, int old_state)
1051{
1052 struct ospf *top;
paul87d6f872004-09-24 08:01:38 +00001053 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001054
1055 if ((top = oi_to_top (nbr->oi)) == NULL)
1056 goto out;
1057
1058 if (old_state != NSM_Full && nbr->state == NSM_Full)
1059 {
1060 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
1061 {
1062 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1063 {
1064 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001065 zlog_debug ("Opaque-LSA: Now get operational!");
paul718e3742002-12-13 20:15:29 +00001066
1067 SET_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT);
1068 }
1069
1070 ospf_opaque_lsa_originate_schedule (nbr->oi, NULL);
1071 }
1072 }
1073 else
1074 if (old_state == NSM_Full && nbr->state != NSM_Full)
1075 {
1076#ifdef NOTYET
1077 /*
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.
1081 */
1082#endif /* NOTYET */
1083 ;
1084 }
1085
paul09e4efd2003-01-18 00:12:02 +00001086 funclist = ospf_opaque_wildcard_funclist;
1087 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1088
paul718e3742002-12-13 20:15:29 +00001089 funclist = ospf_opaque_type9_funclist;
1090 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1091
1092 funclist = ospf_opaque_type10_funclist;
1093 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1094
1095 funclist = ospf_opaque_type11_funclist;
1096 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1097
1098out:
1099 return;
1100}
1101
1102void
1103ospf_opaque_config_write_router (struct vty *vty, struct ospf *ospf)
1104{
paul87d6f872004-09-24 08:01:38 +00001105 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001106
1107 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
1108 vty_out (vty, " capability opaque%s", VTY_NEWLINE);
1109
paul09e4efd2003-01-18 00:12:02 +00001110 funclist = ospf_opaque_wildcard_funclist;
1111 opaque_lsa_config_write_router_callback (funclist, vty);
1112
paul718e3742002-12-13 20:15:29 +00001113 funclist = ospf_opaque_type9_funclist;
1114 opaque_lsa_config_write_router_callback (funclist, vty);
1115
1116 funclist = ospf_opaque_type10_funclist;
1117 opaque_lsa_config_write_router_callback (funclist, vty);
1118
1119 funclist = ospf_opaque_type11_funclist;
1120 opaque_lsa_config_write_router_callback (funclist, vty);
1121
1122 return;
1123}
1124
1125void
1126ospf_opaque_config_write_if (struct vty *vty, struct interface *ifp)
1127{
paul87d6f872004-09-24 08:01:38 +00001128 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001129
paul09e4efd2003-01-18 00:12:02 +00001130 funclist = ospf_opaque_wildcard_funclist;
1131 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1132
paul718e3742002-12-13 20:15:29 +00001133 funclist = ospf_opaque_type9_funclist;
1134 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1135
1136 funclist = ospf_opaque_type10_funclist;
1137 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1138
1139 funclist = ospf_opaque_type11_funclist;
1140 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1141
1142 return;
1143}
1144
1145void
1146ospf_opaque_config_write_debug (struct vty *vty)
1147{
paul87d6f872004-09-24 08:01:38 +00001148 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001149
paul09e4efd2003-01-18 00:12:02 +00001150 funclist = ospf_opaque_wildcard_funclist;
1151 opaque_lsa_config_write_debug_callback (funclist, vty);
1152
paul718e3742002-12-13 20:15:29 +00001153 funclist = ospf_opaque_type9_funclist;
1154 opaque_lsa_config_write_debug_callback (funclist, vty);
1155
1156 funclist = ospf_opaque_type10_funclist;
1157 opaque_lsa_config_write_debug_callback (funclist, vty);
1158
1159 funclist = ospf_opaque_type11_funclist;
1160 opaque_lsa_config_write_debug_callback (funclist, vty);
1161
1162 return;
1163}
1164
1165void
1166show_opaque_info_detail (struct vty *vty, struct ospf_lsa *lsa)
1167{
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;
1173
1174 /* Switch output functionality by vty address. */
1175 if (vty != NULL)
1176 {
paul020709f2003-04-04 02:44:16 +00001177 vty_out (vty, " Opaque-Type %u (%s)%s", opaque_type,
1178 ospf_opaque_type_name (opaque_type), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001179 vty_out (vty, " Opaque-ID 0x%x%s", opaque_id, VTY_NEWLINE);
1180
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?)",
1184 VTY_NEWLINE);
1185 }
1186 else
1187 {
ajs2a42e282004-12-08 18:43:03 +00001188 zlog_debug (" Opaque-Type %u (%s)", opaque_type,
paul020709f2003-04-04 02:44:16 +00001189 ospf_opaque_type_name (opaque_type));
ajs2a42e282004-12-08 18:43:03 +00001190 zlog_debug (" Opaque-ID 0x%x", opaque_id);
paul718e3742002-12-13 20:15:29 +00001191
ajs2a42e282004-12-08 18:43:03 +00001192 zlog_debug (" Opaque-Info: %u octets of data%s",
paul718e3742002-12-13 20:15:29 +00001193 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1194 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)");
1195 }
1196
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);
1201
1202 return;
1203}
1204
1205void
1206ospf_opaque_lsa_dump (struct stream *s, u_int16_t length)
1207{
1208 struct ospf_lsa lsa;
1209
1210 lsa.data = (struct lsa_header *) STREAM_PNT (s);
1211 show_opaque_info_detail (NULL, &lsa);
1212 return;
1213}
1214
1215static int
1216ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa)
1217{
paul87d6f872004-09-24 08:01:38 +00001218 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001219 int rc = -1;
1220
1221 /*
1222 * Some Opaque-LSA user may want to monitor every LSA installation
1223 * into the LSDB, regardless with target LSA type.
1224 */
paul09e4efd2003-01-18 00:12:02 +00001225 funclist = ospf_opaque_wildcard_funclist;
1226 if (new_lsa_callback (funclist, lsa) != 0)
1227 goto out;
1228
paul718e3742002-12-13 20:15:29 +00001229 funclist = ospf_opaque_type9_funclist;
1230 if (new_lsa_callback (funclist, lsa) != 0)
1231 goto out;
1232
1233 funclist = ospf_opaque_type10_funclist;
1234 if (new_lsa_callback (funclist, lsa) != 0)
1235 goto out;
1236
1237 funclist = ospf_opaque_type11_funclist;
1238 if (new_lsa_callback (funclist, lsa) != 0)
1239 goto out;
1240
1241 rc = 0;
1242out:
1243 return rc;
1244}
1245
1246static int
1247ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa)
1248{
paul87d6f872004-09-24 08:01:38 +00001249 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001250 int rc = -1;
1251
1252 /*
1253 * Some Opaque-LSA user may want to monitor every LSA deletion
1254 * from the LSDB, regardless with target LSA type.
1255 */
paul09e4efd2003-01-18 00:12:02 +00001256 funclist = ospf_opaque_wildcard_funclist;
1257 if (del_lsa_callback (funclist, lsa) != 0)
1258 goto out;
1259
paul718e3742002-12-13 20:15:29 +00001260 funclist = ospf_opaque_type9_funclist;
1261 if (del_lsa_callback (funclist, lsa) != 0)
1262 goto out;
1263
1264 funclist = ospf_opaque_type10_funclist;
1265 if (del_lsa_callback (funclist, lsa) != 0)
1266 goto out;
1267
1268 funclist = ospf_opaque_type11_funclist;
1269 if (del_lsa_callback (funclist, lsa) != 0)
1270 goto out;
1271
1272 rc = 0;
1273out:
1274 return rc;
1275}
1276
1277/*------------------------------------------------------------------------*
1278 * Followings are Opaque-LSA origination/refresh management functions.
1279 *------------------------------------------------------------------------*/
1280
1281static int ospf_opaque_type9_lsa_originate (struct thread *t);
1282static int ospf_opaque_type10_lsa_originate (struct thread *t);
1283static int ospf_opaque_type11_lsa_originate (struct thread *t);
paul87d6f872004-09-24 08:01:38 +00001284static void ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg);
paul718e3742002-12-13 20:15:29 +00001285
1286void
1287ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0)
1288{
1289 struct ospf *top;
1290 struct ospf_area *area;
paul1eb8ef22005-04-07 07:30:20 +00001291 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001292 struct opaque_info_per_type *oipt;
1293 int delay = 0;
1294
1295 if ((top = oi_to_top (oi)) == NULL || (area = oi->area) == NULL)
1296 {
1297 zlog_warn ("ospf_opaque_lsa_originate_schedule: Invalid argument?");
1298 goto out;
1299 }
1300
1301 /* It may not a right time to schedule origination now. */
1302 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1303 {
1304 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001305 zlog_debug ("ospf_opaque_lsa_originate_schedule: Not operational.");
paul718e3742002-12-13 20:15:29 +00001306 goto out; /* This is not an error. */
1307 }
1308 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
1309 {
1310 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001311 zlog_debug ("ospf_opaque_lsa_originate_schedule: Under blockade.");
paul718e3742002-12-13 20:15:29 +00001312 goto out; /* This is not an error, too. */
1313 }
1314
1315 if (delay0 != NULL)
1316 delay = *delay0;
1317
1318 /*
1319 * There might be some entries that have been waiting for triggering
1320 * of per opaque-type re-origination get resumed.
1321 */
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);
1325
1326 /*
1327 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1328 */
1329 if (! list_isempty (ospf_opaque_type9_funclist)
1330 && list_isempty (oi->opaque_lsa_self)
1331 && oi->t_opaque_lsa_self == NULL)
1332 {
1333 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001334 zlog_debug ("Schedule Type-9 Opaque-LSA origination in %d sec later.", delay);
paul718e3742002-12-13 20:15:29 +00001335 oi->t_opaque_lsa_self =
1336 thread_add_timer (master, ospf_opaque_type9_lsa_originate, oi, delay);
1337 delay += OSPF_MIN_LS_INTERVAL;
1338 }
1339
1340 if (! list_isempty (ospf_opaque_type10_funclist)
1341 && list_isempty (area->opaque_lsa_self)
1342 && area->t_opaque_lsa_self == NULL)
1343 {
1344 /*
1345 * One AREA may contain multiple OIs, but above 2nd and 3rd
1346 * conditions prevent from scheduling the originate function
1347 * again and again.
1348 */
1349 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001350 zlog_debug ("Schedule Type-10 Opaque-LSA origination in %d sec later.", delay);
paul718e3742002-12-13 20:15:29 +00001351 area->t_opaque_lsa_self =
1352 thread_add_timer (master, ospf_opaque_type10_lsa_originate,
1353 area, delay);
1354 delay += OSPF_MIN_LS_INTERVAL;
1355 }
1356
1357 if (! list_isempty (ospf_opaque_type11_funclist)
1358 && list_isempty (top->opaque_lsa_self)
1359 && top->t_opaque_lsa_self == NULL)
1360 {
1361 /*
1362 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1363 * conditions prevent from scheduling the originate function
1364 * again and again.
1365 */
1366 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001367 zlog_debug ("Schedule Type-11 Opaque-LSA origination in %d sec later.", delay);
paul718e3742002-12-13 20:15:29 +00001368 top->t_opaque_lsa_self =
1369 thread_add_timer (master, ospf_opaque_type11_lsa_originate,
1370 top, delay);
1371 delay += OSPF_MIN_LS_INTERVAL;
1372 }
1373
1374 /*
1375 * Following section treats a special situation that this node's
1376 * opaque capability has changed as "ON -> OFF -> ON".
1377 */
1378 if (! list_isempty (ospf_opaque_type9_funclist)
1379 && ! list_isempty (oi->opaque_lsa_self))
1380 {
paul1eb8ef22005-04-07 07:30:20 +00001381 for (ALL_LIST_ELEMENTS (oi->opaque_lsa_self, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001382 {
hasso0d85b992004-03-18 19:18:33 +00001383 /*
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)
1387 * not being empty.
1388 */
paul1eb8ef22005-04-07 07:30:20 +00001389 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1390 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001391 continue;
1392
1393 ospf_opaque_lsa_reoriginate_schedule ((void *) oi,
1394 OSPF_OPAQUE_LINK_LSA, oipt->opaque_type);
1395 }
1396 }
1397
1398 if (! list_isempty (ospf_opaque_type10_funclist)
1399 && ! list_isempty (area->opaque_lsa_self))
1400 {
paul1eb8ef22005-04-07 07:30:20 +00001401 for (ALL_LIST_ELEMENTS (area->opaque_lsa_self, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001402 {
hasso0d85b992004-03-18 19:18:33 +00001403 /*
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)
1407 * not being empty.
1408 */
paul1eb8ef22005-04-07 07:30:20 +00001409 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1410 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001411 continue;
1412
1413 ospf_opaque_lsa_reoriginate_schedule ((void *) area,
1414 OSPF_OPAQUE_AREA_LSA, oipt->opaque_type);
1415 }
1416 }
1417
1418 if (! list_isempty (ospf_opaque_type11_funclist)
1419 && ! list_isempty (top->opaque_lsa_self))
1420 {
paul1eb8ef22005-04-07 07:30:20 +00001421 for (ALL_LIST_ELEMENTS (top->opaque_lsa_self, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001422 {
hasso0d85b992004-03-18 19:18:33 +00001423 /*
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)
1427 * not being empty.
1428 */
paul1eb8ef22005-04-07 07:30:20 +00001429 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1430 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001431 continue;
1432
1433 ospf_opaque_lsa_reoriginate_schedule ((void *) top,
1434 OSPF_OPAQUE_AS_LSA, oipt->opaque_type);
1435 }
1436 }
1437
1438 if (delay0 != NULL)
1439 *delay0 = delay;
1440
1441out:
1442 return;
1443}
1444
1445static int
1446ospf_opaque_type9_lsa_originate (struct thread *t)
1447{
1448 struct ospf_interface *oi;
1449 int rc;
1450
1451 oi = THREAD_ARG (t);
1452 oi->t_opaque_lsa_self = NULL;
1453
1454 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001455 zlog_debug ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
paul718e3742002-12-13 20:15:29 +00001456 IF_NAME (oi));
1457
1458 rc = opaque_lsa_originate_callback (ospf_opaque_type9_funclist, oi);
1459
1460 return rc;
1461}
1462
1463static int
1464ospf_opaque_type10_lsa_originate (struct thread *t)
1465{
1466 struct ospf_area *area;
1467 int rc;
1468
1469 area = THREAD_ARG (t);
1470 area->t_opaque_lsa_self = NULL;
1471
1472 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001473 zlog_debug ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
paul718e3742002-12-13 20:15:29 +00001474 inet_ntoa (area->area_id));
1475
1476 rc = opaque_lsa_originate_callback (ospf_opaque_type10_funclist, area);
1477
1478 return rc;
1479}
1480
1481static int
1482ospf_opaque_type11_lsa_originate (struct thread *t)
1483{
1484 struct ospf *top;
1485 int rc;
1486
1487 top = THREAD_ARG (t);
1488 top->t_opaque_lsa_self = NULL;
1489
1490 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001491 zlog_debug ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
paul718e3742002-12-13 20:15:29 +00001492
1493 rc = opaque_lsa_originate_callback (ospf_opaque_type11_funclist, top);
1494
1495 return rc;
1496}
1497
1498static void
paul87d6f872004-09-24 08:01:38 +00001499ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg)
paul718e3742002-12-13 20:15:29 +00001500{
paul1eb8ef22005-04-07 07:30:20 +00001501 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001502 struct opaque_info_per_type *oipt;
1503 struct ospf_opaque_functab *functab;
1504
1505 if (listtop == NULL)
1506 goto out;
1507
1508 /*
1509 * Pickup oipt entries those which in SUSPEND status, and give
1510 * them a chance to start re-origination now.
1511 */
paul1eb8ef22005-04-07 07:30:20 +00001512 for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001513 {
paul87d6f872004-09-24 08:01:38 +00001514 if (oipt->status != PROC_SUSPEND)
paul718e3742002-12-13 20:15:29 +00001515 continue;
1516
1517 oipt->status = PROC_NORMAL;
1518
1519 if ((functab = oipt->functab) == NULL
paul87d6f872004-09-24 08:01:38 +00001520 || functab->lsa_originator == NULL)
paul718e3742002-12-13 20:15:29 +00001521 continue;
1522
1523 if ((* functab->lsa_originator)(arg) != 0)
1524 {
1525 zlog_warn ("ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", oipt->opaque_type);
1526 continue;
1527 }
1528 }
1529
1530out:
1531 return;
1532}
1533
1534struct ospf_lsa *
1535ospf_opaque_lsa_install (struct ospf_lsa *lsa, int rt_recalc)
1536{
1537 struct ospf_lsa *new = NULL;
1538 struct opaque_info_per_type *oipt;
1539 struct opaque_info_per_id *oipi;
1540 struct ospf *top;
1541
1542 /* Don't take "rt_recalc" into consideration for now. *//* XXX */
1543
1544 if (! IS_LSA_SELF (lsa))
1545 {
1546 new = lsa; /* Don't touch this LSA. */
1547 goto out;
1548 }
1549
1550 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
ajs2a42e282004-12-08 18:43:03 +00001551 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)));
paul718e3742002-12-13 20:15:29 +00001552
1553 /* Replace the existing lsa with the new one. */
1554 if ((oipt = lookup_opaque_info_by_type (lsa)) != NULL
paul87d6f872004-09-24 08:01:38 +00001555 && (oipi = lookup_opaque_info_by_id (oipt, lsa)) != NULL)
paul718e3742002-12-13 20:15:29 +00001556 {
Paul Jakma1fe6ed32006-07-26 09:37:26 +00001557 ospf_lsa_unlock (&oipi->lsa);
paul718e3742002-12-13 20:15:29 +00001558 oipi->lsa = ospf_lsa_lock (lsa);
1559 }
1560 /* Register the new lsa entry and get its control info. */
1561 else
1562 if ((oipi = register_opaque_lsa (lsa)) == NULL)
1563 {
1564 zlog_warn ("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1565 goto out;
1566 }
1567
1568 /*
1569 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1570 * for periodic refresh of self-originated Opaque-LSAs.
1571 */
1572 switch (lsa->data->type)
1573 {
1574 case OSPF_OPAQUE_LINK_LSA:
paul09e4efd2003-01-18 00:12:02 +00001575 if ((top = oi_to_top (lsa->oi)) == NULL)
1576 {
1577 /* Above conditions must have passed. */
1578 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1579 goto out;
1580 }
1581 break;
paul718e3742002-12-13 20:15:29 +00001582 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00001583 if (lsa->area == NULL || (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001584 {
1585 /* Above conditions must have passed. */
1586 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1587 goto out;
1588 }
1589 break;
1590 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +00001591 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001592 if (lsa->area != NULL && (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001593 {
1594 /* Above conditions must have passed. */
1595 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1596 goto out;
1597 }
1598 break;
1599 default:
1600 zlog_warn ("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", lsa->data->type);
1601 goto out;
1602 }
1603
1604 ospf_refresher_register_lsa (top, lsa);
1605 new = lsa;
1606
1607out:
1608 return new;
1609}
1610
1611void
1612ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
1613{
paul020709f2003-04-04 02:44:16 +00001614 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001615 struct ospf_opaque_functab *functab;
1616
paul020709f2003-04-04 02:44:16 +00001617 ospf = ospf_lookup ();
1618
paul718e3742002-12-13 20:15:29 +00001619 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL
paul87d6f872004-09-24 08:01:38 +00001620 || functab->lsa_refresher == NULL)
paul718e3742002-12-13 20:15:29 +00001621 {
1622 /*
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.
1628 */
1629 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001630 zlog_debug ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id));
paul718e3742002-12-13 20:15:29 +00001631
1632 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
paul68980082003-03-25 05:07:42 +00001633 ospf_lsa_maxage (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00001634 }
1635 else
1636 (* functab->lsa_refresher)(lsa);
1637
1638 return;
1639}
1640
1641/*------------------------------------------------------------------------*
1642 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1643 * triggered by external interventions (vty session, signaling, etc).
1644 *------------------------------------------------------------------------*/
1645
1646#define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
1647 if (!(T)) \
1648 (T) = thread_add_timer (master, (F), (L), (V))
1649
1650static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type);
1651static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t);
1652static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t);
1653static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t);
1654static int ospf_opaque_lsa_refresh_timer (struct thread *t);
1655
1656void
1657ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
1658 u_char lsa_type, u_char opaque_type)
1659{
1660 struct ospf *top;
1661 struct ospf_area dummy, *area = NULL;
1662 struct ospf_interface *oi = NULL;
1663
1664 struct ospf_lsa *lsa;
1665 struct opaque_info_per_type *oipt;
paul87d6f872004-09-24 08:01:38 +00001666 int (*func) (struct thread * t) = NULL;
paul718e3742002-12-13 20:15:29 +00001667 int delay;
1668
1669 switch (lsa_type)
1670 {
1671 case OSPF_OPAQUE_LINK_LSA:
1672 if ((oi = (struct ospf_interface *) lsa_type_dependent) == NULL)
1673 {
paul87d6f872004-09-24 08:01:38 +00001674 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1675 " Type-9 Opaque-LSA: Invalid parameter?");
1676 goto out;
paul718e3742002-12-13 20:15:29 +00001677 }
1678 if ((top = oi_to_top (oi)) == NULL)
1679 {
paul87d6f872004-09-24 08:01:38 +00001680 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1681 IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001682 goto out;
1683 }
paul87d6f872004-09-24 08:01:38 +00001684 if (!list_isempty (ospf_opaque_type9_funclist)
1685 && list_isempty (oi->opaque_lsa_self)
1686 && oi->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001687 {
paul87d6f872004-09-24 08:01:38 +00001688 zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u):"
1689 " Common origination for OI(%s) has already started",
1690 opaque_type, IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001691 goto out;
1692 }
1693 func = ospf_opaque_type9_lsa_reoriginate_timer;
1694 break;
1695 case OSPF_OPAQUE_AREA_LSA:
1696 if ((area = (struct ospf_area *) lsa_type_dependent) == NULL)
1697 {
paul87d6f872004-09-24 08:01:38 +00001698 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1699 " Type-10 Opaque-LSA: Invalid parameter?");
paul718e3742002-12-13 20:15:29 +00001700 goto out;
1701 }
paul68980082003-03-25 05:07:42 +00001702 if ((top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001703 {
paul87d6f872004-09-24 08:01:38 +00001704 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1705 " AREA(%s) -> TOP?", inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001706 goto out;
1707 }
paul87d6f872004-09-24 08:01:38 +00001708 if (!list_isempty (ospf_opaque_type10_funclist)
1709 && list_isempty (area->opaque_lsa_self)
1710 && area->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001711 {
paul87d6f872004-09-24 08:01:38 +00001712 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));
paul718e3742002-12-13 20:15:29 +00001715 goto out;
1716 }
1717 func = ospf_opaque_type10_lsa_reoriginate_timer;
1718 break;
1719 case OSPF_OPAQUE_AS_LSA:
1720 if ((top = (struct ospf *) lsa_type_dependent) == NULL)
1721 {
paul87d6f872004-09-24 08:01:38 +00001722 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1723 " Type-11 Opaque-LSA: Invalid parameter?");
1724 goto out;
paul718e3742002-12-13 20:15:29 +00001725 }
paul87d6f872004-09-24 08:01:38 +00001726 if (!list_isempty (ospf_opaque_type11_funclist)
1727 && list_isempty (top->opaque_lsa_self)
1728 && top->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001729 {
paul87d6f872004-09-24 08:01:38 +00001730 zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u):"
1731 " Common origination has already started", opaque_type);
paul718e3742002-12-13 20:15:29 +00001732 goto out;
1733 }
1734
1735 /* Fake "area" to pass "ospf" to a lookup function later. */
paul68980082003-03-25 05:07:42 +00001736 dummy.ospf = top;
paul718e3742002-12-13 20:15:29 +00001737 area = &dummy;
1738
1739 func = ospf_opaque_type11_lsa_reoriginate_timer;
1740 break;
1741 default:
paul87d6f872004-09-24 08:01:38 +00001742 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1743 " Unexpected LSA-type(%u)",
1744 lsa_type);
paul718e3742002-12-13 20:15:29 +00001745 goto out;
1746 }
1747
1748 /* It may not a right time to schedule reorigination now. */
paul87d6f872004-09-24 08:01:38 +00001749 if (!CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
paul718e3742002-12-13 20:15:29 +00001750 {
1751 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001752 zlog_debug ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
paul87d6f872004-09-24 08:01:38 +00001753 goto out; /* This is not an error. */
paul718e3742002-12-13 20:15:29 +00001754 }
1755 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
1756 {
1757 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001758 zlog_debug ("ospf_opaque_lsa_reoriginate_schedule: Under blockade.");
paul87d6f872004-09-24 08:01:38 +00001759 goto out; /* This is not an error, too. */
paul718e3742002-12-13 20:15:29 +00001760 }
1761
1762 /* Generate a dummy lsa to be passed for a lookup function. */
1763 lsa = pseudo_lsa (oi, area, lsa_type, opaque_type);
1764
1765 if ((oipt = lookup_opaque_info_by_type (lsa)) == NULL)
1766 {
1767 struct ospf_opaque_functab *functab;
1768 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL)
1769 {
paul87d6f872004-09-24 08:01:38 +00001770 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1771 " No associated function?: lsa_type(%u),"
1772 " opaque_type(%u)",
1773 lsa_type, opaque_type);
paul718e3742002-12-13 20:15:29 +00001774 goto out;
1775 }
1776 if ((oipt = register_opaque_info_per_type (functab, lsa)) == NULL)
1777 {
paul87d6f872004-09-24 08:01:38 +00001778 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1779 " Cannot get a control info?: lsa_type(%u),"
1780 " opaque_type(%u)",
1781 lsa_type, opaque_type);
paul718e3742002-12-13 20:15:29 +00001782 goto out;
1783 }
1784 }
1785
1786 if (oipt->t_opaque_lsa_self != NULL)
1787 {
1788 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001789 zlog_debug ("Type-%u Opaque-LSA has already scheduled to"
paul87d6f872004-09-24 08:01:38 +00001790 " RE-ORIGINATE: [opaque-type=%u]",
1791 lsa_type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
paul718e3742002-12-13 20:15:29 +00001792 goto out;
1793 }
1794
1795 /*
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.
1801 */
1802 delay = OSPF_MIN_LS_INTERVAL; /* XXX */
1803
1804 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001805 zlog_debug ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
paul87d6f872004-09-24 08:01:38 +00001806 " sec later: [opaque-type=%u]",
1807 lsa_type, delay,
1808 GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
paul718e3742002-12-13 20:15:29 +00001809
1810 OSPF_OPAQUE_TIMER_ON (oipt->t_opaque_lsa_self, func, oipt, delay);
1811
1812out:
1813 return;
1814}
1815
1816static struct ospf_lsa *
1817pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area,
1818 u_char lsa_type, u_char opaque_type)
1819{
1820 static struct ospf_lsa lsa = { 0 };
1821 static struct lsa_header lsah = { 0 };
1822 u_int32_t tmp;
1823
1824 lsa.oi = oi;
1825 lsa.area = area;
1826 lsa.data = &lsah;
1827
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);
1831
1832 return &lsa;
1833}
1834
1835static int
1836ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t)
1837{
1838 struct opaque_info_per_type *oipt;
1839 struct ospf_opaque_functab *functab;
1840 struct ospf *top;
1841 struct ospf_interface *oi;
1842 int rc = -1;
1843
1844 oipt = THREAD_ARG (t);
1845 oipt->t_opaque_lsa_self = NULL;
1846
1847 if ((functab = oipt->functab) == NULL
1848 || functab->lsa_originator == NULL)
1849 {
1850 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1851 goto out;
1852 }
1853
1854 oi = (struct ospf_interface *) oipt->owner;
1855 if ((top = oi_to_top (oi)) == NULL)
1856 {
1857 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1858 goto out;
1859 }
1860
1861 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)
1862 || ! ospf_if_is_enable (oi)
paul68980082003-03-25 05:07:42 +00001863 || ospf_nbr_count_opaque_capable (oi) == 0)
paul718e3742002-12-13 20:15:29 +00001864 {
1865 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001866 zlog_debug ("Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
paul718e3742002-12-13 20:15:29 +00001867
1868 oipt->status = PROC_SUSPEND;
1869 rc = 0;
1870 goto out;
1871 }
1872
1873 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001874 zlog_debug ("Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)", oipt->opaque_type, IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001875
1876 rc = (* functab->lsa_originator)(oi);
1877out:
1878 return rc;
1879}
1880
1881static int
1882ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t)
1883{
1884 struct opaque_info_per_type *oipt;
1885 struct ospf_opaque_functab *functab;
paul1eb8ef22005-04-07 07:30:20 +00001886 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001887 struct ospf *top;
1888 struct ospf_area *area;
1889 struct ospf_interface *oi;
1890 int n, rc = -1;
1891
1892 oipt = THREAD_ARG (t);
1893 oipt->t_opaque_lsa_self = NULL;
1894
1895 if ((functab = oipt->functab) == NULL
1896 || functab->lsa_originator == NULL)
1897 {
1898 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1899 goto out;
1900 }
1901
1902 area = (struct ospf_area *) oipt->owner;
paul68980082003-03-25 05:07:42 +00001903 if (area == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001904 {
1905 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1906 goto out;
1907 }
1908
1909 /* There must be at least one "opaque-capable, full-state" neighbor. */
1910 n = 0;
paul1eb8ef22005-04-07 07:30:20 +00001911 for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi))
paul718e3742002-12-13 20:15:29 +00001912 {
paul68980082003-03-25 05:07:42 +00001913 if ((n = ospf_nbr_count_opaque_capable (oi)) > 0)
paul718e3742002-12-13 20:15:29 +00001914 break;
1915 }
1916
1917 if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1918 {
1919 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001920 zlog_debug ("Suspend re-origination of Type-10 Opaque-LSAs"
paul87d6f872004-09-24 08:01:38 +00001921 " (opaque-type=%u) for a while...",
1922 oipt->opaque_type);
paul718e3742002-12-13 20:15:29 +00001923
1924 oipt->status = PROC_SUSPEND;
1925 rc = 0;
1926 goto out;
1927 }
1928
1929 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001930 zlog_debug ("Timer[Type10-LSA]: Re-originate Opaque-LSAs"
paul87d6f872004-09-24 08:01:38 +00001931 " (opaque-type=%u) for Area %s",
1932 oipt->opaque_type, inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001933
1934 rc = (* functab->lsa_originator)(area);
1935out:
1936 return rc;
1937}
1938
1939static int
1940ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t)
1941{
1942 struct opaque_info_per_type *oipt;
1943 struct ospf_opaque_functab *functab;
1944 struct ospf *top;
1945 int rc = -1;
1946
1947 oipt = THREAD_ARG (t);
1948 oipt->t_opaque_lsa_self = NULL;
1949
1950 if ((functab = oipt->functab) == NULL
paul87d6f872004-09-24 08:01:38 +00001951 || functab->lsa_originator == NULL)
paul718e3742002-12-13 20:15:29 +00001952 {
paul87d6f872004-09-24 08:01:38 +00001953 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer:"
1954 " No associated function?");
paul718e3742002-12-13 20:15:29 +00001955 goto out;
1956 }
1957
1958 if ((top = (struct ospf *) oipt->owner) == NULL)
1959 {
1960 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1961 goto out;
1962 }
1963
1964 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1965 {
1966 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001967 zlog_debug ("Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
paul718e3742002-12-13 20:15:29 +00001968
1969 oipt->status = PROC_SUSPEND;
1970 rc = 0;
1971 goto out;
1972 }
1973
1974 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001975 zlog_debug ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type);
paul718e3742002-12-13 20:15:29 +00001976
1977 rc = (* functab->lsa_originator)(top);
1978out:
1979 return rc;
1980}
1981
paul718e3742002-12-13 20:15:29 +00001982void
1983ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
1984{
1985 struct opaque_info_per_type *oipt;
1986 struct opaque_info_per_id *oipi;
1987 struct ospf_lsa *lsa;
1988 int delay;
1989
1990 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
1991 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
1992 {
1993 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
1994 goto out;
1995 }
1996
1997 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
1998 if ((lsa = oipi->lsa) == NULL)
1999 {
2000 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
2001 goto out;
2002 }
2003
2004 if (oipi->t_opaque_lsa_self != NULL)
2005 {
2006 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002007 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)));
paul718e3742002-12-13 20:15:29 +00002008 goto out;
2009 }
2010
2011 /* Delete this lsa from neighbor retransmit-list. */
2012 switch (lsa->data->type)
2013 {
2014 case OSPF_OPAQUE_LINK_LSA:
2015 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002016 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002017 break;
2018 case OSPF_OPAQUE_AS_LSA:
ajse6a0bf92005-09-17 18:53:38 +00002019 ospf_ls_retransmit_delete_nbr_as (lsa0->area->ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002020 break;
2021 default:
2022 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2023 goto out;
2024 }
2025
2026 delay = ospf_lsa_refresh_delay (lsa);
2027
2028 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002029 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)));
paul718e3742002-12-13 20:15:29 +00002030
2031 OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self,
2032 ospf_opaque_lsa_refresh_timer, oipi, delay);
2033out:
2034 return;
2035}
2036
2037static int
2038ospf_opaque_lsa_refresh_timer (struct thread *t)
2039{
2040 struct opaque_info_per_id *oipi;
2041 struct ospf_opaque_functab *functab;
2042 struct ospf_lsa *lsa;
2043
2044 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002045 zlog_debug ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
paul718e3742002-12-13 20:15:29 +00002046
2047 oipi = THREAD_ARG (t);
2048 oipi->t_opaque_lsa_self = NULL;
2049
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);
2054
2055 return 0;
2056}
2057
2058void
2059ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
2060{
2061 struct opaque_info_per_type *oipt;
2062 struct opaque_info_per_id *oipi;
2063 struct ospf_lsa *lsa;
2064
2065 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
2066 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
2067 {
2068 zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2069 goto out;
2070 }
2071
2072 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2073 if ((lsa = oipi->lsa) == NULL)
2074 {
2075 zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
2076 goto out;
2077 }
2078
2079 /* Delete this lsa from neighbor retransmit-list. */
2080 switch (lsa->data->type)
2081 {
2082 case OSPF_OPAQUE_LINK_LSA:
2083 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002084 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002085 break;
2086 case OSPF_OPAQUE_AS_LSA:
ajse6a0bf92005-09-17 18:53:38 +00002087 ospf_ls_retransmit_delete_nbr_as (lsa0->area->ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002088 break;
2089 default:
2090 zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2091 goto out;
2092 }
2093
2094 /* Dequeue listnode entry from the list. */
2095 listnode_delete (oipt->id_list, oipi);
2096
2097 /* Avoid misjudgement in the next lookup. */
2098 if (listcount (oipt->id_list) == 0)
2099 oipt->id_list->head = oipt->id_list->tail = NULL;
2100
2101 /* Disassociate internal control information with the given lsa. */
paul718e3742002-12-13 20:15:29 +00002102 free_opaque_info_per_id ((void *) oipi);
2103
2104 /* Force given lsa's age to MaxAge. */
2105 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2106
2107 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002108 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)));
paul718e3742002-12-13 20:15:29 +00002109
2110 /* This lsa will be flushed and removed eventually. */
ajse6a0bf92005-09-17 18:53:38 +00002111 ospf_lsa_maxage (lsa0->area->ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002112
2113out:
2114 return;
2115}
2116
2117/*------------------------------------------------------------------------*
2118 * Followings are control functions to block origination after restart.
2119 *------------------------------------------------------------------------*/
2120
2121static void ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs, struct ospf_neighbor *inbr, struct ospf_lsa *lsa);
2122static void ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi);
2123static void ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area);
2124static void ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top);
2125static unsigned long ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type);
2126
2127void
paul87d6f872004-09-24 08:01:38 +00002128ospf_opaque_adjust_lsreq (struct ospf_neighbor *nbr, struct list *lsas)
paul718e3742002-12-13 20:15:29 +00002129{
2130 struct ospf *top;
2131 struct ospf_area *area;
2132 struct ospf_interface *oi;
paul1eb8ef22005-04-07 07:30:20 +00002133 struct listnode *node1, *nnode1;
2134 struct listnode *node2, *nnode2;
paul718e3742002-12-13 20:15:29 +00002135 struct ospf_lsa *lsa;
2136
2137 if ((top = oi_to_top (nbr->oi)) == NULL)
2138 goto out;
2139
2140 /*
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.
2150 */
paul1eb8ef22005-04-07 07:30:20 +00002151 for (ALL_LIST_ELEMENTS (lsas, node1, nnode1, lsa))
paul718e3742002-12-13 20:15:29 +00002152 {
paul718e3742002-12-13 20:15:29 +00002153 /* Filter out unwanted LSAs. */
2154 if (! IS_OPAQUE_LSA (lsa->data->type))
2155 continue;
2156 if (! IPV4_ADDR_SAME (&lsa->data->adv_router, &top->router_id))
2157 continue;
2158
2159 /*
2160 * Don't touch an LSA which has MaxAge; two possible cases.
2161 *
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.
2165 *
2166 * 2) This LSA has expired in an opaque-capable router and thus
2167 * flushed by the router.
2168 */
2169 if (IS_LSA_MAXAGE (lsa))
2170 continue;
2171
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)
2174 continue;
2175
2176 /* Ok, here we go. */
2177 switch (lsa->data->type)
2178 {
2179 case OSPF_OPAQUE_LINK_LSA:
2180 oi = nbr->oi;
2181 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2182 break;
2183 case OSPF_OPAQUE_AREA_LSA:
2184 area = nbr->oi->area;
paul1eb8ef22005-04-07 07:30:20 +00002185 for (ALL_LIST_ELEMENTS (area->oiflist, node2, nnode2, oi))
2186 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
paul718e3742002-12-13 20:15:29 +00002187 break;
2188 case OSPF_OPAQUE_AS_LSA:
paul1eb8ef22005-04-07 07:30:20 +00002189 for (ALL_LIST_ELEMENTS (top->oiflist, node2, nnode2, oi))
2190 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
paul718e3742002-12-13 20:15:29 +00002191 break;
2192 default:
2193 break;
2194 }
2195 }
2196
2197out:
2198 return;
2199}
2200
2201static void
2202ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs,
2203 struct ospf_neighbor *inbr,
2204 struct ospf_lsa *lsa)
2205{
2206 struct route_node *rn;
2207 struct ospf_neighbor *onbr;
2208 struct ospf_lsa *ls_req;
2209
2210 for (rn = route_top (nbrs); rn; rn = route_next (rn))
2211 {
2212 if ((onbr = rn->info) == NULL)
2213 continue;
2214 if (onbr == inbr)
2215 continue;
2216 if ((ls_req = ospf_ls_request_lookup (onbr, lsa)) == NULL)
2217 continue;
2218
2219 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002220 zlog_debug ("LSA[%s]: Exclude this entry from LSReq to send.", dump_lsa_key (lsa));
paul718e3742002-12-13 20:15:29 +00002221
2222 ospf_ls_request_delete (onbr, ls_req);
2223/* ospf_check_nbr_loading (onbr);*//* XXX */
2224 }
2225
2226 return;
2227}
2228
2229void
paul87d6f872004-09-24 08:01:38 +00002230ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr,
paul69310a62005-05-11 18:09:59 +00002231 struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002232{
2233 struct ospf *top;
paul718e3742002-12-13 20:15:29 +00002234 u_char before;
2235
2236 if ((top = oi_to_top (nbr->oi)) == NULL)
Paul Jakma1fe6ed32006-07-26 09:37:26 +00002237 return;
paul718e3742002-12-13 20:15:29 +00002238
2239 before = IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque);
2240
paul69310a62005-05-11 18:09:59 +00002241 /*
2242 * Since these LSA entries are not yet installed into corresponding
2243 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2244 */
2245 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2246 switch (lsa->data->type)
paul718e3742002-12-13 20:15:29 +00002247 {
paul69310a62005-05-11 18:09:59 +00002248 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);
2251 break;
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);
2255 break;
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);
2259 break;
2260 default:
2261 zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
Paul Jakma1fe6ed32006-07-26 09:37:26 +00002262 return;
paul718e3742002-12-13 20:15:29 +00002263 }
2264
paul69310a62005-05-11 18:09:59 +00002265 ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */
2266
paul718e3742002-12-13 20:15:29 +00002267 if (before == 0 && IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2268 {
2269 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002270 zlog_debug ("Block Opaque-LSA origination: OFF -> ON");
paul718e3742002-12-13 20:15:29 +00002271 }
paul718e3742002-12-13 20:15:29 +00002272}
2273
2274void
paul69310a62005-05-11 18:09:59 +00002275ospf_opaque_ls_ack_received (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002276{
2277 struct ospf *top;
paul69310a62005-05-11 18:09:59 +00002278 int delay;
2279 struct ospf_interface *oi;
paul1eb8ef22005-04-07 07:30:20 +00002280 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002281
2282 if ((top = oi_to_top (nbr->oi)) == NULL)
paul69310a62005-05-11 18:09:59 +00002283 return;
2284
2285 if (!IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2286 return;
2287
2288 switch (lsa->data->type)
paul718e3742002-12-13 20:15:29 +00002289 {
paul69310a62005-05-11 18:09:59 +00002290 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... */
2294 break;
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... */
2299 break;
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... */
2304 break;
2305 default:
2306 zlog_warn ("ospf_opaque_ls_ack_received: Unexpected LSA-type(%u)", lsa->data->type);
2307 return;
paul718e3742002-12-13 20:15:29 +00002308 }
paul69310a62005-05-11 18:09:59 +00002309
paul718e3742002-12-13 20:15:29 +00002310 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2311 {
paul718e3742002-12-13 20:15:29 +00002312 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002313 zlog_debug ("Block Opaque-LSA origination: ON -> OFF");
paul69310a62005-05-11 18:09:59 +00002314 return; /* Blocking still in progress. */
paul718e3742002-12-13 20:15:29 +00002315 }
paul69310a62005-05-11 18:09:59 +00002316
2317 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
2318 return; /* Opaque capability condition must have changed. */
paul718e3742002-12-13 20:15:29 +00002319
paul69310a62005-05-11 18:09:59 +00002320 /* Ok, let's start origination of Opaque-LSAs. */
2321 delay = OSPF_MIN_LS_INTERVAL;
2322
2323 for (ALL_LIST_ELEMENTS (top->oiflist, node, nnode, oi))
2324 {
2325 if (! ospf_if_is_enable (oi)
2326 || ospf_nbr_count_opaque_capable (oi) == 0)
2327 continue;
2328
2329 ospf_opaque_lsa_originate_schedule (oi, &delay);
2330 }
2331
paul718e3742002-12-13 20:15:29 +00002332 return;
2333}
2334
2335static void
2336ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi)
2337{
2338 unsigned long n;
2339
2340 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_LINK_LSA);
2341 if (n == 0)
2342 {
2343 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002344 zlog_debug ("Self-originated type-9 Opaque-LSAs: OI(%s): Flush completed", IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00002345
paul68980082003-03-25 05:07:42 +00002346 UNSET_FLAG (oi->area->ospf->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
paul718e3742002-12-13 20:15:29 +00002347 }
2348 return;
2349}
2350
2351static void
2352ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area)
2353{
paul87d6f872004-09-24 08:01:38 +00002354 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002355 struct ospf_interface *oi;
2356 unsigned long n = 0;
2357
paul1eb8ef22005-04-07 07:30:20 +00002358 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00002359 {
paul718e3742002-12-13 20:15:29 +00002360 if (area->area_id.s_addr != OSPF_AREA_BACKBONE
paul1eb8ef22005-04-07 07:30:20 +00002361 && oi->type == OSPF_IFTYPE_VIRTUALLINK)
paul718e3742002-12-13 20:15:29 +00002362 continue;
2363
2364 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AREA_LSA);
2365 if (n > 0)
2366 break;
2367 }
2368
2369 if (n == 0)
2370 {
2371 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002372 zlog_debug ("Self-originated type-10 Opaque-LSAs: AREA(%s): Flush completed", inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00002373
paul68980082003-03-25 05:07:42 +00002374 UNSET_FLAG (area->ospf->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
paul718e3742002-12-13 20:15:29 +00002375 }
2376
2377 return;
2378}
2379
2380static void
2381ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top)
2382{
paul87d6f872004-09-24 08:01:38 +00002383 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002384 struct ospf_interface *oi;
2385 unsigned long n = 0;
2386
paul1eb8ef22005-04-07 07:30:20 +00002387 for (ALL_LIST_ELEMENTS_RO (top->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00002388 {
paul718e3742002-12-13 20:15:29 +00002389 switch (oi->type)
2390 {
2391 case OSPF_IFTYPE_VIRTUALLINK:
2392 continue;
2393 default:
2394 break;
2395 }
2396
2397 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AS_LSA);
2398 if (n > 0)
2399 goto out;
2400 }
2401
2402 if (n == 0)
2403 {
2404 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002405 zlog_debug ("Self-originated type-11 Opaque-LSAs: Flush completed");
paul718e3742002-12-13 20:15:29 +00002406
2407 UNSET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
2408 }
2409
2410out:
2411 return;
2412}
2413
2414static unsigned long
2415ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type)
2416{
2417 struct route_node *rn;
2418 struct ospf_neighbor *nbr;
2419 struct ospf *top;
2420 unsigned long n = 0;
2421
2422 for (rn = route_top (nbrs); rn; rn = route_next (rn))
2423 {
2424 if ((nbr = rn->info) == NULL)
2425 continue;
2426 if ((top = oi_to_top (nbr->oi)) == NULL)
2427 continue;
2428 if (IPV4_ADDR_SAME (&nbr->router_id, &top->router_id))
2429 continue;
2430 n += ospf_ls_retransmit_count_self (nbr, lsa_type);
2431 }
2432
2433 return n;
2434}
2435
2436/*------------------------------------------------------------------------*
2437 * Followings are util functions; probably be used by Opaque-LSAs only...
2438 *------------------------------------------------------------------------*/
2439
2440void
2441htonf (float *src, float *dst)
2442{
2443 u_int32_t lu1, lu2;
2444
2445 memcpy (&lu1, src, sizeof (u_int32_t));
2446 lu2 = htonl (lu1);
2447 memcpy (dst, &lu2, sizeof (u_int32_t));
2448 return;
2449}
2450
2451void
2452ntohf (float *src, float *dst)
2453{
2454 u_int32_t lu1, lu2;
2455
2456 memcpy (&lu1, src, sizeof (u_int32_t));
2457 lu2 = ntohl (lu1);
2458 memcpy (dst, &lu2, sizeof (u_int32_t));
2459 return;
2460}
2461
2462struct ospf *
2463oi_to_top (struct ospf_interface *oi)
2464{
2465 struct ospf *top = NULL;
2466 struct ospf_area *area;
2467
paul68980082003-03-25 05:07:42 +00002468 if (oi == NULL || (area = oi->area) == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00002469 zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");
2470
2471 return top;
2472}
2473
2474#endif /* HAVE_OPAQUE_LSA */