blob: 01a8e1ce1a302b092efaa5bf04e328d85bc14693 [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 {
paul87d6f872004-09-24 08:01:38 +0000374 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000375 struct ospf_opaque_functab *functab;
paul87d6f872004-09-24 08:01:38 +0000376
377 LIST_LOOP (funclist, functab, node)
378 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;
421 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000422 struct ospf_opaque_functab *functab;
423
424 if ((funclist = ospf_get_opaque_funclist (lsa_type)) != NULL)
425 for (node = listhead (funclist); node; nextnode (node))
426 {
427 if ((functab = getdata (node)) != NULL
paul87d6f872004-09-24 08:01:38 +0000428 && functab->opaque_type == opaque_type)
paul718e3742002-12-13 20:15:29 +0000429 {
430 /* Cleanup internal control information, if it still remains. */
431 if (functab->oipt != NULL)
432 free_opaque_info_per_type (functab->oipt);
433
434 /* Dequeue listnode entry from the list. */
435 listnode_delete (funclist, functab);
436
437 /* Avoid misjudgement in the next lookup. */
438 if (listcount (funclist) == 0)
439 funclist->head = funclist->tail = NULL;
440
441 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, functab);
paul87d6f872004-09-24 08:01:38 +0000442 break;
paul718e3742002-12-13 20:15:29 +0000443 }
444 }
paul87d6f872004-09-24 08:01:38 +0000445
paul718e3742002-12-13 20:15:29 +0000446 return;
447}
448
449static struct ospf_opaque_functab *
450ospf_opaque_functab_lookup (struct ospf_lsa *lsa)
451{
paul87d6f872004-09-24 08:01:38 +0000452 struct list *funclist;
453 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000454 struct ospf_opaque_functab *functab;
455 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
456
457 if ((funclist = ospf_get_opaque_funclist (lsa->data->type)) != NULL)
paul87d6f872004-09-24 08:01:38 +0000458 LIST_LOOP (funclist, functab, node)
459 if (functab->opaque_type == key)
460 return functab;
paul718e3742002-12-13 20:15:29 +0000461
462 return NULL;
463}
464
465/*------------------------------------------------------------------------*
466 * Followings are management functions for self-originated LSA entries.
467 *------------------------------------------------------------------------*/
468
469/*
470 * Opaque-LSA control information per opaque-type.
471 * Single Opaque-Type may have multiple instances; each of them will be
472 * identified by their opaque-id.
473 */
474struct opaque_info_per_type
475{
paul09e4efd2003-01-18 00:12:02 +0000476 u_char lsa_type;
paul718e3742002-12-13 20:15:29 +0000477 u_char opaque_type;
478
479 enum { PROC_NORMAL, PROC_SUSPEND } status;
480
481 /*
482 * Thread for (re-)origination scheduling for this opaque-type.
483 *
484 * Initial origination of Opaque-LSAs is controlled by generic
485 * Opaque-LSA handling module so that same opaque-type entries are
486 * called all at once when certain conditions are met.
487 * However, there might be cases that some Opaque-LSA clients need
488 * to (re-)originate their own Opaque-LSAs out-of-sync with others.
489 * This thread is prepared for that specific purpose.
490 */
491 struct thread *t_opaque_lsa_self;
492
493 /*
paul09e4efd2003-01-18 00:12:02 +0000494 * Backpointer to an "owner" which is LSA-type dependent.
paul718e3742002-12-13 20:15:29 +0000495 * type-9: struct ospf_interface
496 * type-10: struct ospf_area
497 * type-11: struct ospf
498 */
499 void *owner;
500
501 /* Collection of callback functions for this opaque-type. */
502 struct ospf_opaque_functab *functab;
503
504 /* List of Opaque-LSA control informations per opaque-id. */
paul87d6f872004-09-24 08:01:38 +0000505 struct list *id_list;
paul718e3742002-12-13 20:15:29 +0000506};
507
508/* Opaque-LSA control information per opaque-id. */
509struct opaque_info_per_id
510{
511 u_int32_t opaque_id;
512
513 /* Thread for refresh/flush scheduling for this opaque-type/id. */
514 struct thread *t_opaque_lsa_self;
515
516 /* Backpointer to Opaque-LSA control information per opaque-type. */
517 struct opaque_info_per_type *opqctl_type;
518
519 /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
520 struct ospf_lsa *lsa;
521};
522
523static struct opaque_info_per_type *register_opaque_info_per_type (struct ospf_opaque_functab *functab, struct ospf_lsa *new);
524static struct opaque_info_per_type *lookup_opaque_info_by_type (struct ospf_lsa *lsa);
525static struct opaque_info_per_id *register_opaque_info_per_id (struct opaque_info_per_type *oipt, struct ospf_lsa *new);
526static struct opaque_info_per_id *lookup_opaque_info_by_id (struct opaque_info_per_type *oipt, struct ospf_lsa *lsa);
527static struct opaque_info_per_id *register_opaque_lsa (struct ospf_lsa *new);
528
529
530static struct opaque_info_per_type *
531register_opaque_info_per_type (struct ospf_opaque_functab *functab,
532 struct ospf_lsa *new)
533{
534 struct ospf *top;
535 struct opaque_info_per_type *oipt;
536
537 if ((oipt = XCALLOC (MTYPE_OPAQUE_INFO_PER_TYPE,
538 sizeof (struct opaque_info_per_type))) == NULL)
539 {
ajs6099b3b2004-11-20 02:06:59 +0000540 zlog_warn ("register_opaque_info_per_type: XMALLOC: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000541 goto out;
542 }
543
544 switch (new->data->type)
545 {
546 case OSPF_OPAQUE_LINK_LSA:
547 oipt->owner = new->oi;
548 listnode_add (new->oi->opaque_lsa_self, oipt);
549 break;
550 case OSPF_OPAQUE_AREA_LSA:
551 oipt->owner = new->area;
552 listnode_add (new->area->opaque_lsa_self, oipt);
553 break;
554 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +0000555 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000556 if (new->area != NULL && (top = new->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +0000557 {
558 free_opaque_info_per_type ((void *) oipt);
559 oipt = NULL;
560 goto out; /* This case may not exist. */
561 }
562 oipt->owner = top;
563 listnode_add (top->opaque_lsa_self, oipt);
564 break;
565 default:
paul09e4efd2003-01-18 00:12:02 +0000566 zlog_warn ("register_opaque_info_per_type: Unexpected LSA-type(%u)", new->data->type);
paul718e3742002-12-13 20:15:29 +0000567 free_opaque_info_per_type ((void *) oipt);
568 oipt = NULL;
569 goto out; /* This case may not exist. */
570 }
571
paul09e4efd2003-01-18 00:12:02 +0000572 oipt->lsa_type = new->data->type;
paul718e3742002-12-13 20:15:29 +0000573 oipt->opaque_type = GET_OPAQUE_TYPE (ntohl (new->data->id.s_addr));
574 oipt->status = PROC_NORMAL;
575 oipt->t_opaque_lsa_self = NULL;
576 oipt->functab = functab;
577 functab->oipt = oipt;
578 oipt->id_list = list_new ();
579 oipt->id_list->del = free_opaque_info_per_id;
580
581out:
582 return oipt;
583}
584
585static void
586free_opaque_info_per_type (void *val)
587{
588 struct opaque_info_per_type *oipt = (struct opaque_info_per_type *) val;
589 struct opaque_info_per_id *oipi;
590 struct ospf_lsa *lsa;
paul87d6f872004-09-24 08:01:38 +0000591 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000592
593 /* Control information per opaque-id may still exist. */
594 for (node = listhead (oipt->id_list); node; nextnode (node))
595 {
596 if ((oipi = getdata (node)) == NULL)
597 continue;
598 if ((lsa = oipi->lsa) == NULL)
599 continue;
600 if (IS_LSA_MAXAGE (lsa))
601 continue;
602 ospf_opaque_lsa_flush_schedule (lsa);
603 }
604
paul09e4efd2003-01-18 00:12:02 +0000605 /* Remove "oipt" from its owner's self-originated LSA list. */
606 switch (oipt->lsa_type)
607 {
608 case OSPF_OPAQUE_LINK_LSA:
609 {
610 struct ospf_interface *oi = (struct ospf_interface *)(oipt->owner);
611 listnode_delete (oi->opaque_lsa_self, oipt);
612 break;
613 }
614 case OSPF_OPAQUE_AREA_LSA:
615 {
616 struct ospf_area *area = (struct ospf_area *)(oipt->owner);
617 listnode_delete (area->opaque_lsa_self, oipt);
618 break;
619 }
620 case OSPF_OPAQUE_AS_LSA:
621 {
622 struct ospf *top = (struct ospf *)(oipt->owner);
623 listnode_delete (top->opaque_lsa_self, oipt);
624 break;
625 }
626 default:
627 zlog_warn ("free_opaque_info_per_type: Unexpected LSA-type(%u)", oipt->lsa_type);
628 break; /* This case may not exist. */
629 }
630
paul718e3742002-12-13 20:15:29 +0000631 OSPF_TIMER_OFF (oipt->t_opaque_lsa_self);
632 list_delete (oipt->id_list);
633 XFREE (MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
634 return;
635}
636
637static struct opaque_info_per_type *
638lookup_opaque_info_by_type (struct ospf_lsa *lsa)
639{
640 struct ospf *top;
641 struct ospf_area *area;
642 struct ospf_interface *oi;
paul87d6f872004-09-24 08:01:38 +0000643 struct list *listtop = NULL;
644 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000645 struct opaque_info_per_type *oipt = NULL;
646 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
647
648 switch (lsa->data->type)
649 {
650 case OSPF_OPAQUE_LINK_LSA:
651 if ((oi = lsa->oi) != NULL)
652 listtop = oi->opaque_lsa_self;
653 else
654 zlog_warn ("Type-9 Opaque-LSA: Reference to OI is missing?");
655 break;
656 case OSPF_OPAQUE_AREA_LSA:
657 if ((area = lsa->area) != NULL)
658 listtop = area->opaque_lsa_self;
659 else
660 zlog_warn ("Type-10 Opaque-LSA: Reference to AREA is missing?");
661 break;
662 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +0000663 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000664 if ((area = lsa->area) != NULL && (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +0000665 {
666 zlog_warn ("Type-11 Opaque-LSA: Reference to OSPF is missing?");
667 break; /* Unlikely to happen. */
668 }
669 listtop = top->opaque_lsa_self;
670 break;
671 default:
672 zlog_warn ("lookup_opaque_info_by_type: Unexpected LSA-type(%u)", lsa->data->type);
673 break;
674 }
675
676 if (listtop != NULL)
paul87d6f872004-09-24 08:01:38 +0000677 LIST_LOOP (listtop, oipt, node)
678 if (oipt->opaque_type == key)
679 return oipt;
paul718e3742002-12-13 20:15:29 +0000680
681 return NULL;
682}
683
684static struct opaque_info_per_id *
685register_opaque_info_per_id (struct opaque_info_per_type *oipt,
686 struct ospf_lsa *new)
687{
688 struct opaque_info_per_id *oipi;
689
690 if ((oipi = XCALLOC (MTYPE_OPAQUE_INFO_PER_ID,
691 sizeof (struct opaque_info_per_id))) == NULL)
692 {
ajs6099b3b2004-11-20 02:06:59 +0000693 zlog_warn ("register_opaque_info_per_id: XMALLOC: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000694 goto out;
695 }
696 oipi->opaque_id = GET_OPAQUE_ID (ntohl (new->data->id.s_addr));
697 oipi->t_opaque_lsa_self = NULL;
698 oipi->opqctl_type = oipt;
699 oipi->lsa = ospf_lsa_lock (new);
700
701 listnode_add (oipt->id_list, oipi);
702
703out:
704 return oipi;
705}
706
707static void
708free_opaque_info_per_id (void *val)
709{
710 struct opaque_info_per_id *oipi = (struct opaque_info_per_id *) val;
711
712 OSPF_TIMER_OFF (oipi->t_opaque_lsa_self);
713 if (oipi->lsa != NULL)
714 ospf_lsa_unlock (oipi->lsa);
715 XFREE (MTYPE_OPAQUE_INFO_PER_ID, oipi);
716 return;
717}
718
719static struct opaque_info_per_id *
720lookup_opaque_info_by_id (struct opaque_info_per_type *oipt,
721 struct ospf_lsa *lsa)
722{
paul87d6f872004-09-24 08:01:38 +0000723 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000724 struct opaque_info_per_id *oipi;
725 u_int32_t key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
726
paul87d6f872004-09-24 08:01:38 +0000727 LIST_LOOP (oipt->id_list, oipi, node)
728 if (oipi->opaque_id == key)
729 return oipi;
paul718e3742002-12-13 20:15:29 +0000730
731 return NULL;
732}
733
734static struct opaque_info_per_id *
735register_opaque_lsa (struct ospf_lsa *new)
736{
737 struct ospf_opaque_functab *functab;
738 struct opaque_info_per_type *oipt;
739 struct opaque_info_per_id *oipi = NULL;
740
741 if ((functab = ospf_opaque_functab_lookup (new)) == NULL)
742 goto out;
743
744 if ((oipt = lookup_opaque_info_by_type (new)) == NULL
745 && (oipt = register_opaque_info_per_type (functab, new)) == NULL)
746 goto out;
747
748 if ((oipi = register_opaque_info_per_id (oipt, new)) == NULL)
749 goto out;
750
751out:
752 return oipi;
753}
754
755/*------------------------------------------------------------------------*
756 * Followings are (vty) configuration functions for Opaque-LSAs handling.
757 *------------------------------------------------------------------------*/
758
759DEFUN (capability_opaque,
760 capability_opaque_cmd,
761 "capability opaque",
762 "Enable specific OSPF feature\n"
763 "Opaque LSA\n")
764{
765 struct ospf *ospf = (struct ospf *) vty->index;
766
767 /* Turn on the "master switch" of opaque-lsa capability. */
768 if (!CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
769 {
770 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000771 zlog_debug ("Opaque capability: OFF -> ON");
paul718e3742002-12-13 20:15:29 +0000772
773 SET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
774 ospf_renegotiate_optional_capabilities (ospf);
775 }
776 return CMD_SUCCESS;
777}
778
779ALIAS (capability_opaque,
780 ospf_opaque_capable_cmd,
781 "ospf opaque-lsa",
782 "OSPF specific commands\n"
783 "Enable the Opaque-LSA capability (rfc2370)\n")
784
785DEFUN (no_capability_opaque,
786 no_capability_opaque_cmd,
787 "no capability opaque",
788 NO_STR
789 "Enable specific OSPF feature\n"
790 "Opaque LSA\n")
791{
792 struct ospf *ospf = (struct ospf *) vty->index;
793
794 /* Turn off the "master switch" of opaque-lsa capability. */
795 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
796 {
797 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000798 zlog_debug ("Opaque capability: ON -> OFF");
paul718e3742002-12-13 20:15:29 +0000799
800 UNSET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
801 ospf_renegotiate_optional_capabilities (ospf);
802 }
803 return CMD_SUCCESS;
804}
805
806ALIAS (no_capability_opaque,
807 no_ospf_opaque_capable_cmd,
808 "no ospf opaque-lsa",
809 NO_STR
810 "OSPF specific commands\n"
811 "Disable the Opaque-LSA capability (rfc2370)\n")
812
813static void
814ospf_opaque_register_vty (void)
815{
816 install_element (OSPF_NODE, &capability_opaque_cmd);
817 install_element (OSPF_NODE, &no_capability_opaque_cmd);
818 install_element (OSPF_NODE, &ospf_opaque_capable_cmd);
819 install_element (OSPF_NODE, &no_ospf_opaque_capable_cmd);
820 return;
821}
822
823/*------------------------------------------------------------------------*
824 * Followings are collection of user-registered function callers.
825 *------------------------------------------------------------------------*/
826
827static int
paul87d6f872004-09-24 08:01:38 +0000828opaque_lsa_new_if_callback (struct list *funclist, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000829{
paul87d6f872004-09-24 08:01:38 +0000830 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000831 struct ospf_opaque_functab *functab;
832 int rc = -1;
833
paul87d6f872004-09-24 08:01:38 +0000834 LIST_LOOP (funclist, functab, node)
835 if (functab->new_if_hook != NULL)
836 if ((* functab->new_if_hook)(ifp) != 0)
837 goto out;
paul718e3742002-12-13 20:15:29 +0000838 rc = 0;
839out:
840 return rc;
841}
842
843static int
paul87d6f872004-09-24 08:01:38 +0000844opaque_lsa_del_if_callback (struct list *funclist, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000845{
paul87d6f872004-09-24 08:01:38 +0000846 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000847 struct ospf_opaque_functab *functab;
848 int rc = -1;
849
paul87d6f872004-09-24 08:01:38 +0000850 LIST_LOOP (funclist, functab, node)
851 if (functab->del_if_hook != NULL)
852 if ((* functab->del_if_hook)(ifp) != 0)
853 goto out;
paul718e3742002-12-13 20:15:29 +0000854 rc = 0;
855out:
856 return rc;
857}
858
859static void
paul87d6f872004-09-24 08:01:38 +0000860opaque_lsa_ism_change_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000861 struct ospf_interface *oi, int old_status)
862{
paul87d6f872004-09-24 08:01:38 +0000863 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000864 struct ospf_opaque_functab *functab;
865
paul87d6f872004-09-24 08:01:38 +0000866 LIST_LOOP (funclist, functab, node)
867 if (functab->ism_change_hook != NULL)
868 (* functab->ism_change_hook)(oi, old_status);
869
paul718e3742002-12-13 20:15:29 +0000870 return;
871}
872
873static void
paul87d6f872004-09-24 08:01:38 +0000874opaque_lsa_nsm_change_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000875 struct ospf_neighbor *nbr, int old_status)
876{
paul87d6f872004-09-24 08:01:38 +0000877 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000878 struct ospf_opaque_functab *functab;
879
paul87d6f872004-09-24 08:01:38 +0000880 LIST_LOOP (funclist, functab, node)
881 if (functab->nsm_change_hook != NULL)
882 (* functab->nsm_change_hook)(nbr, old_status);
paul718e3742002-12-13 20:15:29 +0000883 return;
884}
885
886static void
paul87d6f872004-09-24 08:01:38 +0000887opaque_lsa_config_write_router_callback (struct list *funclist,
888 struct vty *vty)
paul718e3742002-12-13 20:15:29 +0000889{
paul87d6f872004-09-24 08:01:38 +0000890 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000891 struct ospf_opaque_functab *functab;
892
paul87d6f872004-09-24 08:01:38 +0000893 LIST_LOOP (funclist, functab, node)
894 if (functab->config_write_router != NULL)
895 (* functab->config_write_router)(vty);
paul718e3742002-12-13 20:15:29 +0000896 return;
897}
898
899static void
paul87d6f872004-09-24 08:01:38 +0000900opaque_lsa_config_write_if_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000901 struct vty *vty, struct interface *ifp)
902{
paul87d6f872004-09-24 08:01:38 +0000903 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000904 struct ospf_opaque_functab *functab;
905
paul87d6f872004-09-24 08:01:38 +0000906 LIST_LOOP (funclist, functab, node)
907 if (functab->config_write_if != NULL)
908 (* functab->config_write_if)(vty, ifp);
paul718e3742002-12-13 20:15:29 +0000909 return;
910}
911
912static void
paul87d6f872004-09-24 08:01:38 +0000913opaque_lsa_config_write_debug_callback (struct list *funclist, struct vty *vty)
paul718e3742002-12-13 20:15:29 +0000914{
paul87d6f872004-09-24 08:01:38 +0000915 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000916 struct ospf_opaque_functab *functab;
917
paul87d6f872004-09-24 08:01:38 +0000918 LIST_LOOP (funclist, functab, node)
919 if (functab->config_write_debug != NULL)
920 (* functab->config_write_debug)(vty);
paul718e3742002-12-13 20:15:29 +0000921 return;
922}
923
924static int
paul87d6f872004-09-24 08:01:38 +0000925opaque_lsa_originate_callback (struct list *funclist, void *lsa_type_dependent)
paul718e3742002-12-13 20:15:29 +0000926{
paul87d6f872004-09-24 08:01:38 +0000927 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000928 struct ospf_opaque_functab *functab;
929 int rc = -1;
930
paul87d6f872004-09-24 08:01:38 +0000931 LIST_LOOP (funclist, functab, node)
932 if (functab->lsa_originator != NULL)
933 if ((* functab->lsa_originator)(lsa_type_dependent) != 0)
934 goto out;
paul718e3742002-12-13 20:15:29 +0000935 rc = 0;
936out:
937 return rc;
938}
939
940static int
paul87d6f872004-09-24 08:01:38 +0000941new_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000942{
paul87d6f872004-09-24 08:01:38 +0000943 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000944 struct ospf_opaque_functab *functab;
945 int rc = -1;
946
947 /* This function handles ALL types of LSAs, not only opaque ones. */
paul87d6f872004-09-24 08:01:38 +0000948 LIST_LOOP (funclist, functab, node)
949 if (functab->new_lsa_hook != NULL)
950 if ((* functab->new_lsa_hook)(lsa) != 0)
951 goto out;
paul718e3742002-12-13 20:15:29 +0000952 rc = 0;
953out:
954 return rc;
955}
956
957static int
paul87d6f872004-09-24 08:01:38 +0000958del_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000959{
paul87d6f872004-09-24 08:01:38 +0000960 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000961 struct ospf_opaque_functab *functab;
962 int rc = -1;
963
964 /* This function handles ALL types of LSAs, not only opaque ones. */
paul87d6f872004-09-24 08:01:38 +0000965 LIST_LOOP (funclist, functab, node)
966 if (functab->del_lsa_hook != NULL)
967 if ((* functab->del_lsa_hook)(lsa) != 0)
968 goto out;
paul718e3742002-12-13 20:15:29 +0000969 rc = 0;
970out:
971 return rc;
972}
973
974/*------------------------------------------------------------------------*
975 * Followings are glue functions to call Opaque-LSA specific processing.
976 *------------------------------------------------------------------------*/
977
978int
979ospf_opaque_new_if (struct interface *ifp)
980{
paul87d6f872004-09-24 08:01:38 +0000981 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000982 int rc = -1;
983
paul09e4efd2003-01-18 00:12:02 +0000984 funclist = ospf_opaque_wildcard_funclist;
985 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
986 goto out;
987
paul718e3742002-12-13 20:15:29 +0000988 funclist = ospf_opaque_type9_funclist;
989 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
990 goto out;
991
992 funclist = ospf_opaque_type10_funclist;
993 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
994 goto out;
995
996 funclist = ospf_opaque_type11_funclist;
997 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
998 goto out;
999
1000 rc = 0;
1001out:
1002 return rc;
1003}
1004
1005int
1006ospf_opaque_del_if (struct interface *ifp)
1007{
paul87d6f872004-09-24 08:01:38 +00001008 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001009 int rc = -1;
1010
paul09e4efd2003-01-18 00:12:02 +00001011 funclist = ospf_opaque_wildcard_funclist;
1012 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1013 goto out;
1014
paul718e3742002-12-13 20:15:29 +00001015 funclist = ospf_opaque_type9_funclist;
1016 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1017 goto out;
1018
1019 funclist = ospf_opaque_type10_funclist;
1020 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1021 goto out;
1022
1023 funclist = ospf_opaque_type11_funclist;
1024 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1025 goto out;
1026
1027 rc = 0;
1028out:
1029 return rc;
1030}
1031
1032void
1033ospf_opaque_ism_change (struct ospf_interface *oi, int old_status)
1034{
paul87d6f872004-09-24 08:01:38 +00001035 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001036
paul09e4efd2003-01-18 00:12:02 +00001037 funclist = ospf_opaque_wildcard_funclist;
1038 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1039
paul718e3742002-12-13 20:15:29 +00001040 funclist = ospf_opaque_type9_funclist;
1041 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1042
1043 funclist = ospf_opaque_type10_funclist;
1044 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1045
1046 funclist = ospf_opaque_type11_funclist;
1047 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1048
1049 return;
1050}
1051
1052void
1053ospf_opaque_nsm_change (struct ospf_neighbor *nbr, int old_state)
1054{
1055 struct ospf *top;
paul87d6f872004-09-24 08:01:38 +00001056 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001057
1058 if ((top = oi_to_top (nbr->oi)) == NULL)
1059 goto out;
1060
1061 if (old_state != NSM_Full && nbr->state == NSM_Full)
1062 {
1063 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
1064 {
1065 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1066 {
1067 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001068 zlog_debug ("Opaque-LSA: Now get operational!");
paul718e3742002-12-13 20:15:29 +00001069
1070 SET_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT);
1071 }
1072
1073 ospf_opaque_lsa_originate_schedule (nbr->oi, NULL);
1074 }
1075 }
1076 else
1077 if (old_state == NSM_Full && nbr->state != NSM_Full)
1078 {
1079#ifdef NOTYET
1080 /*
1081 * If no more opaque-capable full-state neighbor remains in the
1082 * flooding scope which corresponds to Opaque-LSA type, periodic
1083 * LS flooding should be stopped.
1084 */
1085#endif /* NOTYET */
1086 ;
1087 }
1088
paul09e4efd2003-01-18 00:12:02 +00001089 funclist = ospf_opaque_wildcard_funclist;
1090 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1091
paul718e3742002-12-13 20:15:29 +00001092 funclist = ospf_opaque_type9_funclist;
1093 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1094
1095 funclist = ospf_opaque_type10_funclist;
1096 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1097
1098 funclist = ospf_opaque_type11_funclist;
1099 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1100
1101out:
1102 return;
1103}
1104
1105void
1106ospf_opaque_config_write_router (struct vty *vty, struct ospf *ospf)
1107{
paul87d6f872004-09-24 08:01:38 +00001108 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001109
1110 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
1111 vty_out (vty, " capability opaque%s", VTY_NEWLINE);
1112
paul09e4efd2003-01-18 00:12:02 +00001113 funclist = ospf_opaque_wildcard_funclist;
1114 opaque_lsa_config_write_router_callback (funclist, vty);
1115
paul718e3742002-12-13 20:15:29 +00001116 funclist = ospf_opaque_type9_funclist;
1117 opaque_lsa_config_write_router_callback (funclist, vty);
1118
1119 funclist = ospf_opaque_type10_funclist;
1120 opaque_lsa_config_write_router_callback (funclist, vty);
1121
1122 funclist = ospf_opaque_type11_funclist;
1123 opaque_lsa_config_write_router_callback (funclist, vty);
1124
1125 return;
1126}
1127
1128void
1129ospf_opaque_config_write_if (struct vty *vty, struct interface *ifp)
1130{
paul87d6f872004-09-24 08:01:38 +00001131 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001132
paul09e4efd2003-01-18 00:12:02 +00001133 funclist = ospf_opaque_wildcard_funclist;
1134 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1135
paul718e3742002-12-13 20:15:29 +00001136 funclist = ospf_opaque_type9_funclist;
1137 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1138
1139 funclist = ospf_opaque_type10_funclist;
1140 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1141
1142 funclist = ospf_opaque_type11_funclist;
1143 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1144
1145 return;
1146}
1147
1148void
1149ospf_opaque_config_write_debug (struct vty *vty)
1150{
paul87d6f872004-09-24 08:01:38 +00001151 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001152
paul09e4efd2003-01-18 00:12:02 +00001153 funclist = ospf_opaque_wildcard_funclist;
1154 opaque_lsa_config_write_debug_callback (funclist, vty);
1155
paul718e3742002-12-13 20:15:29 +00001156 funclist = ospf_opaque_type9_funclist;
1157 opaque_lsa_config_write_debug_callback (funclist, vty);
1158
1159 funclist = ospf_opaque_type10_funclist;
1160 opaque_lsa_config_write_debug_callback (funclist, vty);
1161
1162 funclist = ospf_opaque_type11_funclist;
1163 opaque_lsa_config_write_debug_callback (funclist, vty);
1164
1165 return;
1166}
1167
1168void
1169show_opaque_info_detail (struct vty *vty, struct ospf_lsa *lsa)
1170{
1171 struct lsa_header *lsah = (struct lsa_header *) lsa->data;
1172 u_int32_t lsid = ntohl (lsah->id.s_addr);
1173 u_char opaque_type = GET_OPAQUE_TYPE (lsid);
1174 u_int32_t opaque_id = GET_OPAQUE_ID (lsid);
1175 struct ospf_opaque_functab *functab;
1176
1177 /* Switch output functionality by vty address. */
1178 if (vty != NULL)
1179 {
paul020709f2003-04-04 02:44:16 +00001180 vty_out (vty, " Opaque-Type %u (%s)%s", opaque_type,
1181 ospf_opaque_type_name (opaque_type), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001182 vty_out (vty, " Opaque-ID 0x%x%s", opaque_id, VTY_NEWLINE);
1183
1184 vty_out (vty, " Opaque-Info: %u octets of data%s%s",
1185 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1186 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)",
1187 VTY_NEWLINE);
1188 }
1189 else
1190 {
ajs2a42e282004-12-08 18:43:03 +00001191 zlog_debug (" Opaque-Type %u (%s)", opaque_type,
paul020709f2003-04-04 02:44:16 +00001192 ospf_opaque_type_name (opaque_type));
ajs2a42e282004-12-08 18:43:03 +00001193 zlog_debug (" Opaque-ID 0x%x", opaque_id);
paul718e3742002-12-13 20:15:29 +00001194
ajs2a42e282004-12-08 18:43:03 +00001195 zlog_debug (" Opaque-Info: %u octets of data%s",
paul718e3742002-12-13 20:15:29 +00001196 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1197 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)");
1198 }
1199
1200 /* Call individual output functions. */
1201 if ((functab = ospf_opaque_functab_lookup (lsa)) != NULL)
1202 if (functab->show_opaque_info != NULL)
1203 (* functab->show_opaque_info)(vty, lsa);
1204
1205 return;
1206}
1207
1208void
1209ospf_opaque_lsa_dump (struct stream *s, u_int16_t length)
1210{
1211 struct ospf_lsa lsa;
1212
1213 lsa.data = (struct lsa_header *) STREAM_PNT (s);
1214 show_opaque_info_detail (NULL, &lsa);
1215 return;
1216}
1217
1218static int
1219ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa)
1220{
paul87d6f872004-09-24 08:01:38 +00001221 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001222 int rc = -1;
1223
1224 /*
1225 * Some Opaque-LSA user may want to monitor every LSA installation
1226 * into the LSDB, regardless with target LSA type.
1227 */
paul09e4efd2003-01-18 00:12:02 +00001228 funclist = ospf_opaque_wildcard_funclist;
1229 if (new_lsa_callback (funclist, lsa) != 0)
1230 goto out;
1231
paul718e3742002-12-13 20:15:29 +00001232 funclist = ospf_opaque_type9_funclist;
1233 if (new_lsa_callback (funclist, lsa) != 0)
1234 goto out;
1235
1236 funclist = ospf_opaque_type10_funclist;
1237 if (new_lsa_callback (funclist, lsa) != 0)
1238 goto out;
1239
1240 funclist = ospf_opaque_type11_funclist;
1241 if (new_lsa_callback (funclist, lsa) != 0)
1242 goto out;
1243
1244 rc = 0;
1245out:
1246 return rc;
1247}
1248
1249static int
1250ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa)
1251{
paul87d6f872004-09-24 08:01:38 +00001252 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001253 int rc = -1;
1254
1255 /*
1256 * Some Opaque-LSA user may want to monitor every LSA deletion
1257 * from the LSDB, regardless with target LSA type.
1258 */
paul09e4efd2003-01-18 00:12:02 +00001259 funclist = ospf_opaque_wildcard_funclist;
1260 if (del_lsa_callback (funclist, lsa) != 0)
1261 goto out;
1262
paul718e3742002-12-13 20:15:29 +00001263 funclist = ospf_opaque_type9_funclist;
1264 if (del_lsa_callback (funclist, lsa) != 0)
1265 goto out;
1266
1267 funclist = ospf_opaque_type10_funclist;
1268 if (del_lsa_callback (funclist, lsa) != 0)
1269 goto out;
1270
1271 funclist = ospf_opaque_type11_funclist;
1272 if (del_lsa_callback (funclist, lsa) != 0)
1273 goto out;
1274
1275 rc = 0;
1276out:
1277 return rc;
1278}
1279
1280/*------------------------------------------------------------------------*
1281 * Followings are Opaque-LSA origination/refresh management functions.
1282 *------------------------------------------------------------------------*/
1283
1284static int ospf_opaque_type9_lsa_originate (struct thread *t);
1285static int ospf_opaque_type10_lsa_originate (struct thread *t);
1286static int ospf_opaque_type11_lsa_originate (struct thread *t);
paul87d6f872004-09-24 08:01:38 +00001287static void ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg);
paul718e3742002-12-13 20:15:29 +00001288
1289void
1290ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0)
1291{
1292 struct ospf *top;
1293 struct ospf_area *area;
paul87d6f872004-09-24 08:01:38 +00001294 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001295 struct opaque_info_per_type *oipt;
1296 int delay = 0;
1297
1298 if ((top = oi_to_top (oi)) == NULL || (area = oi->area) == NULL)
1299 {
1300 zlog_warn ("ospf_opaque_lsa_originate_schedule: Invalid argument?");
1301 goto out;
1302 }
1303
1304 /* It may not a right time to schedule origination now. */
1305 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1306 {
1307 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001308 zlog_debug ("ospf_opaque_lsa_originate_schedule: Not operational.");
paul718e3742002-12-13 20:15:29 +00001309 goto out; /* This is not an error. */
1310 }
1311 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
1312 {
1313 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001314 zlog_debug ("ospf_opaque_lsa_originate_schedule: Under blockade.");
paul718e3742002-12-13 20:15:29 +00001315 goto out; /* This is not an error, too. */
1316 }
1317
1318 if (delay0 != NULL)
1319 delay = *delay0;
1320
1321 /*
1322 * There might be some entries that have been waiting for triggering
1323 * of per opaque-type re-origination get resumed.
1324 */
1325 ospf_opaque_lsa_reoriginate_resume ( oi->opaque_lsa_self, (void *) oi);
1326 ospf_opaque_lsa_reoriginate_resume (area->opaque_lsa_self, (void *) area);
1327 ospf_opaque_lsa_reoriginate_resume ( top->opaque_lsa_self, (void *) top);
1328
1329 /*
1330 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1331 */
1332 if (! list_isempty (ospf_opaque_type9_funclist)
1333 && list_isempty (oi->opaque_lsa_self)
1334 && oi->t_opaque_lsa_self == NULL)
1335 {
1336 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001337 zlog_debug ("Schedule Type-9 Opaque-LSA origination in %d sec later.", delay);
paul718e3742002-12-13 20:15:29 +00001338 oi->t_opaque_lsa_self =
1339 thread_add_timer (master, ospf_opaque_type9_lsa_originate, oi, delay);
1340 delay += OSPF_MIN_LS_INTERVAL;
1341 }
1342
1343 if (! list_isempty (ospf_opaque_type10_funclist)
1344 && list_isempty (area->opaque_lsa_self)
1345 && area->t_opaque_lsa_self == NULL)
1346 {
1347 /*
1348 * One AREA may contain multiple OIs, but above 2nd and 3rd
1349 * conditions prevent from scheduling the originate function
1350 * again and again.
1351 */
1352 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001353 zlog_debug ("Schedule Type-10 Opaque-LSA origination in %d sec later.", delay);
paul718e3742002-12-13 20:15:29 +00001354 area->t_opaque_lsa_self =
1355 thread_add_timer (master, ospf_opaque_type10_lsa_originate,
1356 area, delay);
1357 delay += OSPF_MIN_LS_INTERVAL;
1358 }
1359
1360 if (! list_isempty (ospf_opaque_type11_funclist)
1361 && list_isempty (top->opaque_lsa_self)
1362 && top->t_opaque_lsa_self == NULL)
1363 {
1364 /*
1365 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1366 * conditions prevent from scheduling the originate function
1367 * again and again.
1368 */
1369 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001370 zlog_debug ("Schedule Type-11 Opaque-LSA origination in %d sec later.", delay);
paul718e3742002-12-13 20:15:29 +00001371 top->t_opaque_lsa_self =
1372 thread_add_timer (master, ospf_opaque_type11_lsa_originate,
1373 top, delay);
1374 delay += OSPF_MIN_LS_INTERVAL;
1375 }
1376
1377 /*
1378 * Following section treats a special situation that this node's
1379 * opaque capability has changed as "ON -> OFF -> ON".
1380 */
1381 if (! list_isempty (ospf_opaque_type9_funclist)
1382 && ! list_isempty (oi->opaque_lsa_self))
1383 {
1384 for (node = listhead (oi->opaque_lsa_self); node; nextnode (node))
1385 {
hasso0d85b992004-03-18 19:18:33 +00001386 /*
1387 * removed the test for
1388 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1389 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1390 * not being empty.
1391 */
paul718e3742002-12-13 20:15:29 +00001392 if ((oipt = getdata (node)) == NULL /* Something wrong? */
1393 || oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
hasso0d85b992004-03-18 19:18:33 +00001394 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001395 continue;
1396
1397 ospf_opaque_lsa_reoriginate_schedule ((void *) oi,
1398 OSPF_OPAQUE_LINK_LSA, oipt->opaque_type);
1399 }
1400 }
1401
1402 if (! list_isempty (ospf_opaque_type10_funclist)
1403 && ! list_isempty (area->opaque_lsa_self))
1404 {
1405 for (node = listhead (area->opaque_lsa_self); node; nextnode (node))
1406 {
hasso0d85b992004-03-18 19:18:33 +00001407 /*
1408 * removed the test for
1409 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1410 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1411 * not being empty.
1412 */
paul718e3742002-12-13 20:15:29 +00001413 if ((oipt = getdata (node)) == NULL /* Something wrong? */
1414 || oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
hasso0d85b992004-03-18 19:18:33 +00001415 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001416 continue;
1417
1418 ospf_opaque_lsa_reoriginate_schedule ((void *) area,
1419 OSPF_OPAQUE_AREA_LSA, oipt->opaque_type);
1420 }
1421 }
1422
1423 if (! list_isempty (ospf_opaque_type11_funclist)
1424 && ! list_isempty (top->opaque_lsa_self))
1425 {
1426 for (node = listhead (top->opaque_lsa_self); node; nextnode (node))
1427 {
hasso0d85b992004-03-18 19:18:33 +00001428 /*
1429 * removed the test for
1430 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1431 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1432 * not being empty.
1433 */
paul718e3742002-12-13 20:15:29 +00001434 if ((oipt = getdata (node)) == NULL /* Something wrong? */
1435 || oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
hasso0d85b992004-03-18 19:18:33 +00001436 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001437 continue;
1438
1439 ospf_opaque_lsa_reoriginate_schedule ((void *) top,
1440 OSPF_OPAQUE_AS_LSA, oipt->opaque_type);
1441 }
1442 }
1443
1444 if (delay0 != NULL)
1445 *delay0 = delay;
1446
1447out:
1448 return;
1449}
1450
1451static int
1452ospf_opaque_type9_lsa_originate (struct thread *t)
1453{
1454 struct ospf_interface *oi;
1455 int rc;
1456
1457 oi = THREAD_ARG (t);
1458 oi->t_opaque_lsa_self = NULL;
1459
1460 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001461 zlog_debug ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
paul718e3742002-12-13 20:15:29 +00001462 IF_NAME (oi));
1463
1464 rc = opaque_lsa_originate_callback (ospf_opaque_type9_funclist, oi);
1465
1466 return rc;
1467}
1468
1469static int
1470ospf_opaque_type10_lsa_originate (struct thread *t)
1471{
1472 struct ospf_area *area;
1473 int rc;
1474
1475 area = THREAD_ARG (t);
1476 area->t_opaque_lsa_self = NULL;
1477
1478 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001479 zlog_debug ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
paul718e3742002-12-13 20:15:29 +00001480 inet_ntoa (area->area_id));
1481
1482 rc = opaque_lsa_originate_callback (ospf_opaque_type10_funclist, area);
1483
1484 return rc;
1485}
1486
1487static int
1488ospf_opaque_type11_lsa_originate (struct thread *t)
1489{
1490 struct ospf *top;
1491 int rc;
1492
1493 top = THREAD_ARG (t);
1494 top->t_opaque_lsa_self = NULL;
1495
1496 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001497 zlog_debug ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
paul718e3742002-12-13 20:15:29 +00001498
1499 rc = opaque_lsa_originate_callback (ospf_opaque_type11_funclist, top);
1500
1501 return rc;
1502}
1503
1504static void
paul87d6f872004-09-24 08:01:38 +00001505ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg)
paul718e3742002-12-13 20:15:29 +00001506{
paul87d6f872004-09-24 08:01:38 +00001507 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001508 struct opaque_info_per_type *oipt;
1509 struct ospf_opaque_functab *functab;
1510
1511 if (listtop == NULL)
1512 goto out;
1513
1514 /*
1515 * Pickup oipt entries those which in SUSPEND status, and give
1516 * them a chance to start re-origination now.
1517 */
paul87d6f872004-09-24 08:01:38 +00001518 LIST_LOOP (listtop, oipt, node)
paul718e3742002-12-13 20:15:29 +00001519 {
paul87d6f872004-09-24 08:01:38 +00001520 if (oipt->status != PROC_SUSPEND)
paul718e3742002-12-13 20:15:29 +00001521 continue;
1522
1523 oipt->status = PROC_NORMAL;
1524
1525 if ((functab = oipt->functab) == NULL
paul87d6f872004-09-24 08:01:38 +00001526 || functab->lsa_originator == NULL)
paul718e3742002-12-13 20:15:29 +00001527 continue;
1528
1529 if ((* functab->lsa_originator)(arg) != 0)
1530 {
1531 zlog_warn ("ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", oipt->opaque_type);
1532 continue;
1533 }
1534 }
1535
1536out:
1537 return;
1538}
1539
1540struct ospf_lsa *
1541ospf_opaque_lsa_install (struct ospf_lsa *lsa, int rt_recalc)
1542{
1543 struct ospf_lsa *new = NULL;
1544 struct opaque_info_per_type *oipt;
1545 struct opaque_info_per_id *oipi;
1546 struct ospf *top;
1547
1548 /* Don't take "rt_recalc" into consideration for now. *//* XXX */
1549
1550 if (! IS_LSA_SELF (lsa))
1551 {
1552 new = lsa; /* Don't touch this LSA. */
1553 goto out;
1554 }
1555
1556 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
ajs2a42e282004-12-08 18:43:03 +00001557 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 +00001558
1559 /* Replace the existing lsa with the new one. */
1560 if ((oipt = lookup_opaque_info_by_type (lsa)) != NULL
paul87d6f872004-09-24 08:01:38 +00001561 && (oipi = lookup_opaque_info_by_id (oipt, lsa)) != NULL)
paul718e3742002-12-13 20:15:29 +00001562 {
1563 ospf_lsa_unlock (oipi->lsa);
1564 oipi->lsa = ospf_lsa_lock (lsa);
1565 }
1566 /* Register the new lsa entry and get its control info. */
1567 else
1568 if ((oipi = register_opaque_lsa (lsa)) == NULL)
1569 {
1570 zlog_warn ("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1571 goto out;
1572 }
1573
1574 /*
1575 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1576 * for periodic refresh of self-originated Opaque-LSAs.
1577 */
1578 switch (lsa->data->type)
1579 {
1580 case OSPF_OPAQUE_LINK_LSA:
paul09e4efd2003-01-18 00:12:02 +00001581 if ((top = oi_to_top (lsa->oi)) == NULL)
1582 {
1583 /* Above conditions must have passed. */
1584 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1585 goto out;
1586 }
1587 break;
paul718e3742002-12-13 20:15:29 +00001588 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00001589 if (lsa->area == NULL || (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001590 {
1591 /* Above conditions must have passed. */
1592 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1593 goto out;
1594 }
1595 break;
1596 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +00001597 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001598 if (lsa->area != NULL && (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001599 {
1600 /* Above conditions must have passed. */
1601 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1602 goto out;
1603 }
1604 break;
1605 default:
1606 zlog_warn ("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", lsa->data->type);
1607 goto out;
1608 }
1609
1610 ospf_refresher_register_lsa (top, lsa);
1611 new = lsa;
1612
1613out:
1614 return new;
1615}
1616
1617void
1618ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
1619{
paul020709f2003-04-04 02:44:16 +00001620 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001621 struct ospf_opaque_functab *functab;
1622
paul020709f2003-04-04 02:44:16 +00001623 ospf = ospf_lookup ();
1624
paul718e3742002-12-13 20:15:29 +00001625 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL
paul87d6f872004-09-24 08:01:38 +00001626 || functab->lsa_refresher == NULL)
paul718e3742002-12-13 20:15:29 +00001627 {
1628 /*
1629 * Though this LSA seems to have originated on this node, the
1630 * handling module for this "lsa-type and opaque-type" was
1631 * already deleted sometime ago.
1632 * Anyway, this node still has a responsibility to flush this
1633 * LSA from the routing domain.
1634 */
1635 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001636 zlog_debug ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id));
paul718e3742002-12-13 20:15:29 +00001637
1638 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
paul68980082003-03-25 05:07:42 +00001639 ospf_lsa_maxage (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00001640 }
1641 else
1642 (* functab->lsa_refresher)(lsa);
1643
1644 return;
1645}
1646
1647/*------------------------------------------------------------------------*
1648 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1649 * triggered by external interventions (vty session, signaling, etc).
1650 *------------------------------------------------------------------------*/
1651
1652#define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
1653 if (!(T)) \
1654 (T) = thread_add_timer (master, (F), (L), (V))
1655
1656static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type);
1657static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t);
1658static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t);
1659static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t);
1660static int ospf_opaque_lsa_refresh_timer (struct thread *t);
1661
1662void
1663ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
1664 u_char lsa_type, u_char opaque_type)
1665{
1666 struct ospf *top;
1667 struct ospf_area dummy, *area = NULL;
1668 struct ospf_interface *oi = NULL;
1669
1670 struct ospf_lsa *lsa;
1671 struct opaque_info_per_type *oipt;
paul87d6f872004-09-24 08:01:38 +00001672 int (*func) (struct thread * t) = NULL;
paul718e3742002-12-13 20:15:29 +00001673 int delay;
1674
1675 switch (lsa_type)
1676 {
1677 case OSPF_OPAQUE_LINK_LSA:
1678 if ((oi = (struct ospf_interface *) lsa_type_dependent) == NULL)
1679 {
paul87d6f872004-09-24 08:01:38 +00001680 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1681 " Type-9 Opaque-LSA: Invalid parameter?");
1682 goto out;
paul718e3742002-12-13 20:15:29 +00001683 }
1684 if ((top = oi_to_top (oi)) == NULL)
1685 {
paul87d6f872004-09-24 08:01:38 +00001686 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1687 IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001688 goto out;
1689 }
paul87d6f872004-09-24 08:01:38 +00001690 if (!list_isempty (ospf_opaque_type9_funclist)
1691 && list_isempty (oi->opaque_lsa_self)
1692 && oi->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001693 {
paul87d6f872004-09-24 08:01:38 +00001694 zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u):"
1695 " Common origination for OI(%s) has already started",
1696 opaque_type, IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001697 goto out;
1698 }
1699 func = ospf_opaque_type9_lsa_reoriginate_timer;
1700 break;
1701 case OSPF_OPAQUE_AREA_LSA:
1702 if ((area = (struct ospf_area *) lsa_type_dependent) == NULL)
1703 {
paul87d6f872004-09-24 08:01:38 +00001704 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1705 " Type-10 Opaque-LSA: Invalid parameter?");
paul718e3742002-12-13 20:15:29 +00001706 goto out;
1707 }
paul68980082003-03-25 05:07:42 +00001708 if ((top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001709 {
paul87d6f872004-09-24 08:01:38 +00001710 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1711 " AREA(%s) -> TOP?", inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001712 goto out;
1713 }
paul87d6f872004-09-24 08:01:38 +00001714 if (!list_isempty (ospf_opaque_type10_funclist)
1715 && list_isempty (area->opaque_lsa_self)
1716 && area->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001717 {
paul87d6f872004-09-24 08:01:38 +00001718 zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u):"
1719 " Common origination for AREA(%s) has already started",
1720 opaque_type, inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001721 goto out;
1722 }
1723 func = ospf_opaque_type10_lsa_reoriginate_timer;
1724 break;
1725 case OSPF_OPAQUE_AS_LSA:
1726 if ((top = (struct ospf *) lsa_type_dependent) == NULL)
1727 {
paul87d6f872004-09-24 08:01:38 +00001728 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1729 " Type-11 Opaque-LSA: Invalid parameter?");
1730 goto out;
paul718e3742002-12-13 20:15:29 +00001731 }
paul87d6f872004-09-24 08:01:38 +00001732 if (!list_isempty (ospf_opaque_type11_funclist)
1733 && list_isempty (top->opaque_lsa_self)
1734 && top->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001735 {
paul87d6f872004-09-24 08:01:38 +00001736 zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u):"
1737 " Common origination has already started", opaque_type);
paul718e3742002-12-13 20:15:29 +00001738 goto out;
1739 }
1740
1741 /* Fake "area" to pass "ospf" to a lookup function later. */
paul68980082003-03-25 05:07:42 +00001742 dummy.ospf = top;
paul718e3742002-12-13 20:15:29 +00001743 area = &dummy;
1744
1745 func = ospf_opaque_type11_lsa_reoriginate_timer;
1746 break;
1747 default:
paul87d6f872004-09-24 08:01:38 +00001748 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1749 " Unexpected LSA-type(%u)",
1750 lsa_type);
paul718e3742002-12-13 20:15:29 +00001751 goto out;
1752 }
1753
1754 /* It may not a right time to schedule reorigination now. */
paul87d6f872004-09-24 08:01:38 +00001755 if (!CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
paul718e3742002-12-13 20:15:29 +00001756 {
1757 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001758 zlog_debug ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
paul87d6f872004-09-24 08:01:38 +00001759 goto out; /* This is not an error. */
paul718e3742002-12-13 20:15:29 +00001760 }
1761 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
1762 {
1763 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001764 zlog_debug ("ospf_opaque_lsa_reoriginate_schedule: Under blockade.");
paul87d6f872004-09-24 08:01:38 +00001765 goto out; /* This is not an error, too. */
paul718e3742002-12-13 20:15:29 +00001766 }
1767
1768 /* Generate a dummy lsa to be passed for a lookup function. */
1769 lsa = pseudo_lsa (oi, area, lsa_type, opaque_type);
1770
1771 if ((oipt = lookup_opaque_info_by_type (lsa)) == NULL)
1772 {
1773 struct ospf_opaque_functab *functab;
1774 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL)
1775 {
paul87d6f872004-09-24 08:01:38 +00001776 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1777 " No associated function?: lsa_type(%u),"
1778 " opaque_type(%u)",
1779 lsa_type, opaque_type);
paul718e3742002-12-13 20:15:29 +00001780 goto out;
1781 }
1782 if ((oipt = register_opaque_info_per_type (functab, lsa)) == NULL)
1783 {
paul87d6f872004-09-24 08:01:38 +00001784 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1785 " Cannot get a control info?: lsa_type(%u),"
1786 " opaque_type(%u)",
1787 lsa_type, opaque_type);
paul718e3742002-12-13 20:15:29 +00001788 goto out;
1789 }
1790 }
1791
1792 if (oipt->t_opaque_lsa_self != NULL)
1793 {
1794 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001795 zlog_debug ("Type-%u Opaque-LSA has already scheduled to"
paul87d6f872004-09-24 08:01:38 +00001796 " RE-ORIGINATE: [opaque-type=%u]",
1797 lsa_type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
paul718e3742002-12-13 20:15:29 +00001798 goto out;
1799 }
1800
1801 /*
1802 * Different from initial origination time, in which various conditions
1803 * (opaque capability, neighbor status etc) are assured by caller of
1804 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1805 * it is highly possible that these conditions might not be satisfied
1806 * at the time of re-origination function is to be called.
1807 */
1808 delay = OSPF_MIN_LS_INTERVAL; /* XXX */
1809
1810 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001811 zlog_debug ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
paul87d6f872004-09-24 08:01:38 +00001812 " sec later: [opaque-type=%u]",
1813 lsa_type, delay,
1814 GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
paul718e3742002-12-13 20:15:29 +00001815
1816 OSPF_OPAQUE_TIMER_ON (oipt->t_opaque_lsa_self, func, oipt, delay);
1817
1818out:
1819 return;
1820}
1821
1822static struct ospf_lsa *
1823pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area,
1824 u_char lsa_type, u_char opaque_type)
1825{
1826 static struct ospf_lsa lsa = { 0 };
1827 static struct lsa_header lsah = { 0 };
1828 u_int32_t tmp;
1829
1830 lsa.oi = oi;
1831 lsa.area = area;
1832 lsa.data = &lsah;
1833
1834 lsah.type = lsa_type;
1835 tmp = SET_OPAQUE_LSID (opaque_type, 0); /* Opaque-ID is unused here. */
1836 lsah.id.s_addr = htonl (tmp);
1837
1838 return &lsa;
1839}
1840
1841static int
1842ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t)
1843{
1844 struct opaque_info_per_type *oipt;
1845 struct ospf_opaque_functab *functab;
1846 struct ospf *top;
1847 struct ospf_interface *oi;
1848 int rc = -1;
1849
1850 oipt = THREAD_ARG (t);
1851 oipt->t_opaque_lsa_self = NULL;
1852
1853 if ((functab = oipt->functab) == NULL
1854 || functab->lsa_originator == NULL)
1855 {
1856 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1857 goto out;
1858 }
1859
1860 oi = (struct ospf_interface *) oipt->owner;
1861 if ((top = oi_to_top (oi)) == NULL)
1862 {
1863 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1864 goto out;
1865 }
1866
1867 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)
1868 || ! ospf_if_is_enable (oi)
paul68980082003-03-25 05:07:42 +00001869 || ospf_nbr_count_opaque_capable (oi) == 0)
paul718e3742002-12-13 20:15:29 +00001870 {
1871 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001872 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 +00001873
1874 oipt->status = PROC_SUSPEND;
1875 rc = 0;
1876 goto out;
1877 }
1878
1879 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001880 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 +00001881
1882 rc = (* functab->lsa_originator)(oi);
1883out:
1884 return rc;
1885}
1886
1887static int
1888ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t)
1889{
1890 struct opaque_info_per_type *oipt;
1891 struct ospf_opaque_functab *functab;
paul87d6f872004-09-24 08:01:38 +00001892 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001893 struct ospf *top;
1894 struct ospf_area *area;
1895 struct ospf_interface *oi;
1896 int n, rc = -1;
1897
1898 oipt = THREAD_ARG (t);
1899 oipt->t_opaque_lsa_self = NULL;
1900
1901 if ((functab = oipt->functab) == NULL
1902 || functab->lsa_originator == NULL)
1903 {
1904 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1905 goto out;
1906 }
1907
1908 area = (struct ospf_area *) oipt->owner;
paul68980082003-03-25 05:07:42 +00001909 if (area == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001910 {
1911 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1912 goto out;
1913 }
1914
1915 /* There must be at least one "opaque-capable, full-state" neighbor. */
1916 n = 0;
paul87d6f872004-09-24 08:01:38 +00001917 LIST_LOOP (area->oiflist, oi, node)
paul718e3742002-12-13 20:15:29 +00001918 {
paul68980082003-03-25 05:07:42 +00001919 if ((n = ospf_nbr_count_opaque_capable (oi)) > 0)
paul718e3742002-12-13 20:15:29 +00001920 break;
1921 }
1922
1923 if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1924 {
1925 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001926 zlog_debug ("Suspend re-origination of Type-10 Opaque-LSAs"
paul87d6f872004-09-24 08:01:38 +00001927 " (opaque-type=%u) for a while...",
1928 oipt->opaque_type);
paul718e3742002-12-13 20:15:29 +00001929
1930 oipt->status = PROC_SUSPEND;
1931 rc = 0;
1932 goto out;
1933 }
1934
1935 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001936 zlog_debug ("Timer[Type10-LSA]: Re-originate Opaque-LSAs"
paul87d6f872004-09-24 08:01:38 +00001937 " (opaque-type=%u) for Area %s",
1938 oipt->opaque_type, inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001939
1940 rc = (* functab->lsa_originator)(area);
1941out:
1942 return rc;
1943}
1944
1945static int
1946ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t)
1947{
1948 struct opaque_info_per_type *oipt;
1949 struct ospf_opaque_functab *functab;
1950 struct ospf *top;
1951 int rc = -1;
1952
1953 oipt = THREAD_ARG (t);
1954 oipt->t_opaque_lsa_self = NULL;
1955
1956 if ((functab = oipt->functab) == NULL
paul87d6f872004-09-24 08:01:38 +00001957 || functab->lsa_originator == NULL)
paul718e3742002-12-13 20:15:29 +00001958 {
paul87d6f872004-09-24 08:01:38 +00001959 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer:"
1960 " No associated function?");
paul718e3742002-12-13 20:15:29 +00001961 goto out;
1962 }
1963
1964 if ((top = (struct ospf *) oipt->owner) == NULL)
1965 {
1966 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1967 goto out;
1968 }
1969
1970 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1971 {
1972 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001973 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 +00001974
1975 oipt->status = PROC_SUSPEND;
1976 rc = 0;
1977 goto out;
1978 }
1979
1980 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001981 zlog_debug ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type);
paul718e3742002-12-13 20:15:29 +00001982
1983 rc = (* functab->lsa_originator)(top);
1984out:
1985 return rc;
1986}
1987
1988extern int ospf_lsa_refresh_delay (struct ospf_lsa *); /* ospf_lsa.c */
1989
1990void
1991ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
1992{
paul020709f2003-04-04 02:44:16 +00001993 struct ospf *ospf = ospf;
paul718e3742002-12-13 20:15:29 +00001994 struct opaque_info_per_type *oipt;
1995 struct opaque_info_per_id *oipi;
1996 struct ospf_lsa *lsa;
1997 int delay;
1998
paul020709f2003-04-04 02:44:16 +00001999 ospf = ospf_lookup ();
2000
paul718e3742002-12-13 20:15:29 +00002001 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
2002 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
2003 {
2004 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
2005 goto out;
2006 }
2007
2008 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2009 if ((lsa = oipi->lsa) == NULL)
2010 {
2011 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
2012 goto out;
2013 }
2014
2015 if (oipi->t_opaque_lsa_self != NULL)
2016 {
2017 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002018 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 +00002019 goto out;
2020 }
2021
2022 /* Delete this lsa from neighbor retransmit-list. */
2023 switch (lsa->data->type)
2024 {
2025 case OSPF_OPAQUE_LINK_LSA:
2026 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002027 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002028 break;
2029 case OSPF_OPAQUE_AS_LSA:
paul68980082003-03-25 05:07:42 +00002030 ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002031 break;
2032 default:
2033 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2034 goto out;
2035 }
2036
2037 delay = ospf_lsa_refresh_delay (lsa);
2038
2039 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002040 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 +00002041
2042 OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self,
2043 ospf_opaque_lsa_refresh_timer, oipi, delay);
2044out:
2045 return;
2046}
2047
2048static int
2049ospf_opaque_lsa_refresh_timer (struct thread *t)
2050{
2051 struct opaque_info_per_id *oipi;
2052 struct ospf_opaque_functab *functab;
2053 struct ospf_lsa *lsa;
2054
2055 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002056 zlog_debug ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
paul718e3742002-12-13 20:15:29 +00002057
2058 oipi = THREAD_ARG (t);
2059 oipi->t_opaque_lsa_self = NULL;
2060
2061 if ((lsa = oipi->lsa) != NULL)
2062 if ((functab = oipi->opqctl_type->functab) != NULL)
2063 if (functab->lsa_refresher != NULL)
2064 (* functab->lsa_refresher)(lsa);
2065
2066 return 0;
2067}
2068
2069void
2070ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
2071{
paul020709f2003-04-04 02:44:16 +00002072 struct ospf *ospf = ospf;
paul718e3742002-12-13 20:15:29 +00002073 struct opaque_info_per_type *oipt;
2074 struct opaque_info_per_id *oipi;
2075 struct ospf_lsa *lsa;
2076
paul020709f2003-04-04 02:44:16 +00002077 ospf = ospf_lookup ();
2078
paul718e3742002-12-13 20:15:29 +00002079 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
2080 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
2081 {
2082 zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2083 goto out;
2084 }
2085
2086 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2087 if ((lsa = oipi->lsa) == NULL)
2088 {
2089 zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
2090 goto out;
2091 }
2092
2093 /* Delete this lsa from neighbor retransmit-list. */
2094 switch (lsa->data->type)
2095 {
2096 case OSPF_OPAQUE_LINK_LSA:
2097 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002098 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002099 break;
2100 case OSPF_OPAQUE_AS_LSA:
paul68980082003-03-25 05:07:42 +00002101 ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002102 break;
2103 default:
2104 zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2105 goto out;
2106 }
2107
2108 /* Dequeue listnode entry from the list. */
2109 listnode_delete (oipt->id_list, oipi);
2110
2111 /* Avoid misjudgement in the next lookup. */
2112 if (listcount (oipt->id_list) == 0)
2113 oipt->id_list->head = oipt->id_list->tail = NULL;
2114
2115 /* Disassociate internal control information with the given lsa. */
paul718e3742002-12-13 20:15:29 +00002116 free_opaque_info_per_id ((void *) oipi);
2117
2118 /* Force given lsa's age to MaxAge. */
2119 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2120
2121 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002122 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 +00002123
2124 /* This lsa will be flushed and removed eventually. */
paul68980082003-03-25 05:07:42 +00002125 ospf_lsa_maxage (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002126
2127out:
2128 return;
2129}
2130
2131/*------------------------------------------------------------------------*
2132 * Followings are control functions to block origination after restart.
2133 *------------------------------------------------------------------------*/
2134
2135static void ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs, struct ospf_neighbor *inbr, struct ospf_lsa *lsa);
2136static void ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi);
2137static void ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area);
2138static void ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top);
2139static unsigned long ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type);
2140
2141void
paul87d6f872004-09-24 08:01:38 +00002142ospf_opaque_adjust_lsreq (struct ospf_neighbor *nbr, struct list *lsas)
paul718e3742002-12-13 20:15:29 +00002143{
2144 struct ospf *top;
2145 struct ospf_area *area;
2146 struct ospf_interface *oi;
paul87d6f872004-09-24 08:01:38 +00002147 struct listnode *node1, *node2;
paul718e3742002-12-13 20:15:29 +00002148 struct ospf_lsa *lsa;
2149
2150 if ((top = oi_to_top (nbr->oi)) == NULL)
2151 goto out;
2152
2153 /*
2154 * If an instance of self-originated Opaque-LSA is found in the given
2155 * LSA list, and it is not installed to LSDB yet, exclude it from the
2156 * list "nbr->ls_req". In this way, it is assured that an LSReq message,
2157 * which might be sent in the process of flooding, will not request for
2158 * the LSA to be flushed immediately; otherwise, depending on timing,
2159 * an LSUpd message will carry instances of target LSAs with MaxAge,
2160 * while other LSUpd message might carry old LSA instances (non-MaxAge).
2161 * Obviously, the latter would trigger miserable situations that repeat
2162 * installation and removal of unwanted LSAs indefinitely.
2163 */
2164 for (node1 = listhead (lsas); node1; nextnode (node1))
2165 {
2166 if ((lsa = getdata (node1)) == NULL)
2167 continue;
2168
2169 /* Filter out unwanted LSAs. */
2170 if (! IS_OPAQUE_LSA (lsa->data->type))
2171 continue;
2172 if (! IPV4_ADDR_SAME (&lsa->data->adv_router, &top->router_id))
2173 continue;
2174
2175 /*
2176 * Don't touch an LSA which has MaxAge; two possible cases.
2177 *
2178 * 1) This LSA has originally flushed by myself (received LSUpd
2179 * message's router-id is equal to my router-id), and flooded
2180 * back by an opaque-capable router.
2181 *
2182 * 2) This LSA has expired in an opaque-capable router and thus
2183 * flushed by the router.
2184 */
2185 if (IS_LSA_MAXAGE (lsa))
2186 continue;
2187
2188 /* If the LSA has installed in the LSDB, nothing to do here. */
2189 if (ospf_lsa_lookup_by_header (nbr->oi->area, lsa->data) != NULL)
2190 continue;
2191
2192 /* Ok, here we go. */
2193 switch (lsa->data->type)
2194 {
2195 case OSPF_OPAQUE_LINK_LSA:
2196 oi = nbr->oi;
2197 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2198 break;
2199 case OSPF_OPAQUE_AREA_LSA:
2200 area = nbr->oi->area;
2201 for (node2 = listhead (area->oiflist); node2; nextnode (node2))
2202 {
2203 if ((oi = getdata (node2)) == NULL)
2204 continue;
2205 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2206 }
2207 break;
2208 case OSPF_OPAQUE_AS_LSA:
2209 for (node2 = listhead (top->oiflist); node2; nextnode (node2))
2210 {
2211 if ((oi = getdata (node2)) == NULL)
2212 continue;
2213 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2214 }
2215 break;
2216 default:
2217 break;
2218 }
2219 }
2220
2221out:
2222 return;
2223}
2224
2225static void
2226ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs,
2227 struct ospf_neighbor *inbr,
2228 struct ospf_lsa *lsa)
2229{
2230 struct route_node *rn;
2231 struct ospf_neighbor *onbr;
2232 struct ospf_lsa *ls_req;
2233
2234 for (rn = route_top (nbrs); rn; rn = route_next (rn))
2235 {
2236 if ((onbr = rn->info) == NULL)
2237 continue;
2238 if (onbr == inbr)
2239 continue;
2240 if ((ls_req = ospf_ls_request_lookup (onbr, lsa)) == NULL)
2241 continue;
2242
2243 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002244 zlog_debug ("LSA[%s]: Exclude this entry from LSReq to send.", dump_lsa_key (lsa));
paul718e3742002-12-13 20:15:29 +00002245
2246 ospf_ls_request_delete (onbr, ls_req);
2247/* ospf_check_nbr_loading (onbr);*//* XXX */
2248 }
2249
2250 return;
2251}
2252
2253void
paul87d6f872004-09-24 08:01:38 +00002254ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr,
2255 struct list *lsas)
paul718e3742002-12-13 20:15:29 +00002256{
2257 struct ospf *top;
paul87d6f872004-09-24 08:01:38 +00002258 struct listnode *node, *next;
paul718e3742002-12-13 20:15:29 +00002259 struct ospf_lsa *lsa;
2260 u_char before;
2261
2262 if ((top = oi_to_top (nbr->oi)) == NULL)
2263 goto out;
2264
2265 before = IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque);
2266
2267 for (node = listhead (lsas); node; node = next)
2268 {
2269 next = node->next;
2270
2271 if ((lsa = getdata (node)) == NULL)
2272 continue;
2273
2274 listnode_delete (lsas, lsa);
2275
2276 /*
2277 * Since these LSA entries are not yet installed into corresponding
2278 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2279 */
2280 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2281 switch (lsa->data->type)
2282 {
2283 case OSPF_OPAQUE_LINK_LSA:
2284 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
2285 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2286 break;
2287 case OSPF_OPAQUE_AREA_LSA:
2288 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
2289 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2290 break;
2291 case OSPF_OPAQUE_AS_LSA:
2292 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
paul68980082003-03-25 05:07:42 +00002293 ospf_flood_through_as (top, NULL/*inbr*/, lsa);
paul718e3742002-12-13 20:15:29 +00002294 break;
2295 default:
2296 zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
2297 goto out;
2298 }
2299
2300 ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */
2301 }
2302
2303 if (before == 0 && IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2304 {
2305 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002306 zlog_debug ("Block Opaque-LSA origination: OFF -> ON");
paul718e3742002-12-13 20:15:29 +00002307 }
2308
2309out:
2310 return;
2311}
2312
2313void
paul87d6f872004-09-24 08:01:38 +00002314ospf_opaque_ls_ack_received (struct ospf_neighbor *nbr, struct list *acks)
paul718e3742002-12-13 20:15:29 +00002315{
2316 struct ospf *top;
paul87d6f872004-09-24 08:01:38 +00002317 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002318 struct ospf_lsa *lsa;
2319 char type9_lsa_rcv = 0, type10_lsa_rcv = 0, type11_lsa_rcv = 0;
2320
2321 if ((top = oi_to_top (nbr->oi)) == NULL)
2322 goto out;
2323
paul87d6f872004-09-24 08:01:38 +00002324 LIST_LOOP (acks, lsa, node)
paul718e3742002-12-13 20:15:29 +00002325 {
paul718e3742002-12-13 20:15:29 +00002326 switch (lsa->data->type)
2327 {
2328 case OSPF_OPAQUE_LINK_LSA:
2329 type9_lsa_rcv = 1;
2330 /* Callback function... */
2331 break;
2332 case OSPF_OPAQUE_AREA_LSA:
2333 type10_lsa_rcv = 1;
2334 /* Callback function... */
2335 break;
2336 case OSPF_OPAQUE_AS_LSA:
2337 type11_lsa_rcv = 1;
2338 /* Callback function... */
2339 break;
2340 default:
2341 zlog_warn ("ospf_opaque_ls_ack_received: Unexpected LSA-type(%u)", lsa->data->type);
2342 goto out;
2343 }
2344 }
2345
2346 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2347 {
2348 int delay;
2349 struct ospf_interface *oi;
2350
2351 if (type9_lsa_rcv
2352 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT))
2353 ospf_opaque_type9_lsa_rxmt_nbr_check (nbr->oi);
2354
2355 if (type10_lsa_rcv
2356 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT))
2357 ospf_opaque_type10_lsa_rxmt_nbr_check (nbr->oi->area);
2358
2359 if (type11_lsa_rcv
2360 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT))
2361 ospf_opaque_type11_lsa_rxmt_nbr_check (top);
2362
2363 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2364 goto out; /* Blocking still in progress. */
2365
2366 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002367 zlog_debug ("Block Opaque-LSA origination: ON -> OFF");
paul718e3742002-12-13 20:15:29 +00002368
2369 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
2370 goto out; /* Opaque capability condition must have changed. */
2371
2372 /* Ok, let's start origination of Opaque-LSAs. */
2373 delay = OSPF_MIN_LS_INTERVAL;
paul718e3742002-12-13 20:15:29 +00002374
paul87d6f872004-09-24 08:01:38 +00002375 LIST_LOOP (top->oiflist, oi, node)
2376 {
paul718e3742002-12-13 20:15:29 +00002377 if (! ospf_if_is_enable (oi)
paul87d6f872004-09-24 08:01:38 +00002378 || ospf_nbr_count_opaque_capable (oi) == 0)
paul718e3742002-12-13 20:15:29 +00002379 continue;
2380
2381 ospf_opaque_lsa_originate_schedule (oi, &delay);
2382 }
2383 }
2384
2385out:
2386 return;
2387}
2388
2389static void
2390ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi)
2391{
2392 unsigned long n;
2393
2394 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_LINK_LSA);
2395 if (n == 0)
2396 {
2397 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002398 zlog_debug ("Self-originated type-9 Opaque-LSAs: OI(%s): Flush completed", IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00002399
paul68980082003-03-25 05:07:42 +00002400 UNSET_FLAG (oi->area->ospf->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
paul718e3742002-12-13 20:15:29 +00002401 }
2402 return;
2403}
2404
2405static void
2406ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area)
2407{
paul87d6f872004-09-24 08:01:38 +00002408 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002409 struct ospf_interface *oi;
2410 unsigned long n = 0;
2411
2412 for (node = listhead (area->oiflist); node; nextnode (node))
2413 {
2414 if ((oi = getdata (node)) == NULL)
2415 continue;
2416
2417 if (area->area_id.s_addr != OSPF_AREA_BACKBONE
2418 && oi->type == OSPF_IFTYPE_VIRTUALLINK)
2419 continue;
2420
2421 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AREA_LSA);
2422 if (n > 0)
2423 break;
2424 }
2425
2426 if (n == 0)
2427 {
2428 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002429 zlog_debug ("Self-originated type-10 Opaque-LSAs: AREA(%s): Flush completed", inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00002430
paul68980082003-03-25 05:07:42 +00002431 UNSET_FLAG (area->ospf->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
paul718e3742002-12-13 20:15:29 +00002432 }
2433
2434 return;
2435}
2436
2437static void
2438ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top)
2439{
paul87d6f872004-09-24 08:01:38 +00002440 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002441 struct ospf_interface *oi;
2442 unsigned long n = 0;
2443
2444 for (node = listhead (top->oiflist); node; nextnode (node))
2445 {
2446 if ((oi = getdata (node)) == NULL)
2447 continue;
2448
2449 switch (oi->type)
2450 {
2451 case OSPF_IFTYPE_VIRTUALLINK:
2452 continue;
2453 default:
2454 break;
2455 }
2456
2457 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AS_LSA);
2458 if (n > 0)
2459 goto out;
2460 }
2461
2462 if (n == 0)
2463 {
2464 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002465 zlog_debug ("Self-originated type-11 Opaque-LSAs: Flush completed");
paul718e3742002-12-13 20:15:29 +00002466
2467 UNSET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
2468 }
2469
2470out:
2471 return;
2472}
2473
2474static unsigned long
2475ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type)
2476{
2477 struct route_node *rn;
2478 struct ospf_neighbor *nbr;
2479 struct ospf *top;
2480 unsigned long n = 0;
2481
2482 for (rn = route_top (nbrs); rn; rn = route_next (rn))
2483 {
2484 if ((nbr = rn->info) == NULL)
2485 continue;
2486 if ((top = oi_to_top (nbr->oi)) == NULL)
2487 continue;
2488 if (IPV4_ADDR_SAME (&nbr->router_id, &top->router_id))
2489 continue;
2490 n += ospf_ls_retransmit_count_self (nbr, lsa_type);
2491 }
2492
2493 return n;
2494}
2495
2496/*------------------------------------------------------------------------*
2497 * Followings are util functions; probably be used by Opaque-LSAs only...
2498 *------------------------------------------------------------------------*/
2499
2500void
2501htonf (float *src, float *dst)
2502{
2503 u_int32_t lu1, lu2;
2504
2505 memcpy (&lu1, src, sizeof (u_int32_t));
2506 lu2 = htonl (lu1);
2507 memcpy (dst, &lu2, sizeof (u_int32_t));
2508 return;
2509}
2510
2511void
2512ntohf (float *src, float *dst)
2513{
2514 u_int32_t lu1, lu2;
2515
2516 memcpy (&lu1, src, sizeof (u_int32_t));
2517 lu2 = ntohl (lu1);
2518 memcpy (dst, &lu2, sizeof (u_int32_t));
2519 return;
2520}
2521
2522struct ospf *
2523oi_to_top (struct ospf_interface *oi)
2524{
2525 struct ospf *top = NULL;
2526 struct ospf_area *area;
2527
paul68980082003-03-25 05:07:42 +00002528 if (oi == NULL || (area = oi->area) == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00002529 zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");
2530
2531 return top;
2532}
2533
2534#endif /* HAVE_OPAQUE_LSA */