blob: 8563b85a798c9443df95630a9d456fe838abccb3 [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";
226 else if (OPAQUE_TYPE_RANGE_RESERVED (opaque_type))
227 name = "Private/Experimental";
228 break;
229 }
230 return name;
231}
232
233/*------------------------------------------------------------------------*
234 * Followings are management functions to store user specified callbacks.
235 *------------------------------------------------------------------------*/
236
237struct opaque_info_per_type; /* Forward declaration. */
238
239struct ospf_opaque_functab
240{
241 u_char opaque_type;
242 struct opaque_info_per_type *oipt;
243
244 int (* new_if_hook)(struct interface *ifp);
245 int (* del_if_hook)(struct interface *ifp);
246 void (* ism_change_hook)(struct ospf_interface *oi, int old_status);
247 void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status);
248 void (* config_write_router)(struct vty *vty);
249 void (* config_write_if )(struct vty *vty, struct interface *ifp);
250 void (* config_write_debug )(struct vty *vty);
251 void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa);
252 int (* lsa_originator)(void *arg);
253 void (* lsa_refresher )(struct ospf_lsa *lsa);
254 int (* new_lsa_hook)(struct ospf_lsa *lsa);
255 int (* del_lsa_hook)(struct ospf_lsa *lsa);
256};
257
paul87d6f872004-09-24 08:01:38 +0000258/* Handle LSA-9/10/11 altogether. */
259static struct list *ospf_opaque_wildcard_funclist;
260static struct list *ospf_opaque_type9_funclist;
261static struct list *ospf_opaque_type10_funclist;
262static struct list *ospf_opaque_type11_funclist;
paul718e3742002-12-13 20:15:29 +0000263
264static void
265ospf_opaque_del_functab (void *val)
266{
267 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, val);
268 return;
269}
270
271static void
272ospf_opaque_funclist_init (void)
273{
paul87d6f872004-09-24 08:01:38 +0000274 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000275
paul09e4efd2003-01-18 00:12:02 +0000276 funclist = ospf_opaque_wildcard_funclist = list_new ();
277 funclist->del = ospf_opaque_del_functab;
278
paul718e3742002-12-13 20:15:29 +0000279 funclist = ospf_opaque_type9_funclist = list_new ();
280 funclist->del = ospf_opaque_del_functab;
281
282 funclist = ospf_opaque_type10_funclist = list_new ();
283 funclist->del = ospf_opaque_del_functab;
284
285 funclist = ospf_opaque_type11_funclist = list_new ();
286 funclist->del = ospf_opaque_del_functab;
287 return;
288}
289
290static void
291ospf_opaque_funclist_term (void)
292{
paul87d6f872004-09-24 08:01:38 +0000293 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000294
paul09e4efd2003-01-18 00:12:02 +0000295 funclist = ospf_opaque_wildcard_funclist;
296 list_delete (funclist);
297
paul718e3742002-12-13 20:15:29 +0000298 funclist = ospf_opaque_type9_funclist;
299 list_delete (funclist);
300
301 funclist = ospf_opaque_type10_funclist;
302 list_delete (funclist);
303
304 funclist = ospf_opaque_type11_funclist;
305 list_delete (funclist);
306 return;
307}
308
paul87d6f872004-09-24 08:01:38 +0000309static struct list *
paul718e3742002-12-13 20:15:29 +0000310ospf_get_opaque_funclist (u_char lsa_type)
311{
paul87d6f872004-09-24 08:01:38 +0000312 struct list *funclist = NULL;
paul718e3742002-12-13 20:15:29 +0000313
314 switch (lsa_type)
315 {
paul09e4efd2003-01-18 00:12:02 +0000316 case OPAQUE_TYPE_WILDCARD:
317 /* XXX
318 * This is an ugly trick to handle type-9/10/11 LSA altogether.
319 * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor
320 * an officially assigned opaque-type.
321 * Though it is possible that the value might be officially used
322 * in the future, we use it internally as a special label, for now.
323 */
324 funclist = ospf_opaque_wildcard_funclist;
325 break;
paul718e3742002-12-13 20:15:29 +0000326 case OSPF_OPAQUE_LINK_LSA:
327 funclist = ospf_opaque_type9_funclist;
328 break;
329 case OSPF_OPAQUE_AREA_LSA:
330 funclist = ospf_opaque_type10_funclist;
331 break;
332 case OSPF_OPAQUE_AS_LSA:
333 funclist = ospf_opaque_type11_funclist;
334 break;
335 default:
336 zlog_warn ("ospf_get_opaque_funclist: Unexpected LSA-type(%u)", lsa_type);
337 break;
338 }
339 return funclist;
340}
341
paul87d6f872004-09-24 08:01:38 +0000342/* XXX: such a huge argument list can /not/ be healthy... */
paul718e3742002-12-13 20:15:29 +0000343int
344ospf_register_opaque_functab (
345 u_char lsa_type,
346 u_char opaque_type,
347 int (* new_if_hook)(struct interface *ifp),
348 int (* del_if_hook)(struct interface *ifp),
349 void (* ism_change_hook)(struct ospf_interface *oi, int old_status),
350 void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status),
351 void (* config_write_router)(struct vty *vty),
352 void (* config_write_if )(struct vty *vty, struct interface *ifp),
353 void (* config_write_debug )(struct vty *vty),
354 void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa),
355 int (* lsa_originator)(void *arg),
356 void (* lsa_refresher )(struct ospf_lsa *lsa),
357 int (* new_lsa_hook)(struct ospf_lsa *lsa),
358 int (* del_lsa_hook)(struct ospf_lsa *lsa))
359{
paul87d6f872004-09-24 08:01:38 +0000360 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000361 struct ospf_opaque_functab *new;
362 int rc = -1;
363
364 if ((funclist = ospf_get_opaque_funclist (lsa_type)) == NULL)
365 {
paul87d6f872004-09-24 08:01:38 +0000366 zlog_warn ("ospf_register_opaque_functab: Cannot get funclist"
367 " for Type-%u LSAs?",
368 lsa_type);
paul718e3742002-12-13 20:15:29 +0000369 goto out;
370 }
371 else
372 {
paul87d6f872004-09-24 08:01:38 +0000373 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000374 struct ospf_opaque_functab *functab;
paul87d6f872004-09-24 08:01:38 +0000375
376 LIST_LOOP (funclist, functab, node)
377 if (functab->opaque_type == opaque_type)
378 {
379 zlog_warn ("ospf_register_opaque_functab: Duplicated entry?:"
380 " lsa_type(%u), opaque_type(%u)",
381 lsa_type, opaque_type);
382 goto out;
383 }
paul718e3742002-12-13 20:15:29 +0000384 }
385
386 if ((new = XCALLOC (MTYPE_OSPF_OPAQUE_FUNCTAB,
387 sizeof (struct ospf_opaque_functab))) == NULL)
388 {
paul87d6f872004-09-24 08:01:38 +0000389 zlog_warn ("ospf_register_opaque_functab: XMALLOC: %s",
390 strerror (errno));
paul718e3742002-12-13 20:15:29 +0000391 goto out;
392 }
393
394 new->opaque_type = opaque_type;
395 new->oipt = NULL;
396 new->new_if_hook = new_if_hook;
397 new->del_if_hook = del_if_hook;
398 new->ism_change_hook = ism_change_hook;
399 new->nsm_change_hook = nsm_change_hook;
400 new->config_write_router = config_write_router;
401 new->config_write_if = config_write_if;
402 new->config_write_debug = config_write_debug;
403 new->show_opaque_info = show_opaque_info;
404 new->lsa_originator = lsa_originator;
405 new->lsa_refresher = lsa_refresher;
406 new->new_lsa_hook = new_lsa_hook;
407 new->del_lsa_hook = del_lsa_hook;
408
409 listnode_add (funclist, new);
410 rc = 0;
411
412out:
413 return rc;
414}
415
416void
417ospf_delete_opaque_functab (u_char lsa_type, u_char opaque_type)
418{
paul87d6f872004-09-24 08:01:38 +0000419 struct list *funclist;
420 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000421 struct ospf_opaque_functab *functab;
422
423 if ((funclist = ospf_get_opaque_funclist (lsa_type)) != NULL)
424 for (node = listhead (funclist); node; nextnode (node))
425 {
426 if ((functab = getdata (node)) != NULL
paul87d6f872004-09-24 08:01:38 +0000427 && 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)
paul87d6f872004-09-24 08:01:38 +0000457 LIST_LOOP (funclist, functab, node)
458 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 {
539 zlog_warn ("register_opaque_info_per_type: XMALLOC: %s", strerror (errno));
540 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;
paul87d6f872004-09-24 08:01:38 +0000590 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000591
592 /* Control information per opaque-id may still exist. */
593 for (node = listhead (oipt->id_list); node; nextnode (node))
594 {
595 if ((oipi = getdata (node)) == NULL)
596 continue;
597 if ((lsa = oipi->lsa) == NULL)
598 continue;
599 if (IS_LSA_MAXAGE (lsa))
600 continue;
601 ospf_opaque_lsa_flush_schedule (lsa);
602 }
603
paul09e4efd2003-01-18 00:12:02 +0000604 /* Remove "oipt" from its owner's self-originated LSA list. */
605 switch (oipt->lsa_type)
606 {
607 case OSPF_OPAQUE_LINK_LSA:
608 {
609 struct ospf_interface *oi = (struct ospf_interface *)(oipt->owner);
610 listnode_delete (oi->opaque_lsa_self, oipt);
611 break;
612 }
613 case OSPF_OPAQUE_AREA_LSA:
614 {
615 struct ospf_area *area = (struct ospf_area *)(oipt->owner);
616 listnode_delete (area->opaque_lsa_self, oipt);
617 break;
618 }
619 case OSPF_OPAQUE_AS_LSA:
620 {
621 struct ospf *top = (struct ospf *)(oipt->owner);
622 listnode_delete (top->opaque_lsa_self, oipt);
623 break;
624 }
625 default:
626 zlog_warn ("free_opaque_info_per_type: Unexpected LSA-type(%u)", oipt->lsa_type);
627 break; /* This case may not exist. */
628 }
629
paul718e3742002-12-13 20:15:29 +0000630 OSPF_TIMER_OFF (oipt->t_opaque_lsa_self);
631 list_delete (oipt->id_list);
632 XFREE (MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
633 return;
634}
635
636static struct opaque_info_per_type *
637lookup_opaque_info_by_type (struct ospf_lsa *lsa)
638{
639 struct ospf *top;
640 struct ospf_area *area;
641 struct ospf_interface *oi;
paul87d6f872004-09-24 08:01:38 +0000642 struct list *listtop = NULL;
643 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000644 struct opaque_info_per_type *oipt = NULL;
645 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
646
647 switch (lsa->data->type)
648 {
649 case OSPF_OPAQUE_LINK_LSA:
650 if ((oi = lsa->oi) != NULL)
651 listtop = oi->opaque_lsa_self;
652 else
653 zlog_warn ("Type-9 Opaque-LSA: Reference to OI is missing?");
654 break;
655 case OSPF_OPAQUE_AREA_LSA:
656 if ((area = lsa->area) != NULL)
657 listtop = area->opaque_lsa_self;
658 else
659 zlog_warn ("Type-10 Opaque-LSA: Reference to AREA is missing?");
660 break;
661 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +0000662 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000663 if ((area = lsa->area) != NULL && (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +0000664 {
665 zlog_warn ("Type-11 Opaque-LSA: Reference to OSPF is missing?");
666 break; /* Unlikely to happen. */
667 }
668 listtop = top->opaque_lsa_self;
669 break;
670 default:
671 zlog_warn ("lookup_opaque_info_by_type: Unexpected LSA-type(%u)", lsa->data->type);
672 break;
673 }
674
675 if (listtop != NULL)
paul87d6f872004-09-24 08:01:38 +0000676 LIST_LOOP (listtop, oipt, node)
677 if (oipt->opaque_type == key)
678 return oipt;
paul718e3742002-12-13 20:15:29 +0000679
680 return NULL;
681}
682
683static struct opaque_info_per_id *
684register_opaque_info_per_id (struct opaque_info_per_type *oipt,
685 struct ospf_lsa *new)
686{
687 struct opaque_info_per_id *oipi;
688
689 if ((oipi = XCALLOC (MTYPE_OPAQUE_INFO_PER_ID,
690 sizeof (struct opaque_info_per_id))) == NULL)
691 {
692 zlog_warn ("register_opaque_info_per_id: XMALLOC: %s", strerror (errno));
693 goto out;
694 }
695 oipi->opaque_id = GET_OPAQUE_ID (ntohl (new->data->id.s_addr));
696 oipi->t_opaque_lsa_self = NULL;
697 oipi->opqctl_type = oipt;
698 oipi->lsa = ospf_lsa_lock (new);
699
700 listnode_add (oipt->id_list, oipi);
701
702out:
703 return oipi;
704}
705
706static void
707free_opaque_info_per_id (void *val)
708{
709 struct opaque_info_per_id *oipi = (struct opaque_info_per_id *) val;
710
711 OSPF_TIMER_OFF (oipi->t_opaque_lsa_self);
712 if (oipi->lsa != NULL)
713 ospf_lsa_unlock (oipi->lsa);
714 XFREE (MTYPE_OPAQUE_INFO_PER_ID, oipi);
715 return;
716}
717
718static struct opaque_info_per_id *
719lookup_opaque_info_by_id (struct opaque_info_per_type *oipt,
720 struct ospf_lsa *lsa)
721{
paul87d6f872004-09-24 08:01:38 +0000722 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000723 struct opaque_info_per_id *oipi;
724 u_int32_t key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
725
paul87d6f872004-09-24 08:01:38 +0000726 LIST_LOOP (oipt->id_list, oipi, node)
727 if (oipi->opaque_id == key)
728 return oipi;
paul718e3742002-12-13 20:15:29 +0000729
730 return NULL;
731}
732
733static struct opaque_info_per_id *
734register_opaque_lsa (struct ospf_lsa *new)
735{
736 struct ospf_opaque_functab *functab;
737 struct opaque_info_per_type *oipt;
738 struct opaque_info_per_id *oipi = NULL;
739
740 if ((functab = ospf_opaque_functab_lookup (new)) == NULL)
741 goto out;
742
743 if ((oipt = lookup_opaque_info_by_type (new)) == NULL
744 && (oipt = register_opaque_info_per_type (functab, new)) == NULL)
745 goto out;
746
747 if ((oipi = register_opaque_info_per_id (oipt, new)) == NULL)
748 goto out;
749
750out:
751 return oipi;
752}
753
754/*------------------------------------------------------------------------*
755 * Followings are (vty) configuration functions for Opaque-LSAs handling.
756 *------------------------------------------------------------------------*/
757
758DEFUN (capability_opaque,
759 capability_opaque_cmd,
760 "capability opaque",
761 "Enable specific OSPF feature\n"
762 "Opaque LSA\n")
763{
764 struct ospf *ospf = (struct ospf *) vty->index;
765
766 /* Turn on the "master switch" of opaque-lsa capability. */
767 if (!CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
768 {
769 if (IS_DEBUG_OSPF_EVENT)
770 zlog_info ("Opaque capability: OFF -> ON");
771
772 SET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
773 ospf_renegotiate_optional_capabilities (ospf);
774 }
775 return CMD_SUCCESS;
776}
777
778ALIAS (capability_opaque,
779 ospf_opaque_capable_cmd,
780 "ospf opaque-lsa",
781 "OSPF specific commands\n"
782 "Enable the Opaque-LSA capability (rfc2370)\n")
783
784DEFUN (no_capability_opaque,
785 no_capability_opaque_cmd,
786 "no capability opaque",
787 NO_STR
788 "Enable specific OSPF feature\n"
789 "Opaque LSA\n")
790{
791 struct ospf *ospf = (struct ospf *) vty->index;
792
793 /* Turn off the "master switch" of opaque-lsa capability. */
794 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
795 {
796 if (IS_DEBUG_OSPF_EVENT)
797 zlog_info ("Opaque capability: ON -> OFF");
798
799 UNSET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
800 ospf_renegotiate_optional_capabilities (ospf);
801 }
802 return CMD_SUCCESS;
803}
804
805ALIAS (no_capability_opaque,
806 no_ospf_opaque_capable_cmd,
807 "no ospf opaque-lsa",
808 NO_STR
809 "OSPF specific commands\n"
810 "Disable the Opaque-LSA capability (rfc2370)\n")
811
812static void
813ospf_opaque_register_vty (void)
814{
815 install_element (OSPF_NODE, &capability_opaque_cmd);
816 install_element (OSPF_NODE, &no_capability_opaque_cmd);
817 install_element (OSPF_NODE, &ospf_opaque_capable_cmd);
818 install_element (OSPF_NODE, &no_ospf_opaque_capable_cmd);
819 return;
820}
821
822/*------------------------------------------------------------------------*
823 * Followings are collection of user-registered function callers.
824 *------------------------------------------------------------------------*/
825
826static int
paul87d6f872004-09-24 08:01:38 +0000827opaque_lsa_new_if_callback (struct list *funclist, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000828{
paul87d6f872004-09-24 08:01:38 +0000829 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000830 struct ospf_opaque_functab *functab;
831 int rc = -1;
832
paul87d6f872004-09-24 08:01:38 +0000833 LIST_LOOP (funclist, functab, node)
834 if (functab->new_if_hook != NULL)
835 if ((* functab->new_if_hook)(ifp) != 0)
836 goto out;
paul718e3742002-12-13 20:15:29 +0000837 rc = 0;
838out:
839 return rc;
840}
841
842static int
paul87d6f872004-09-24 08:01:38 +0000843opaque_lsa_del_if_callback (struct list *funclist, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000844{
paul87d6f872004-09-24 08:01:38 +0000845 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000846 struct ospf_opaque_functab *functab;
847 int rc = -1;
848
paul87d6f872004-09-24 08:01:38 +0000849 LIST_LOOP (funclist, functab, node)
850 if (functab->del_if_hook != NULL)
851 if ((* functab->del_if_hook)(ifp) != 0)
852 goto out;
paul718e3742002-12-13 20:15:29 +0000853 rc = 0;
854out:
855 return rc;
856}
857
858static void
paul87d6f872004-09-24 08:01:38 +0000859opaque_lsa_ism_change_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000860 struct ospf_interface *oi, int old_status)
861{
paul87d6f872004-09-24 08:01:38 +0000862 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000863 struct ospf_opaque_functab *functab;
864
paul87d6f872004-09-24 08:01:38 +0000865 LIST_LOOP (funclist, functab, node)
866 if (functab->ism_change_hook != NULL)
867 (* functab->ism_change_hook)(oi, old_status);
868
paul718e3742002-12-13 20:15:29 +0000869 return;
870}
871
872static void
paul87d6f872004-09-24 08:01:38 +0000873opaque_lsa_nsm_change_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000874 struct ospf_neighbor *nbr, int old_status)
875{
paul87d6f872004-09-24 08:01:38 +0000876 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000877 struct ospf_opaque_functab *functab;
878
paul87d6f872004-09-24 08:01:38 +0000879 LIST_LOOP (funclist, functab, node)
880 if (functab->nsm_change_hook != NULL)
881 (* functab->nsm_change_hook)(nbr, old_status);
paul718e3742002-12-13 20:15:29 +0000882 return;
883}
884
885static void
paul87d6f872004-09-24 08:01:38 +0000886opaque_lsa_config_write_router_callback (struct list *funclist,
887 struct vty *vty)
paul718e3742002-12-13 20:15:29 +0000888{
paul87d6f872004-09-24 08:01:38 +0000889 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000890 struct ospf_opaque_functab *functab;
891
paul87d6f872004-09-24 08:01:38 +0000892 LIST_LOOP (funclist, functab, node)
893 if (functab->config_write_router != NULL)
894 (* functab->config_write_router)(vty);
paul718e3742002-12-13 20:15:29 +0000895 return;
896}
897
898static void
paul87d6f872004-09-24 08:01:38 +0000899opaque_lsa_config_write_if_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000900 struct vty *vty, struct interface *ifp)
901{
paul87d6f872004-09-24 08:01:38 +0000902 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000903 struct ospf_opaque_functab *functab;
904
paul87d6f872004-09-24 08:01:38 +0000905 LIST_LOOP (funclist, functab, node)
906 if (functab->config_write_if != NULL)
907 (* functab->config_write_if)(vty, ifp);
paul718e3742002-12-13 20:15:29 +0000908 return;
909}
910
911static void
paul87d6f872004-09-24 08:01:38 +0000912opaque_lsa_config_write_debug_callback (struct list *funclist, struct vty *vty)
paul718e3742002-12-13 20:15:29 +0000913{
paul87d6f872004-09-24 08:01:38 +0000914 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000915 struct ospf_opaque_functab *functab;
916
paul87d6f872004-09-24 08:01:38 +0000917 LIST_LOOP (funclist, functab, node)
918 if (functab->config_write_debug != NULL)
919 (* functab->config_write_debug)(vty);
paul718e3742002-12-13 20:15:29 +0000920 return;
921}
922
923static int
paul87d6f872004-09-24 08:01:38 +0000924opaque_lsa_originate_callback (struct list *funclist, void *lsa_type_dependent)
paul718e3742002-12-13 20:15:29 +0000925{
paul87d6f872004-09-24 08:01:38 +0000926 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000927 struct ospf_opaque_functab *functab;
928 int rc = -1;
929
paul87d6f872004-09-24 08:01:38 +0000930 LIST_LOOP (funclist, functab, node)
931 if (functab->lsa_originator != NULL)
932 if ((* functab->lsa_originator)(lsa_type_dependent) != 0)
933 goto out;
paul718e3742002-12-13 20:15:29 +0000934 rc = 0;
935out:
936 return rc;
937}
938
939static int
paul87d6f872004-09-24 08:01:38 +0000940new_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000941{
paul87d6f872004-09-24 08:01:38 +0000942 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000943 struct ospf_opaque_functab *functab;
944 int rc = -1;
945
946 /* This function handles ALL types of LSAs, not only opaque ones. */
paul87d6f872004-09-24 08:01:38 +0000947 LIST_LOOP (funclist, functab, node)
948 if (functab->new_lsa_hook != NULL)
949 if ((* functab->new_lsa_hook)(lsa) != 0)
950 goto out;
paul718e3742002-12-13 20:15:29 +0000951 rc = 0;
952out:
953 return rc;
954}
955
956static int
paul87d6f872004-09-24 08:01:38 +0000957del_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000958{
paul87d6f872004-09-24 08:01:38 +0000959 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000960 struct ospf_opaque_functab *functab;
961 int rc = -1;
962
963 /* This function handles ALL types of LSAs, not only opaque ones. */
paul87d6f872004-09-24 08:01:38 +0000964 LIST_LOOP (funclist, functab, node)
965 if (functab->del_lsa_hook != NULL)
966 if ((* functab->del_lsa_hook)(lsa) != 0)
967 goto out;
paul718e3742002-12-13 20:15:29 +0000968 rc = 0;
969out:
970 return rc;
971}
972
973/*------------------------------------------------------------------------*
974 * Followings are glue functions to call Opaque-LSA specific processing.
975 *------------------------------------------------------------------------*/
976
977int
978ospf_opaque_new_if (struct interface *ifp)
979{
paul87d6f872004-09-24 08:01:38 +0000980 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000981 int rc = -1;
982
paul09e4efd2003-01-18 00:12:02 +0000983 funclist = ospf_opaque_wildcard_funclist;
984 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
985 goto out;
986
paul718e3742002-12-13 20:15:29 +0000987 funclist = ospf_opaque_type9_funclist;
988 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
989 goto out;
990
991 funclist = ospf_opaque_type10_funclist;
992 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
993 goto out;
994
995 funclist = ospf_opaque_type11_funclist;
996 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
997 goto out;
998
999 rc = 0;
1000out:
1001 return rc;
1002}
1003
1004int
1005ospf_opaque_del_if (struct interface *ifp)
1006{
paul87d6f872004-09-24 08:01:38 +00001007 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001008 int rc = -1;
1009
paul09e4efd2003-01-18 00:12:02 +00001010 funclist = ospf_opaque_wildcard_funclist;
1011 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1012 goto out;
1013
paul718e3742002-12-13 20:15:29 +00001014 funclist = ospf_opaque_type9_funclist;
1015 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1016 goto out;
1017
1018 funclist = ospf_opaque_type10_funclist;
1019 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1020 goto out;
1021
1022 funclist = ospf_opaque_type11_funclist;
1023 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1024 goto out;
1025
1026 rc = 0;
1027out:
1028 return rc;
1029}
1030
1031void
1032ospf_opaque_ism_change (struct ospf_interface *oi, int old_status)
1033{
paul87d6f872004-09-24 08:01:38 +00001034 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001035
paul09e4efd2003-01-18 00:12:02 +00001036 funclist = ospf_opaque_wildcard_funclist;
1037 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1038
paul718e3742002-12-13 20:15:29 +00001039 funclist = ospf_opaque_type9_funclist;
1040 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1041
1042 funclist = ospf_opaque_type10_funclist;
1043 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1044
1045 funclist = ospf_opaque_type11_funclist;
1046 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1047
1048 return;
1049}
1050
1051void
1052ospf_opaque_nsm_change (struct ospf_neighbor *nbr, int old_state)
1053{
1054 struct ospf *top;
paul87d6f872004-09-24 08:01:38 +00001055 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001056
1057 if ((top = oi_to_top (nbr->oi)) == NULL)
1058 goto out;
1059
1060 if (old_state != NSM_Full && nbr->state == NSM_Full)
1061 {
1062 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
1063 {
1064 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1065 {
1066 if (IS_DEBUG_OSPF_EVENT)
1067 zlog_info ("Opaque-LSA: Now get operational!");
1068
1069 SET_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT);
1070 }
1071
1072 ospf_opaque_lsa_originate_schedule (nbr->oi, NULL);
1073 }
1074 }
1075 else
1076 if (old_state == NSM_Full && nbr->state != NSM_Full)
1077 {
1078#ifdef NOTYET
1079 /*
1080 * If no more opaque-capable full-state neighbor remains in the
1081 * flooding scope which corresponds to Opaque-LSA type, periodic
1082 * LS flooding should be stopped.
1083 */
1084#endif /* NOTYET */
1085 ;
1086 }
1087
paul09e4efd2003-01-18 00:12:02 +00001088 funclist = ospf_opaque_wildcard_funclist;
1089 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1090
paul718e3742002-12-13 20:15:29 +00001091 funclist = ospf_opaque_type9_funclist;
1092 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1093
1094 funclist = ospf_opaque_type10_funclist;
1095 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1096
1097 funclist = ospf_opaque_type11_funclist;
1098 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1099
1100out:
1101 return;
1102}
1103
1104void
1105ospf_opaque_config_write_router (struct vty *vty, struct ospf *ospf)
1106{
paul87d6f872004-09-24 08:01:38 +00001107 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001108
1109 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
1110 vty_out (vty, " capability opaque%s", VTY_NEWLINE);
1111
paul09e4efd2003-01-18 00:12:02 +00001112 funclist = ospf_opaque_wildcard_funclist;
1113 opaque_lsa_config_write_router_callback (funclist, vty);
1114
paul718e3742002-12-13 20:15:29 +00001115 funclist = ospf_opaque_type9_funclist;
1116 opaque_lsa_config_write_router_callback (funclist, vty);
1117
1118 funclist = ospf_opaque_type10_funclist;
1119 opaque_lsa_config_write_router_callback (funclist, vty);
1120
1121 funclist = ospf_opaque_type11_funclist;
1122 opaque_lsa_config_write_router_callback (funclist, vty);
1123
1124 return;
1125}
1126
1127void
1128ospf_opaque_config_write_if (struct vty *vty, struct interface *ifp)
1129{
paul87d6f872004-09-24 08:01:38 +00001130 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001131
paul09e4efd2003-01-18 00:12:02 +00001132 funclist = ospf_opaque_wildcard_funclist;
1133 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1134
paul718e3742002-12-13 20:15:29 +00001135 funclist = ospf_opaque_type9_funclist;
1136 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1137
1138 funclist = ospf_opaque_type10_funclist;
1139 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1140
1141 funclist = ospf_opaque_type11_funclist;
1142 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1143
1144 return;
1145}
1146
1147void
1148ospf_opaque_config_write_debug (struct vty *vty)
1149{
paul87d6f872004-09-24 08:01:38 +00001150 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001151
paul09e4efd2003-01-18 00:12:02 +00001152 funclist = ospf_opaque_wildcard_funclist;
1153 opaque_lsa_config_write_debug_callback (funclist, vty);
1154
paul718e3742002-12-13 20:15:29 +00001155 funclist = ospf_opaque_type9_funclist;
1156 opaque_lsa_config_write_debug_callback (funclist, vty);
1157
1158 funclist = ospf_opaque_type10_funclist;
1159 opaque_lsa_config_write_debug_callback (funclist, vty);
1160
1161 funclist = ospf_opaque_type11_funclist;
1162 opaque_lsa_config_write_debug_callback (funclist, vty);
1163
1164 return;
1165}
1166
1167void
1168show_opaque_info_detail (struct vty *vty, struct ospf_lsa *lsa)
1169{
1170 struct lsa_header *lsah = (struct lsa_header *) lsa->data;
1171 u_int32_t lsid = ntohl (lsah->id.s_addr);
1172 u_char opaque_type = GET_OPAQUE_TYPE (lsid);
1173 u_int32_t opaque_id = GET_OPAQUE_ID (lsid);
1174 struct ospf_opaque_functab *functab;
1175
1176 /* Switch output functionality by vty address. */
1177 if (vty != NULL)
1178 {
paul020709f2003-04-04 02:44:16 +00001179 vty_out (vty, " Opaque-Type %u (%s)%s", opaque_type,
1180 ospf_opaque_type_name (opaque_type), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001181 vty_out (vty, " Opaque-ID 0x%x%s", opaque_id, VTY_NEWLINE);
1182
1183 vty_out (vty, " Opaque-Info: %u octets of data%s%s",
1184 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1185 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)",
1186 VTY_NEWLINE);
1187 }
1188 else
1189 {
paul020709f2003-04-04 02:44:16 +00001190 zlog_info (" Opaque-Type %u (%s)", opaque_type,
1191 ospf_opaque_type_name (opaque_type));
paul718e3742002-12-13 20:15:29 +00001192 zlog_info (" Opaque-ID 0x%x", opaque_id);
1193
1194 zlog_info (" Opaque-Info: %u octets of data%s",
1195 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1196 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)");
1197 }
1198
1199 /* Call individual output functions. */
1200 if ((functab = ospf_opaque_functab_lookup (lsa)) != NULL)
1201 if (functab->show_opaque_info != NULL)
1202 (* functab->show_opaque_info)(vty, lsa);
1203
1204 return;
1205}
1206
1207void
1208ospf_opaque_lsa_dump (struct stream *s, u_int16_t length)
1209{
1210 struct ospf_lsa lsa;
1211
1212 lsa.data = (struct lsa_header *) STREAM_PNT (s);
1213 show_opaque_info_detail (NULL, &lsa);
1214 return;
1215}
1216
1217static int
1218ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa)
1219{
paul87d6f872004-09-24 08:01:38 +00001220 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001221 int rc = -1;
1222
1223 /*
1224 * Some Opaque-LSA user may want to monitor every LSA installation
1225 * into the LSDB, regardless with target LSA type.
1226 */
paul09e4efd2003-01-18 00:12:02 +00001227 funclist = ospf_opaque_wildcard_funclist;
1228 if (new_lsa_callback (funclist, lsa) != 0)
1229 goto out;
1230
paul718e3742002-12-13 20:15:29 +00001231 funclist = ospf_opaque_type9_funclist;
1232 if (new_lsa_callback (funclist, lsa) != 0)
1233 goto out;
1234
1235 funclist = ospf_opaque_type10_funclist;
1236 if (new_lsa_callback (funclist, lsa) != 0)
1237 goto out;
1238
1239 funclist = ospf_opaque_type11_funclist;
1240 if (new_lsa_callback (funclist, lsa) != 0)
1241 goto out;
1242
1243 rc = 0;
1244out:
1245 return rc;
1246}
1247
1248static int
1249ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa)
1250{
paul87d6f872004-09-24 08:01:38 +00001251 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001252 int rc = -1;
1253
1254 /*
1255 * Some Opaque-LSA user may want to monitor every LSA deletion
1256 * from the LSDB, regardless with target LSA type.
1257 */
paul09e4efd2003-01-18 00:12:02 +00001258 funclist = ospf_opaque_wildcard_funclist;
1259 if (del_lsa_callback (funclist, lsa) != 0)
1260 goto out;
1261
paul718e3742002-12-13 20:15:29 +00001262 funclist = ospf_opaque_type9_funclist;
1263 if (del_lsa_callback (funclist, lsa) != 0)
1264 goto out;
1265
1266 funclist = ospf_opaque_type10_funclist;
1267 if (del_lsa_callback (funclist, lsa) != 0)
1268 goto out;
1269
1270 funclist = ospf_opaque_type11_funclist;
1271 if (del_lsa_callback (funclist, lsa) != 0)
1272 goto out;
1273
1274 rc = 0;
1275out:
1276 return rc;
1277}
1278
1279/*------------------------------------------------------------------------*
1280 * Followings are Opaque-LSA origination/refresh management functions.
1281 *------------------------------------------------------------------------*/
1282
1283static int ospf_opaque_type9_lsa_originate (struct thread *t);
1284static int ospf_opaque_type10_lsa_originate (struct thread *t);
1285static int ospf_opaque_type11_lsa_originate (struct thread *t);
paul87d6f872004-09-24 08:01:38 +00001286static void ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg);
paul718e3742002-12-13 20:15:29 +00001287
1288void
1289ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0)
1290{
1291 struct ospf *top;
1292 struct ospf_area *area;
paul87d6f872004-09-24 08:01:38 +00001293 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001294 struct opaque_info_per_type *oipt;
1295 int delay = 0;
1296
1297 if ((top = oi_to_top (oi)) == NULL || (area = oi->area) == NULL)
1298 {
1299 zlog_warn ("ospf_opaque_lsa_originate_schedule: Invalid argument?");
1300 goto out;
1301 }
1302
1303 /* It may not a right time to schedule origination now. */
1304 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1305 {
1306 if (IS_DEBUG_OSPF_EVENT)
1307 zlog_info ("ospf_opaque_lsa_originate_schedule: Not operational.");
1308 goto out; /* This is not an error. */
1309 }
1310 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
1311 {
1312 if (IS_DEBUG_OSPF_EVENT)
1313 zlog_info ("ospf_opaque_lsa_originate_schedule: Under blockade.");
1314 goto out; /* This is not an error, too. */
1315 }
1316
1317 if (delay0 != NULL)
1318 delay = *delay0;
1319
1320 /*
1321 * There might be some entries that have been waiting for triggering
1322 * of per opaque-type re-origination get resumed.
1323 */
1324 ospf_opaque_lsa_reoriginate_resume ( oi->opaque_lsa_self, (void *) oi);
1325 ospf_opaque_lsa_reoriginate_resume (area->opaque_lsa_self, (void *) area);
1326 ospf_opaque_lsa_reoriginate_resume ( top->opaque_lsa_self, (void *) top);
1327
1328 /*
1329 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1330 */
1331 if (! list_isempty (ospf_opaque_type9_funclist)
1332 && list_isempty (oi->opaque_lsa_self)
1333 && oi->t_opaque_lsa_self == NULL)
1334 {
1335 if (IS_DEBUG_OSPF_EVENT)
1336 zlog_info ("Schedule Type-9 Opaque-LSA origination in %d sec later.", delay);
1337 oi->t_opaque_lsa_self =
1338 thread_add_timer (master, ospf_opaque_type9_lsa_originate, oi, delay);
1339 delay += OSPF_MIN_LS_INTERVAL;
1340 }
1341
1342 if (! list_isempty (ospf_opaque_type10_funclist)
1343 && list_isempty (area->opaque_lsa_self)
1344 && area->t_opaque_lsa_self == NULL)
1345 {
1346 /*
1347 * One AREA may contain multiple OIs, but above 2nd and 3rd
1348 * conditions prevent from scheduling the originate function
1349 * again and again.
1350 */
1351 if (IS_DEBUG_OSPF_EVENT)
1352 zlog_info ("Schedule Type-10 Opaque-LSA origination in %d sec later.", delay);
1353 area->t_opaque_lsa_self =
1354 thread_add_timer (master, ospf_opaque_type10_lsa_originate,
1355 area, delay);
1356 delay += OSPF_MIN_LS_INTERVAL;
1357 }
1358
1359 if (! list_isempty (ospf_opaque_type11_funclist)
1360 && list_isempty (top->opaque_lsa_self)
1361 && top->t_opaque_lsa_self == NULL)
1362 {
1363 /*
1364 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1365 * conditions prevent from scheduling the originate function
1366 * again and again.
1367 */
1368 if (IS_DEBUG_OSPF_EVENT)
1369 zlog_info ("Schedule Type-11 Opaque-LSA origination in %d sec later.", delay);
1370 top->t_opaque_lsa_self =
1371 thread_add_timer (master, ospf_opaque_type11_lsa_originate,
1372 top, delay);
1373 delay += OSPF_MIN_LS_INTERVAL;
1374 }
1375
1376 /*
1377 * Following section treats a special situation that this node's
1378 * opaque capability has changed as "ON -> OFF -> ON".
1379 */
1380 if (! list_isempty (ospf_opaque_type9_funclist)
1381 && ! list_isempty (oi->opaque_lsa_self))
1382 {
1383 for (node = listhead (oi->opaque_lsa_self); node; nextnode (node))
1384 {
hasso0d85b992004-03-18 19:18:33 +00001385 /*
1386 * removed the test for
1387 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1388 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1389 * not being empty.
1390 */
paul718e3742002-12-13 20:15:29 +00001391 if ((oipt = getdata (node)) == NULL /* Something wrong? */
1392 || oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
hasso0d85b992004-03-18 19:18:33 +00001393 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001394 continue;
1395
1396 ospf_opaque_lsa_reoriginate_schedule ((void *) oi,
1397 OSPF_OPAQUE_LINK_LSA, oipt->opaque_type);
1398 }
1399 }
1400
1401 if (! list_isempty (ospf_opaque_type10_funclist)
1402 && ! list_isempty (area->opaque_lsa_self))
1403 {
1404 for (node = listhead (area->opaque_lsa_self); node; nextnode (node))
1405 {
hasso0d85b992004-03-18 19:18:33 +00001406 /*
1407 * removed the test for
1408 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1409 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1410 * not being empty.
1411 */
paul718e3742002-12-13 20:15:29 +00001412 if ((oipt = getdata (node)) == NULL /* Something wrong? */
1413 || oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
hasso0d85b992004-03-18 19:18:33 +00001414 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001415 continue;
1416
1417 ospf_opaque_lsa_reoriginate_schedule ((void *) area,
1418 OSPF_OPAQUE_AREA_LSA, oipt->opaque_type);
1419 }
1420 }
1421
1422 if (! list_isempty (ospf_opaque_type11_funclist)
1423 && ! list_isempty (top->opaque_lsa_self))
1424 {
1425 for (node = listhead (top->opaque_lsa_self); node; nextnode (node))
1426 {
hasso0d85b992004-03-18 19:18:33 +00001427 /*
1428 * removed the test for
1429 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1430 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1431 * not being empty.
1432 */
paul718e3742002-12-13 20:15:29 +00001433 if ((oipt = getdata (node)) == NULL /* Something wrong? */
1434 || oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
hasso0d85b992004-03-18 19:18:33 +00001435 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001436 continue;
1437
1438 ospf_opaque_lsa_reoriginate_schedule ((void *) top,
1439 OSPF_OPAQUE_AS_LSA, oipt->opaque_type);
1440 }
1441 }
1442
1443 if (delay0 != NULL)
1444 *delay0 = delay;
1445
1446out:
1447 return;
1448}
1449
1450static int
1451ospf_opaque_type9_lsa_originate (struct thread *t)
1452{
1453 struct ospf_interface *oi;
1454 int rc;
1455
1456 oi = THREAD_ARG (t);
1457 oi->t_opaque_lsa_self = NULL;
1458
1459 if (IS_DEBUG_OSPF_EVENT)
1460 zlog_info ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
1461 IF_NAME (oi));
1462
1463 rc = opaque_lsa_originate_callback (ospf_opaque_type9_funclist, oi);
1464
1465 return rc;
1466}
1467
1468static int
1469ospf_opaque_type10_lsa_originate (struct thread *t)
1470{
1471 struct ospf_area *area;
1472 int rc;
1473
1474 area = THREAD_ARG (t);
1475 area->t_opaque_lsa_self = NULL;
1476
1477 if (IS_DEBUG_OSPF_EVENT)
1478 zlog_info ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
1479 inet_ntoa (area->area_id));
1480
1481 rc = opaque_lsa_originate_callback (ospf_opaque_type10_funclist, area);
1482
1483 return rc;
1484}
1485
1486static int
1487ospf_opaque_type11_lsa_originate (struct thread *t)
1488{
1489 struct ospf *top;
1490 int rc;
1491
1492 top = THREAD_ARG (t);
1493 top->t_opaque_lsa_self = NULL;
1494
1495 if (IS_DEBUG_OSPF_EVENT)
1496 zlog_info ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
1497
1498 rc = opaque_lsa_originate_callback (ospf_opaque_type11_funclist, top);
1499
1500 return rc;
1501}
1502
1503static void
paul87d6f872004-09-24 08:01:38 +00001504ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg)
paul718e3742002-12-13 20:15:29 +00001505{
paul87d6f872004-09-24 08:01:38 +00001506 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001507 struct opaque_info_per_type *oipt;
1508 struct ospf_opaque_functab *functab;
1509
1510 if (listtop == NULL)
1511 goto out;
1512
1513 /*
1514 * Pickup oipt entries those which in SUSPEND status, and give
1515 * them a chance to start re-origination now.
1516 */
paul87d6f872004-09-24 08:01:38 +00001517 LIST_LOOP (listtop, oipt, node)
paul718e3742002-12-13 20:15:29 +00001518 {
paul87d6f872004-09-24 08:01:38 +00001519 if (oipt->status != PROC_SUSPEND)
paul718e3742002-12-13 20:15:29 +00001520 continue;
1521
1522 oipt->status = PROC_NORMAL;
1523
1524 if ((functab = oipt->functab) == NULL
paul87d6f872004-09-24 08:01:38 +00001525 || functab->lsa_originator == NULL)
paul718e3742002-12-13 20:15:29 +00001526 continue;
1527
1528 if ((* functab->lsa_originator)(arg) != 0)
1529 {
1530 zlog_warn ("ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", oipt->opaque_type);
1531 continue;
1532 }
1533 }
1534
1535out:
1536 return;
1537}
1538
1539struct ospf_lsa *
1540ospf_opaque_lsa_install (struct ospf_lsa *lsa, int rt_recalc)
1541{
1542 struct ospf_lsa *new = NULL;
1543 struct opaque_info_per_type *oipt;
1544 struct opaque_info_per_id *oipi;
1545 struct ospf *top;
1546
1547 /* Don't take "rt_recalc" into consideration for now. *//* XXX */
1548
1549 if (! IS_LSA_SELF (lsa))
1550 {
1551 new = lsa; /* Don't touch this LSA. */
1552 goto out;
1553 }
1554
1555 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
1556 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)));
1557
1558 /* Replace the existing lsa with the new one. */
1559 if ((oipt = lookup_opaque_info_by_type (lsa)) != NULL
paul87d6f872004-09-24 08:01:38 +00001560 && (oipi = lookup_opaque_info_by_id (oipt, lsa)) != NULL)
paul718e3742002-12-13 20:15:29 +00001561 {
1562 ospf_lsa_unlock (oipi->lsa);
1563 oipi->lsa = ospf_lsa_lock (lsa);
1564 }
1565 /* Register the new lsa entry and get its control info. */
1566 else
1567 if ((oipi = register_opaque_lsa (lsa)) == NULL)
1568 {
1569 zlog_warn ("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1570 goto out;
1571 }
1572
1573 /*
1574 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1575 * for periodic refresh of self-originated Opaque-LSAs.
1576 */
1577 switch (lsa->data->type)
1578 {
1579 case OSPF_OPAQUE_LINK_LSA:
paul09e4efd2003-01-18 00:12:02 +00001580 if ((top = oi_to_top (lsa->oi)) == NULL)
1581 {
1582 /* Above conditions must have passed. */
1583 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1584 goto out;
1585 }
1586 break;
paul718e3742002-12-13 20:15:29 +00001587 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00001588 if (lsa->area == NULL || (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001589 {
1590 /* Above conditions must have passed. */
1591 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1592 goto out;
1593 }
1594 break;
1595 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +00001596 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001597 if (lsa->area != NULL && (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001598 {
1599 /* Above conditions must have passed. */
1600 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1601 goto out;
1602 }
1603 break;
1604 default:
1605 zlog_warn ("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", lsa->data->type);
1606 goto out;
1607 }
1608
1609 ospf_refresher_register_lsa (top, lsa);
1610 new = lsa;
1611
1612out:
1613 return new;
1614}
1615
1616void
1617ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
1618{
paul020709f2003-04-04 02:44:16 +00001619 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001620 struct ospf_opaque_functab *functab;
1621
paul020709f2003-04-04 02:44:16 +00001622 ospf = ospf_lookup ();
1623
paul718e3742002-12-13 20:15:29 +00001624 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL
paul87d6f872004-09-24 08:01:38 +00001625 || functab->lsa_refresher == NULL)
paul718e3742002-12-13 20:15:29 +00001626 {
1627 /*
1628 * Though this LSA seems to have originated on this node, the
1629 * handling module for this "lsa-type and opaque-type" was
1630 * already deleted sometime ago.
1631 * Anyway, this node still has a responsibility to flush this
1632 * LSA from the routing domain.
1633 */
1634 if (IS_DEBUG_OSPF_EVENT)
1635 zlog_info ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id));
1636
1637 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
paul68980082003-03-25 05:07:42 +00001638 ospf_lsa_maxage (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00001639 }
1640 else
1641 (* functab->lsa_refresher)(lsa);
1642
1643 return;
1644}
1645
1646/*------------------------------------------------------------------------*
1647 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1648 * triggered by external interventions (vty session, signaling, etc).
1649 *------------------------------------------------------------------------*/
1650
1651#define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
1652 if (!(T)) \
1653 (T) = thread_add_timer (master, (F), (L), (V))
1654
1655static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type);
1656static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t);
1657static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t);
1658static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t);
1659static int ospf_opaque_lsa_refresh_timer (struct thread *t);
1660
1661void
1662ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
1663 u_char lsa_type, u_char opaque_type)
1664{
1665 struct ospf *top;
1666 struct ospf_area dummy, *area = NULL;
1667 struct ospf_interface *oi = NULL;
1668
1669 struct ospf_lsa *lsa;
1670 struct opaque_info_per_type *oipt;
paul87d6f872004-09-24 08:01:38 +00001671 int (*func) (struct thread * t) = NULL;
paul718e3742002-12-13 20:15:29 +00001672 int delay;
1673
1674 switch (lsa_type)
1675 {
1676 case OSPF_OPAQUE_LINK_LSA:
1677 if ((oi = (struct ospf_interface *) lsa_type_dependent) == NULL)
1678 {
paul87d6f872004-09-24 08:01:38 +00001679 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1680 " Type-9 Opaque-LSA: Invalid parameter?");
1681 goto out;
paul718e3742002-12-13 20:15:29 +00001682 }
1683 if ((top = oi_to_top (oi)) == NULL)
1684 {
paul87d6f872004-09-24 08:01:38 +00001685 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1686 IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001687 goto out;
1688 }
paul87d6f872004-09-24 08:01:38 +00001689 if (!list_isempty (ospf_opaque_type9_funclist)
1690 && list_isempty (oi->opaque_lsa_self)
1691 && oi->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001692 {
paul87d6f872004-09-24 08:01:38 +00001693 zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u):"
1694 " Common origination for OI(%s) has already started",
1695 opaque_type, IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001696 goto out;
1697 }
1698 func = ospf_opaque_type9_lsa_reoriginate_timer;
1699 break;
1700 case OSPF_OPAQUE_AREA_LSA:
1701 if ((area = (struct ospf_area *) lsa_type_dependent) == NULL)
1702 {
paul87d6f872004-09-24 08:01:38 +00001703 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1704 " Type-10 Opaque-LSA: Invalid parameter?");
paul718e3742002-12-13 20:15:29 +00001705 goto out;
1706 }
paul68980082003-03-25 05:07:42 +00001707 if ((top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001708 {
paul87d6f872004-09-24 08:01:38 +00001709 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1710 " AREA(%s) -> TOP?", inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001711 goto out;
1712 }
paul87d6f872004-09-24 08:01:38 +00001713 if (!list_isempty (ospf_opaque_type10_funclist)
1714 && list_isempty (area->opaque_lsa_self)
1715 && area->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001716 {
paul87d6f872004-09-24 08:01:38 +00001717 zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u):"
1718 " Common origination for AREA(%s) has already started",
1719 opaque_type, inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001720 goto out;
1721 }
1722 func = ospf_opaque_type10_lsa_reoriginate_timer;
1723 break;
1724 case OSPF_OPAQUE_AS_LSA:
1725 if ((top = (struct ospf *) lsa_type_dependent) == NULL)
1726 {
paul87d6f872004-09-24 08:01:38 +00001727 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1728 " Type-11 Opaque-LSA: Invalid parameter?");
1729 goto out;
paul718e3742002-12-13 20:15:29 +00001730 }
paul87d6f872004-09-24 08:01:38 +00001731 if (!list_isempty (ospf_opaque_type11_funclist)
1732 && list_isempty (top->opaque_lsa_self)
1733 && top->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001734 {
paul87d6f872004-09-24 08:01:38 +00001735 zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u):"
1736 " Common origination has already started", opaque_type);
paul718e3742002-12-13 20:15:29 +00001737 goto out;
1738 }
1739
1740 /* Fake "area" to pass "ospf" to a lookup function later. */
paul68980082003-03-25 05:07:42 +00001741 dummy.ospf = top;
paul718e3742002-12-13 20:15:29 +00001742 area = &dummy;
1743
1744 func = ospf_opaque_type11_lsa_reoriginate_timer;
1745 break;
1746 default:
paul87d6f872004-09-24 08:01:38 +00001747 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1748 " Unexpected LSA-type(%u)",
1749 lsa_type);
paul718e3742002-12-13 20:15:29 +00001750 goto out;
1751 }
1752
1753 /* It may not a right time to schedule reorigination now. */
paul87d6f872004-09-24 08:01:38 +00001754 if (!CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
paul718e3742002-12-13 20:15:29 +00001755 {
1756 if (IS_DEBUG_OSPF_EVENT)
1757 zlog_info ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
paul87d6f872004-09-24 08:01:38 +00001758 goto out; /* This is not an error. */
paul718e3742002-12-13 20:15:29 +00001759 }
1760 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
1761 {
1762 if (IS_DEBUG_OSPF_EVENT)
1763 zlog_info ("ospf_opaque_lsa_reoriginate_schedule: Under blockade.");
paul87d6f872004-09-24 08:01:38 +00001764 goto out; /* This is not an error, too. */
paul718e3742002-12-13 20:15:29 +00001765 }
1766
1767 /* Generate a dummy lsa to be passed for a lookup function. */
1768 lsa = pseudo_lsa (oi, area, lsa_type, opaque_type);
1769
1770 if ((oipt = lookup_opaque_info_by_type (lsa)) == NULL)
1771 {
1772 struct ospf_opaque_functab *functab;
1773 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL)
1774 {
paul87d6f872004-09-24 08:01:38 +00001775 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1776 " No associated function?: lsa_type(%u),"
1777 " opaque_type(%u)",
1778 lsa_type, opaque_type);
paul718e3742002-12-13 20:15:29 +00001779 goto out;
1780 }
1781 if ((oipt = register_opaque_info_per_type (functab, lsa)) == NULL)
1782 {
paul87d6f872004-09-24 08:01:38 +00001783 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1784 " Cannot get a control info?: lsa_type(%u),"
1785 " opaque_type(%u)",
1786 lsa_type, opaque_type);
paul718e3742002-12-13 20:15:29 +00001787 goto out;
1788 }
1789 }
1790
1791 if (oipt->t_opaque_lsa_self != NULL)
1792 {
1793 if (IS_DEBUG_OSPF_EVENT)
paul87d6f872004-09-24 08:01:38 +00001794 zlog_info ("Type-%u Opaque-LSA has already scheduled to"
1795 " RE-ORIGINATE: [opaque-type=%u]",
1796 lsa_type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
paul718e3742002-12-13 20:15:29 +00001797 goto out;
1798 }
1799
1800 /*
1801 * Different from initial origination time, in which various conditions
1802 * (opaque capability, neighbor status etc) are assured by caller of
1803 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1804 * it is highly possible that these conditions might not be satisfied
1805 * at the time of re-origination function is to be called.
1806 */
1807 delay = OSPF_MIN_LS_INTERVAL; /* XXX */
1808
1809 if (IS_DEBUG_OSPF_EVENT)
paul87d6f872004-09-24 08:01:38 +00001810 zlog_info ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
1811 " sec later: [opaque-type=%u]",
1812 lsa_type, delay,
1813 GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
paul718e3742002-12-13 20:15:29 +00001814
1815 OSPF_OPAQUE_TIMER_ON (oipt->t_opaque_lsa_self, func, oipt, delay);
1816
1817out:
1818 return;
1819}
1820
1821static struct ospf_lsa *
1822pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area,
1823 u_char lsa_type, u_char opaque_type)
1824{
1825 static struct ospf_lsa lsa = { 0 };
1826 static struct lsa_header lsah = { 0 };
1827 u_int32_t tmp;
1828
1829 lsa.oi = oi;
1830 lsa.area = area;
1831 lsa.data = &lsah;
1832
1833 lsah.type = lsa_type;
1834 tmp = SET_OPAQUE_LSID (opaque_type, 0); /* Opaque-ID is unused here. */
1835 lsah.id.s_addr = htonl (tmp);
1836
1837 return &lsa;
1838}
1839
1840static int
1841ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t)
1842{
1843 struct opaque_info_per_type *oipt;
1844 struct ospf_opaque_functab *functab;
1845 struct ospf *top;
1846 struct ospf_interface *oi;
1847 int rc = -1;
1848
1849 oipt = THREAD_ARG (t);
1850 oipt->t_opaque_lsa_self = NULL;
1851
1852 if ((functab = oipt->functab) == NULL
1853 || functab->lsa_originator == NULL)
1854 {
1855 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1856 goto out;
1857 }
1858
1859 oi = (struct ospf_interface *) oipt->owner;
1860 if ((top = oi_to_top (oi)) == NULL)
1861 {
1862 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1863 goto out;
1864 }
1865
1866 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)
1867 || ! ospf_if_is_enable (oi)
paul68980082003-03-25 05:07:42 +00001868 || ospf_nbr_count_opaque_capable (oi) == 0)
paul718e3742002-12-13 20:15:29 +00001869 {
1870 if (IS_DEBUG_OSPF_EVENT)
1871 zlog_info ("Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
1872
1873 oipt->status = PROC_SUSPEND;
1874 rc = 0;
1875 goto out;
1876 }
1877
1878 if (IS_DEBUG_OSPF_EVENT)
1879 zlog_info ("Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)", oipt->opaque_type, IF_NAME (oi));
1880
1881 rc = (* functab->lsa_originator)(oi);
1882out:
1883 return rc;
1884}
1885
1886static int
1887ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t)
1888{
1889 struct opaque_info_per_type *oipt;
1890 struct ospf_opaque_functab *functab;
paul87d6f872004-09-24 08:01:38 +00001891 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001892 struct ospf *top;
1893 struct ospf_area *area;
1894 struct ospf_interface *oi;
1895 int n, rc = -1;
1896
1897 oipt = THREAD_ARG (t);
1898 oipt->t_opaque_lsa_self = NULL;
1899
1900 if ((functab = oipt->functab) == NULL
1901 || functab->lsa_originator == NULL)
1902 {
1903 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1904 goto out;
1905 }
1906
1907 area = (struct ospf_area *) oipt->owner;
paul68980082003-03-25 05:07:42 +00001908 if (area == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001909 {
1910 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1911 goto out;
1912 }
1913
1914 /* There must be at least one "opaque-capable, full-state" neighbor. */
1915 n = 0;
paul87d6f872004-09-24 08:01:38 +00001916 LIST_LOOP (area->oiflist, oi, node)
paul718e3742002-12-13 20:15:29 +00001917 {
paul68980082003-03-25 05:07:42 +00001918 if ((n = ospf_nbr_count_opaque_capable (oi)) > 0)
paul718e3742002-12-13 20:15:29 +00001919 break;
1920 }
1921
1922 if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1923 {
1924 if (IS_DEBUG_OSPF_EVENT)
paul87d6f872004-09-24 08:01:38 +00001925 zlog_info ("Suspend re-origination of Type-10 Opaque-LSAs"
1926 " (opaque-type=%u) for a while...",
1927 oipt->opaque_type);
paul718e3742002-12-13 20:15:29 +00001928
1929 oipt->status = PROC_SUSPEND;
1930 rc = 0;
1931 goto out;
1932 }
1933
1934 if (IS_DEBUG_OSPF_EVENT)
paul87d6f872004-09-24 08:01:38 +00001935 zlog_info ("Timer[Type10-LSA]: Re-originate Opaque-LSAs"
1936 " (opaque-type=%u) for Area %s",
1937 oipt->opaque_type, inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001938
1939 rc = (* functab->lsa_originator)(area);
1940out:
1941 return rc;
1942}
1943
1944static int
1945ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t)
1946{
1947 struct opaque_info_per_type *oipt;
1948 struct ospf_opaque_functab *functab;
1949 struct ospf *top;
1950 int rc = -1;
1951
1952 oipt = THREAD_ARG (t);
1953 oipt->t_opaque_lsa_self = NULL;
1954
1955 if ((functab = oipt->functab) == NULL
paul87d6f872004-09-24 08:01:38 +00001956 || functab->lsa_originator == NULL)
paul718e3742002-12-13 20:15:29 +00001957 {
paul87d6f872004-09-24 08:01:38 +00001958 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer:"
1959 " No associated function?");
paul718e3742002-12-13 20:15:29 +00001960 goto out;
1961 }
1962
1963 if ((top = (struct ospf *) oipt->owner) == NULL)
1964 {
1965 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1966 goto out;
1967 }
1968
1969 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1970 {
1971 if (IS_DEBUG_OSPF_EVENT)
1972 zlog_info ("Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
1973
1974 oipt->status = PROC_SUSPEND;
1975 rc = 0;
1976 goto out;
1977 }
1978
1979 if (IS_DEBUG_OSPF_EVENT)
1980 zlog_info ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type);
1981
1982 rc = (* functab->lsa_originator)(top);
1983out:
1984 return rc;
1985}
1986
1987extern int ospf_lsa_refresh_delay (struct ospf_lsa *); /* ospf_lsa.c */
1988
1989void
1990ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
1991{
paul020709f2003-04-04 02:44:16 +00001992 struct ospf *ospf = ospf;
paul718e3742002-12-13 20:15:29 +00001993 struct opaque_info_per_type *oipt;
1994 struct opaque_info_per_id *oipi;
1995 struct ospf_lsa *lsa;
1996 int delay;
1997
paul020709f2003-04-04 02:44:16 +00001998 ospf = ospf_lookup ();
1999
paul718e3742002-12-13 20:15:29 +00002000 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
2001 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
2002 {
2003 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
2004 goto out;
2005 }
2006
2007 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2008 if ((lsa = oipi->lsa) == NULL)
2009 {
2010 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
2011 goto out;
2012 }
2013
2014 if (oipi->t_opaque_lsa_self != NULL)
2015 {
2016 if (IS_DEBUG_OSPF_EVENT)
2017 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)));
2018 goto out;
2019 }
2020
2021 /* Delete this lsa from neighbor retransmit-list. */
2022 switch (lsa->data->type)
2023 {
2024 case OSPF_OPAQUE_LINK_LSA:
2025 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002026 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002027 break;
2028 case OSPF_OPAQUE_AS_LSA:
paul68980082003-03-25 05:07:42 +00002029 ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002030 break;
2031 default:
2032 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2033 goto out;
2034 }
2035
2036 delay = ospf_lsa_refresh_delay (lsa);
2037
2038 if (IS_DEBUG_OSPF_EVENT)
2039 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)));
2040
2041 OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self,
2042 ospf_opaque_lsa_refresh_timer, oipi, delay);
2043out:
2044 return;
2045}
2046
2047static int
2048ospf_opaque_lsa_refresh_timer (struct thread *t)
2049{
2050 struct opaque_info_per_id *oipi;
2051 struct ospf_opaque_functab *functab;
2052 struct ospf_lsa *lsa;
2053
2054 if (IS_DEBUG_OSPF_EVENT)
2055 zlog_info ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
2056
2057 oipi = THREAD_ARG (t);
2058 oipi->t_opaque_lsa_self = NULL;
2059
2060 if ((lsa = oipi->lsa) != NULL)
2061 if ((functab = oipi->opqctl_type->functab) != NULL)
2062 if (functab->lsa_refresher != NULL)
2063 (* functab->lsa_refresher)(lsa);
2064
2065 return 0;
2066}
2067
2068void
2069ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
2070{
paul020709f2003-04-04 02:44:16 +00002071 struct ospf *ospf = ospf;
paul718e3742002-12-13 20:15:29 +00002072 struct opaque_info_per_type *oipt;
2073 struct opaque_info_per_id *oipi;
2074 struct ospf_lsa *lsa;
2075
paul020709f2003-04-04 02:44:16 +00002076 ospf = ospf_lookup ();
2077
paul718e3742002-12-13 20:15:29 +00002078 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
2079 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
2080 {
2081 zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2082 goto out;
2083 }
2084
2085 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2086 if ((lsa = oipi->lsa) == NULL)
2087 {
2088 zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
2089 goto out;
2090 }
2091
2092 /* Delete this lsa from neighbor retransmit-list. */
2093 switch (lsa->data->type)
2094 {
2095 case OSPF_OPAQUE_LINK_LSA:
2096 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002097 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002098 break;
2099 case OSPF_OPAQUE_AS_LSA:
paul68980082003-03-25 05:07:42 +00002100 ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002101 break;
2102 default:
2103 zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2104 goto out;
2105 }
2106
2107 /* Dequeue listnode entry from the list. */
2108 listnode_delete (oipt->id_list, oipi);
2109
2110 /* Avoid misjudgement in the next lookup. */
2111 if (listcount (oipt->id_list) == 0)
2112 oipt->id_list->head = oipt->id_list->tail = NULL;
2113
2114 /* Disassociate internal control information with the given lsa. */
paul718e3742002-12-13 20:15:29 +00002115 free_opaque_info_per_id ((void *) oipi);
2116
2117 /* Force given lsa's age to MaxAge. */
2118 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2119
2120 if (IS_DEBUG_OSPF_EVENT)
2121 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)));
2122
2123 /* This lsa will be flushed and removed eventually. */
paul68980082003-03-25 05:07:42 +00002124 ospf_lsa_maxage (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002125
2126out:
2127 return;
2128}
2129
2130/*------------------------------------------------------------------------*
2131 * Followings are control functions to block origination after restart.
2132 *------------------------------------------------------------------------*/
2133
2134static void ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs, struct ospf_neighbor *inbr, struct ospf_lsa *lsa);
2135static void ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi);
2136static void ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area);
2137static void ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top);
2138static unsigned long ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type);
2139
2140void
paul87d6f872004-09-24 08:01:38 +00002141ospf_opaque_adjust_lsreq (struct ospf_neighbor *nbr, struct list *lsas)
paul718e3742002-12-13 20:15:29 +00002142{
2143 struct ospf *top;
2144 struct ospf_area *area;
2145 struct ospf_interface *oi;
paul87d6f872004-09-24 08:01:38 +00002146 struct listnode *node1, *node2;
paul718e3742002-12-13 20:15:29 +00002147 struct ospf_lsa *lsa;
2148
2149 if ((top = oi_to_top (nbr->oi)) == NULL)
2150 goto out;
2151
2152 /*
2153 * If an instance of self-originated Opaque-LSA is found in the given
2154 * LSA list, and it is not installed to LSDB yet, exclude it from the
2155 * list "nbr->ls_req". In this way, it is assured that an LSReq message,
2156 * which might be sent in the process of flooding, will not request for
2157 * the LSA to be flushed immediately; otherwise, depending on timing,
2158 * an LSUpd message will carry instances of target LSAs with MaxAge,
2159 * while other LSUpd message might carry old LSA instances (non-MaxAge).
2160 * Obviously, the latter would trigger miserable situations that repeat
2161 * installation and removal of unwanted LSAs indefinitely.
2162 */
2163 for (node1 = listhead (lsas); node1; nextnode (node1))
2164 {
2165 if ((lsa = getdata (node1)) == NULL)
2166 continue;
2167
2168 /* Filter out unwanted LSAs. */
2169 if (! IS_OPAQUE_LSA (lsa->data->type))
2170 continue;
2171 if (! IPV4_ADDR_SAME (&lsa->data->adv_router, &top->router_id))
2172 continue;
2173
2174 /*
2175 * Don't touch an LSA which has MaxAge; two possible cases.
2176 *
2177 * 1) This LSA has originally flushed by myself (received LSUpd
2178 * message's router-id is equal to my router-id), and flooded
2179 * back by an opaque-capable router.
2180 *
2181 * 2) This LSA has expired in an opaque-capable router and thus
2182 * flushed by the router.
2183 */
2184 if (IS_LSA_MAXAGE (lsa))
2185 continue;
2186
2187 /* If the LSA has installed in the LSDB, nothing to do here. */
2188 if (ospf_lsa_lookup_by_header (nbr->oi->area, lsa->data) != NULL)
2189 continue;
2190
2191 /* Ok, here we go. */
2192 switch (lsa->data->type)
2193 {
2194 case OSPF_OPAQUE_LINK_LSA:
2195 oi = nbr->oi;
2196 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2197 break;
2198 case OSPF_OPAQUE_AREA_LSA:
2199 area = nbr->oi->area;
2200 for (node2 = listhead (area->oiflist); node2; nextnode (node2))
2201 {
2202 if ((oi = getdata (node2)) == NULL)
2203 continue;
2204 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2205 }
2206 break;
2207 case OSPF_OPAQUE_AS_LSA:
2208 for (node2 = listhead (top->oiflist); node2; nextnode (node2))
2209 {
2210 if ((oi = getdata (node2)) == NULL)
2211 continue;
2212 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2213 }
2214 break;
2215 default:
2216 break;
2217 }
2218 }
2219
2220out:
2221 return;
2222}
2223
2224static void
2225ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs,
2226 struct ospf_neighbor *inbr,
2227 struct ospf_lsa *lsa)
2228{
2229 struct route_node *rn;
2230 struct ospf_neighbor *onbr;
2231 struct ospf_lsa *ls_req;
2232
2233 for (rn = route_top (nbrs); rn; rn = route_next (rn))
2234 {
2235 if ((onbr = rn->info) == NULL)
2236 continue;
2237 if (onbr == inbr)
2238 continue;
2239 if ((ls_req = ospf_ls_request_lookup (onbr, lsa)) == NULL)
2240 continue;
2241
2242 if (IS_DEBUG_OSPF_EVENT)
2243 zlog_info ("LSA[%s]: Exclude this entry from LSReq to send.", dump_lsa_key (lsa));
2244
2245 ospf_ls_request_delete (onbr, ls_req);
2246/* ospf_check_nbr_loading (onbr);*//* XXX */
2247 }
2248
2249 return;
2250}
2251
2252void
paul87d6f872004-09-24 08:01:38 +00002253ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr,
2254 struct list *lsas)
paul718e3742002-12-13 20:15:29 +00002255{
2256 struct ospf *top;
paul87d6f872004-09-24 08:01:38 +00002257 struct listnode *node, *next;
paul718e3742002-12-13 20:15:29 +00002258 struct ospf_lsa *lsa;
2259 u_char before;
2260
2261 if ((top = oi_to_top (nbr->oi)) == NULL)
2262 goto out;
2263
2264 before = IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque);
2265
2266 for (node = listhead (lsas); node; node = next)
2267 {
2268 next = node->next;
2269
2270 if ((lsa = getdata (node)) == NULL)
2271 continue;
2272
2273 listnode_delete (lsas, lsa);
2274
2275 /*
2276 * Since these LSA entries are not yet installed into corresponding
2277 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2278 */
2279 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2280 switch (lsa->data->type)
2281 {
2282 case OSPF_OPAQUE_LINK_LSA:
2283 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
2284 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2285 break;
2286 case OSPF_OPAQUE_AREA_LSA:
2287 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
2288 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2289 break;
2290 case OSPF_OPAQUE_AS_LSA:
2291 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
paul68980082003-03-25 05:07:42 +00002292 ospf_flood_through_as (top, NULL/*inbr*/, lsa);
paul718e3742002-12-13 20:15:29 +00002293 break;
2294 default:
2295 zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
2296 goto out;
2297 }
2298
2299 ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */
2300 }
2301
2302 if (before == 0 && IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2303 {
2304 if (IS_DEBUG_OSPF_EVENT)
2305 zlog_info ("Block Opaque-LSA origination: OFF -> ON");
2306 }
2307
2308out:
2309 return;
2310}
2311
2312void
paul87d6f872004-09-24 08:01:38 +00002313ospf_opaque_ls_ack_received (struct ospf_neighbor *nbr, struct list *acks)
paul718e3742002-12-13 20:15:29 +00002314{
2315 struct ospf *top;
paul87d6f872004-09-24 08:01:38 +00002316 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002317 struct ospf_lsa *lsa;
2318 char type9_lsa_rcv = 0, type10_lsa_rcv = 0, type11_lsa_rcv = 0;
2319
2320 if ((top = oi_to_top (nbr->oi)) == NULL)
2321 goto out;
2322
paul87d6f872004-09-24 08:01:38 +00002323 LIST_LOOP (acks, lsa, node)
paul718e3742002-12-13 20:15:29 +00002324 {
paul718e3742002-12-13 20:15:29 +00002325 switch (lsa->data->type)
2326 {
2327 case OSPF_OPAQUE_LINK_LSA:
2328 type9_lsa_rcv = 1;
2329 /* Callback function... */
2330 break;
2331 case OSPF_OPAQUE_AREA_LSA:
2332 type10_lsa_rcv = 1;
2333 /* Callback function... */
2334 break;
2335 case OSPF_OPAQUE_AS_LSA:
2336 type11_lsa_rcv = 1;
2337 /* Callback function... */
2338 break;
2339 default:
2340 zlog_warn ("ospf_opaque_ls_ack_received: Unexpected LSA-type(%u)", lsa->data->type);
2341 goto out;
2342 }
2343 }
2344
2345 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2346 {
2347 int delay;
2348 struct ospf_interface *oi;
2349
2350 if (type9_lsa_rcv
2351 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT))
2352 ospf_opaque_type9_lsa_rxmt_nbr_check (nbr->oi);
2353
2354 if (type10_lsa_rcv
2355 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT))
2356 ospf_opaque_type10_lsa_rxmt_nbr_check (nbr->oi->area);
2357
2358 if (type11_lsa_rcv
2359 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT))
2360 ospf_opaque_type11_lsa_rxmt_nbr_check (top);
2361
2362 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2363 goto out; /* Blocking still in progress. */
2364
2365 if (IS_DEBUG_OSPF_EVENT)
2366 zlog_info ("Block Opaque-LSA origination: ON -> OFF");
2367
2368 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
2369 goto out; /* Opaque capability condition must have changed. */
2370
2371 /* Ok, let's start origination of Opaque-LSAs. */
2372 delay = OSPF_MIN_LS_INTERVAL;
paul718e3742002-12-13 20:15:29 +00002373
paul87d6f872004-09-24 08:01:38 +00002374 LIST_LOOP (top->oiflist, oi, node)
2375 {
paul718e3742002-12-13 20:15:29 +00002376 if (! ospf_if_is_enable (oi)
paul87d6f872004-09-24 08:01:38 +00002377 || ospf_nbr_count_opaque_capable (oi) == 0)
paul718e3742002-12-13 20:15:29 +00002378 continue;
2379
2380 ospf_opaque_lsa_originate_schedule (oi, &delay);
2381 }
2382 }
2383
2384out:
2385 return;
2386}
2387
2388static void
2389ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi)
2390{
2391 unsigned long n;
2392
2393 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_LINK_LSA);
2394 if (n == 0)
2395 {
2396 if (IS_DEBUG_OSPF_EVENT)
2397 zlog_info ("Self-originated type-9 Opaque-LSAs: OI(%s): Flush completed", IF_NAME (oi));
2398
paul68980082003-03-25 05:07:42 +00002399 UNSET_FLAG (oi->area->ospf->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
paul718e3742002-12-13 20:15:29 +00002400 }
2401 return;
2402}
2403
2404static void
2405ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area)
2406{
paul87d6f872004-09-24 08:01:38 +00002407 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002408 struct ospf_interface *oi;
2409 unsigned long n = 0;
2410
2411 for (node = listhead (area->oiflist); node; nextnode (node))
2412 {
2413 if ((oi = getdata (node)) == NULL)
2414 continue;
2415
2416 if (area->area_id.s_addr != OSPF_AREA_BACKBONE
2417 && oi->type == OSPF_IFTYPE_VIRTUALLINK)
2418 continue;
2419
2420 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AREA_LSA);
2421 if (n > 0)
2422 break;
2423 }
2424
2425 if (n == 0)
2426 {
2427 if (IS_DEBUG_OSPF_EVENT)
2428 zlog_info ("Self-originated type-10 Opaque-LSAs: AREA(%s): Flush completed", inet_ntoa (area->area_id));
2429
paul68980082003-03-25 05:07:42 +00002430 UNSET_FLAG (area->ospf->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
paul718e3742002-12-13 20:15:29 +00002431 }
2432
2433 return;
2434}
2435
2436static void
2437ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top)
2438{
paul87d6f872004-09-24 08:01:38 +00002439 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002440 struct ospf_interface *oi;
2441 unsigned long n = 0;
2442
2443 for (node = listhead (top->oiflist); node; nextnode (node))
2444 {
2445 if ((oi = getdata (node)) == NULL)
2446 continue;
2447
2448 switch (oi->type)
2449 {
2450 case OSPF_IFTYPE_VIRTUALLINK:
2451 continue;
2452 default:
2453 break;
2454 }
2455
2456 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AS_LSA);
2457 if (n > 0)
2458 goto out;
2459 }
2460
2461 if (n == 0)
2462 {
2463 if (IS_DEBUG_OSPF_EVENT)
2464 zlog_info ("Self-originated type-11 Opaque-LSAs: Flush completed");
2465
2466 UNSET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
2467 }
2468
2469out:
2470 return;
2471}
2472
2473static unsigned long
2474ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type)
2475{
2476 struct route_node *rn;
2477 struct ospf_neighbor *nbr;
2478 struct ospf *top;
2479 unsigned long n = 0;
2480
2481 for (rn = route_top (nbrs); rn; rn = route_next (rn))
2482 {
2483 if ((nbr = rn->info) == NULL)
2484 continue;
2485 if ((top = oi_to_top (nbr->oi)) == NULL)
2486 continue;
2487 if (IPV4_ADDR_SAME (&nbr->router_id, &top->router_id))
2488 continue;
2489 n += ospf_ls_retransmit_count_self (nbr, lsa_type);
2490 }
2491
2492 return n;
2493}
2494
2495/*------------------------------------------------------------------------*
2496 * Followings are util functions; probably be used by Opaque-LSAs only...
2497 *------------------------------------------------------------------------*/
2498
2499void
2500htonf (float *src, float *dst)
2501{
2502 u_int32_t lu1, lu2;
2503
2504 memcpy (&lu1, src, sizeof (u_int32_t));
2505 lu2 = htonl (lu1);
2506 memcpy (dst, &lu2, sizeof (u_int32_t));
2507 return;
2508}
2509
2510void
2511ntohf (float *src, float *dst)
2512{
2513 u_int32_t lu1, lu2;
2514
2515 memcpy (&lu1, src, sizeof (u_int32_t));
2516 lu2 = ntohl (lu1);
2517 memcpy (dst, &lu2, sizeof (u_int32_t));
2518 return;
2519}
2520
2521struct ospf *
2522oi_to_top (struct ospf_interface *oi)
2523{
2524 struct ospf *top = NULL;
2525 struct ospf_area *area;
2526
paul68980082003-03-25 05:07:42 +00002527 if (oi == NULL || (area = oi->area) == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00002528 zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");
2529
2530 return top;
2531}
2532
2533#endif /* HAVE_OPAQUE_LSA */