blob: d0d1be3d5a263bf8c1456896391835f303795d99 [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);
hassoc3abdb72004-10-11 16:27:03 +000072extern int ospf_apiserver_enable;
paul283ae332003-03-17 01:16:55 +000073#endif /* SUPPORT_OSPF_API */
74
paul718e3742002-12-13 20:15:29 +000075static void ospf_opaque_register_vty (void);
76static void ospf_opaque_funclist_init (void);
77static void ospf_opaque_funclist_term (void);
78static void free_opaque_info_per_type (void *val);
79static void free_opaque_info_per_id (void *val);
80static int ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa);
81static int ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa);
82
83void
84ospf_opaque_init (void)
85{
86 ospf_opaque_register_vty ();
87 ospf_opaque_funclist_init ();
88
89#ifdef HAVE_OSPF_TE
90 if (ospf_mpls_te_init () != 0)
91 exit (1);
92#endif /* HAVE_OSPF_TE */
93
paul283ae332003-03-17 01:16:55 +000094#ifdef SUPPORT_OSPF_API
hassoc3abdb72004-10-11 16:27:03 +000095 if ((ospf_apiserver_enable) && (ospf_apiserver_init () != 0))
paul283ae332003-03-17 01:16:55 +000096 exit (1);
97#endif /* SUPPORT_OSPF_API */
98
paul718e3742002-12-13 20:15:29 +000099 return;
100}
101
102void
103ospf_opaque_term (void)
104{
105#ifdef HAVE_OSPF_TE
106 ospf_mpls_te_term ();
107#endif /* HAVE_OSPF_TE */
108
paul283ae332003-03-17 01:16:55 +0000109#ifdef SUPPORT_OSPF_API
110 ospf_apiserver_term ();
111#endif /* SUPPORT_OSPF_API */
112
paul718e3742002-12-13 20:15:29 +0000113 ospf_opaque_funclist_term ();
114 return;
115}
116
117int
118ospf_opaque_type9_lsa_init (struct ospf_interface *oi)
119{
120 if (oi->opaque_lsa_self != NULL)
121 list_delete (oi->opaque_lsa_self);
122
123 oi->opaque_lsa_self = list_new ();
124 oi->opaque_lsa_self->del = free_opaque_info_per_type;
125 oi->t_opaque_lsa_self = NULL;
126 return 0;
127}
128
129void
130ospf_opaque_type9_lsa_term (struct ospf_interface *oi)
131{
132 OSPF_TIMER_OFF (oi->t_opaque_lsa_self);
133 if (oi->opaque_lsa_self != NULL)
134 list_delete (oi->opaque_lsa_self);
135 oi->opaque_lsa_self = NULL;
136 return;
137}
138
139int
140ospf_opaque_type10_lsa_init (struct ospf_area *area)
141{
142 if (area->opaque_lsa_self != NULL)
143 list_delete (area->opaque_lsa_self);
144
145 area->opaque_lsa_self = list_new ();
146 area->opaque_lsa_self->del = free_opaque_info_per_type;
147 area->t_opaque_lsa_self = NULL;
148
149#ifdef MONITOR_LSDB_CHANGE
150 area->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
151 area->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
152#endif /* MONITOR_LSDB_CHANGE */
153 return 0;
154}
155
156void
157ospf_opaque_type10_lsa_term (struct ospf_area *area)
158{
159#ifdef MONITOR_LSDB_CHANGE
160 area->lsdb->new_lsa_hook =
161 area->lsdb->del_lsa_hook = NULL;
162#endif /* MONITOR_LSDB_CHANGE */
163
164 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
165 if (area->opaque_lsa_self != NULL)
166 list_delete (area->opaque_lsa_self);
167 area->opaque_lsa_self = NULL;
168 return;
169}
170
171int
172ospf_opaque_type11_lsa_init (struct ospf *top)
173{
174 if (top->opaque_lsa_self != NULL)
175 list_delete (top->opaque_lsa_self);
176
177 top->opaque_lsa_self = list_new ();
178 top->opaque_lsa_self->del = free_opaque_info_per_type;
179 top->t_opaque_lsa_self = NULL;
180
181#ifdef MONITOR_LSDB_CHANGE
182 top->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
183 top->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
184#endif /* MONITOR_LSDB_CHANGE */
185 return 0;
186}
187
188void
189ospf_opaque_type11_lsa_term (struct ospf *top)
190{
191#ifdef MONITOR_LSDB_CHANGE
192 top->lsdb->new_lsa_hook =
193 top->lsdb->del_lsa_hook = NULL;
194#endif /* MONITOR_LSDB_CHANGE */
195
196 OSPF_TIMER_OFF (top->t_opaque_lsa_self);
197 if (top->opaque_lsa_self != NULL)
198 list_delete (top->opaque_lsa_self);
199 top->opaque_lsa_self = NULL;
200 return;
201}
202
203static const char *
204ospf_opaque_type_name (u_char opaque_type)
205{
206 const char *name = "Unknown";
207
208 switch (opaque_type)
209 {
210 case OPAQUE_TYPE_WILDCARD: /* This is a special assignment! */
211 name = "Wildcard";
212 break;
213 case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA:
214 name = "Traffic Engineering LSA";
215 break;
216 case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC:
217 name = "Sycamore optical topology description";
218 break;
219 case OPAQUE_TYPE_GRACE_LSA:
220 name = "Grace-LSA";
221 break;
222 default:
223 if (OPAQUE_TYPE_RANGE_UNASSIGNED (opaque_type))
224 name = "Unassigned";
225 else if (OPAQUE_TYPE_RANGE_RESERVED (opaque_type))
226 name = "Private/Experimental";
227 break;
228 }
229 return name;
230}
231
232/*------------------------------------------------------------------------*
233 * Followings are management functions to store user specified callbacks.
234 *------------------------------------------------------------------------*/
235
236struct opaque_info_per_type; /* Forward declaration. */
237
238struct ospf_opaque_functab
239{
240 u_char opaque_type;
241 struct opaque_info_per_type *oipt;
242
243 int (* new_if_hook)(struct interface *ifp);
244 int (* del_if_hook)(struct interface *ifp);
245 void (* ism_change_hook)(struct ospf_interface *oi, int old_status);
246 void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status);
247 void (* config_write_router)(struct vty *vty);
248 void (* config_write_if )(struct vty *vty, struct interface *ifp);
249 void (* config_write_debug )(struct vty *vty);
250 void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa);
251 int (* lsa_originator)(void *arg);
252 void (* lsa_refresher )(struct ospf_lsa *lsa);
253 int (* new_lsa_hook)(struct ospf_lsa *lsa);
254 int (* del_lsa_hook)(struct ospf_lsa *lsa);
255};
256
paul87d6f872004-09-24 08:01:38 +0000257/* Handle LSA-9/10/11 altogether. */
258static struct list *ospf_opaque_wildcard_funclist;
259static struct list *ospf_opaque_type9_funclist;
260static struct list *ospf_opaque_type10_funclist;
261static struct list *ospf_opaque_type11_funclist;
paul718e3742002-12-13 20:15:29 +0000262
263static void
264ospf_opaque_del_functab (void *val)
265{
266 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, val);
267 return;
268}
269
270static void
271ospf_opaque_funclist_init (void)
272{
paul87d6f872004-09-24 08:01:38 +0000273 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000274
paul09e4efd2003-01-18 00:12:02 +0000275 funclist = ospf_opaque_wildcard_funclist = list_new ();
276 funclist->del = ospf_opaque_del_functab;
277
paul718e3742002-12-13 20:15:29 +0000278 funclist = ospf_opaque_type9_funclist = list_new ();
279 funclist->del = ospf_opaque_del_functab;
280
281 funclist = ospf_opaque_type10_funclist = list_new ();
282 funclist->del = ospf_opaque_del_functab;
283
284 funclist = ospf_opaque_type11_funclist = list_new ();
285 funclist->del = ospf_opaque_del_functab;
286 return;
287}
288
289static void
290ospf_opaque_funclist_term (void)
291{
paul87d6f872004-09-24 08:01:38 +0000292 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000293
paul09e4efd2003-01-18 00:12:02 +0000294 funclist = ospf_opaque_wildcard_funclist;
295 list_delete (funclist);
296
paul718e3742002-12-13 20:15:29 +0000297 funclist = ospf_opaque_type9_funclist;
298 list_delete (funclist);
299
300 funclist = ospf_opaque_type10_funclist;
301 list_delete (funclist);
302
303 funclist = ospf_opaque_type11_funclist;
304 list_delete (funclist);
305 return;
306}
307
paul87d6f872004-09-24 08:01:38 +0000308static struct list *
paul718e3742002-12-13 20:15:29 +0000309ospf_get_opaque_funclist (u_char lsa_type)
310{
paul87d6f872004-09-24 08:01:38 +0000311 struct list *funclist = NULL;
paul718e3742002-12-13 20:15:29 +0000312
313 switch (lsa_type)
314 {
paul09e4efd2003-01-18 00:12:02 +0000315 case OPAQUE_TYPE_WILDCARD:
316 /* XXX
317 * This is an ugly trick to handle type-9/10/11 LSA altogether.
318 * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor
319 * an officially assigned opaque-type.
320 * Though it is possible that the value might be officially used
321 * in the future, we use it internally as a special label, for now.
322 */
323 funclist = ospf_opaque_wildcard_funclist;
324 break;
paul718e3742002-12-13 20:15:29 +0000325 case OSPF_OPAQUE_LINK_LSA:
326 funclist = ospf_opaque_type9_funclist;
327 break;
328 case OSPF_OPAQUE_AREA_LSA:
329 funclist = ospf_opaque_type10_funclist;
330 break;
331 case OSPF_OPAQUE_AS_LSA:
332 funclist = ospf_opaque_type11_funclist;
333 break;
334 default:
335 zlog_warn ("ospf_get_opaque_funclist: Unexpected LSA-type(%u)", lsa_type);
336 break;
337 }
338 return funclist;
339}
340
paul87d6f872004-09-24 08:01:38 +0000341/* XXX: such a huge argument list can /not/ be healthy... */
paul718e3742002-12-13 20:15:29 +0000342int
343ospf_register_opaque_functab (
344 u_char lsa_type,
345 u_char opaque_type,
346 int (* new_if_hook)(struct interface *ifp),
347 int (* del_if_hook)(struct interface *ifp),
348 void (* ism_change_hook)(struct ospf_interface *oi, int old_status),
349 void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status),
350 void (* config_write_router)(struct vty *vty),
351 void (* config_write_if )(struct vty *vty, struct interface *ifp),
352 void (* config_write_debug )(struct vty *vty),
353 void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa),
354 int (* lsa_originator)(void *arg),
355 void (* lsa_refresher )(struct ospf_lsa *lsa),
356 int (* new_lsa_hook)(struct ospf_lsa *lsa),
357 int (* del_lsa_hook)(struct ospf_lsa *lsa))
358{
paul87d6f872004-09-24 08:01:38 +0000359 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000360 struct ospf_opaque_functab *new;
361 int rc = -1;
362
363 if ((funclist = ospf_get_opaque_funclist (lsa_type)) == NULL)
364 {
paul87d6f872004-09-24 08:01:38 +0000365 zlog_warn ("ospf_register_opaque_functab: Cannot get funclist"
366 " for Type-%u LSAs?",
367 lsa_type);
paul718e3742002-12-13 20:15:29 +0000368 goto out;
369 }
370 else
371 {
paul87d6f872004-09-24 08:01:38 +0000372 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000373 struct ospf_opaque_functab *functab;
paul87d6f872004-09-24 08:01:38 +0000374
375 LIST_LOOP (funclist, functab, node)
376 if (functab->opaque_type == opaque_type)
377 {
378 zlog_warn ("ospf_register_opaque_functab: Duplicated entry?:"
379 " lsa_type(%u), opaque_type(%u)",
380 lsa_type, opaque_type);
381 goto out;
382 }
paul718e3742002-12-13 20:15:29 +0000383 }
384
385 if ((new = XCALLOC (MTYPE_OSPF_OPAQUE_FUNCTAB,
386 sizeof (struct ospf_opaque_functab))) == NULL)
387 {
paul87d6f872004-09-24 08:01:38 +0000388 zlog_warn ("ospf_register_opaque_functab: XMALLOC: %s",
389 strerror (errno));
paul718e3742002-12-13 20:15:29 +0000390 goto out;
391 }
392
393 new->opaque_type = opaque_type;
394 new->oipt = NULL;
395 new->new_if_hook = new_if_hook;
396 new->del_if_hook = del_if_hook;
397 new->ism_change_hook = ism_change_hook;
398 new->nsm_change_hook = nsm_change_hook;
399 new->config_write_router = config_write_router;
400 new->config_write_if = config_write_if;
401 new->config_write_debug = config_write_debug;
402 new->show_opaque_info = show_opaque_info;
403 new->lsa_originator = lsa_originator;
404 new->lsa_refresher = lsa_refresher;
405 new->new_lsa_hook = new_lsa_hook;
406 new->del_lsa_hook = del_lsa_hook;
407
408 listnode_add (funclist, new);
409 rc = 0;
410
411out:
412 return rc;
413}
414
415void
416ospf_delete_opaque_functab (u_char lsa_type, u_char opaque_type)
417{
paul87d6f872004-09-24 08:01:38 +0000418 struct list *funclist;
419 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000420 struct ospf_opaque_functab *functab;
421
422 if ((funclist = ospf_get_opaque_funclist (lsa_type)) != NULL)
423 for (node = listhead (funclist); node; nextnode (node))
424 {
425 if ((functab = getdata (node)) != NULL
paul87d6f872004-09-24 08:01:38 +0000426 && functab->opaque_type == opaque_type)
paul718e3742002-12-13 20:15:29 +0000427 {
428 /* Cleanup internal control information, if it still remains. */
429 if (functab->oipt != NULL)
430 free_opaque_info_per_type (functab->oipt);
431
432 /* Dequeue listnode entry from the list. */
433 listnode_delete (funclist, functab);
434
435 /* Avoid misjudgement in the next lookup. */
436 if (listcount (funclist) == 0)
437 funclist->head = funclist->tail = NULL;
438
439 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, functab);
paul87d6f872004-09-24 08:01:38 +0000440 break;
paul718e3742002-12-13 20:15:29 +0000441 }
442 }
paul87d6f872004-09-24 08:01:38 +0000443
paul718e3742002-12-13 20:15:29 +0000444 return;
445}
446
447static struct ospf_opaque_functab *
448ospf_opaque_functab_lookup (struct ospf_lsa *lsa)
449{
paul87d6f872004-09-24 08:01:38 +0000450 struct list *funclist;
451 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000452 struct ospf_opaque_functab *functab;
453 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
454
455 if ((funclist = ospf_get_opaque_funclist (lsa->data->type)) != NULL)
paul87d6f872004-09-24 08:01:38 +0000456 LIST_LOOP (funclist, functab, node)
457 if (functab->opaque_type == key)
458 return functab;
paul718e3742002-12-13 20:15:29 +0000459
460 return NULL;
461}
462
463/*------------------------------------------------------------------------*
464 * Followings are management functions for self-originated LSA entries.
465 *------------------------------------------------------------------------*/
466
467/*
468 * Opaque-LSA control information per opaque-type.
469 * Single Opaque-Type may have multiple instances; each of them will be
470 * identified by their opaque-id.
471 */
472struct opaque_info_per_type
473{
paul09e4efd2003-01-18 00:12:02 +0000474 u_char lsa_type;
paul718e3742002-12-13 20:15:29 +0000475 u_char opaque_type;
476
477 enum { PROC_NORMAL, PROC_SUSPEND } status;
478
479 /*
480 * Thread for (re-)origination scheduling for this opaque-type.
481 *
482 * Initial origination of Opaque-LSAs is controlled by generic
483 * Opaque-LSA handling module so that same opaque-type entries are
484 * called all at once when certain conditions are met.
485 * However, there might be cases that some Opaque-LSA clients need
486 * to (re-)originate their own Opaque-LSAs out-of-sync with others.
487 * This thread is prepared for that specific purpose.
488 */
489 struct thread *t_opaque_lsa_self;
490
491 /*
paul09e4efd2003-01-18 00:12:02 +0000492 * Backpointer to an "owner" which is LSA-type dependent.
paul718e3742002-12-13 20:15:29 +0000493 * type-9: struct ospf_interface
494 * type-10: struct ospf_area
495 * type-11: struct ospf
496 */
497 void *owner;
498
499 /* Collection of callback functions for this opaque-type. */
500 struct ospf_opaque_functab *functab;
501
502 /* List of Opaque-LSA control informations per opaque-id. */
paul87d6f872004-09-24 08:01:38 +0000503 struct list *id_list;
paul718e3742002-12-13 20:15:29 +0000504};
505
506/* Opaque-LSA control information per opaque-id. */
507struct opaque_info_per_id
508{
509 u_int32_t opaque_id;
510
511 /* Thread for refresh/flush scheduling for this opaque-type/id. */
512 struct thread *t_opaque_lsa_self;
513
514 /* Backpointer to Opaque-LSA control information per opaque-type. */
515 struct opaque_info_per_type *opqctl_type;
516
517 /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
518 struct ospf_lsa *lsa;
519};
520
521static struct opaque_info_per_type *register_opaque_info_per_type (struct ospf_opaque_functab *functab, struct ospf_lsa *new);
522static struct opaque_info_per_type *lookup_opaque_info_by_type (struct ospf_lsa *lsa);
523static struct opaque_info_per_id *register_opaque_info_per_id (struct opaque_info_per_type *oipt, struct ospf_lsa *new);
524static struct opaque_info_per_id *lookup_opaque_info_by_id (struct opaque_info_per_type *oipt, struct ospf_lsa *lsa);
525static struct opaque_info_per_id *register_opaque_lsa (struct ospf_lsa *new);
526
527
528static struct opaque_info_per_type *
529register_opaque_info_per_type (struct ospf_opaque_functab *functab,
530 struct ospf_lsa *new)
531{
532 struct ospf *top;
533 struct opaque_info_per_type *oipt;
534
535 if ((oipt = XCALLOC (MTYPE_OPAQUE_INFO_PER_TYPE,
536 sizeof (struct opaque_info_per_type))) == NULL)
537 {
538 zlog_warn ("register_opaque_info_per_type: XMALLOC: %s", strerror (errno));
539 goto out;
540 }
541
542 switch (new->data->type)
543 {
544 case OSPF_OPAQUE_LINK_LSA:
545 oipt->owner = new->oi;
546 listnode_add (new->oi->opaque_lsa_self, oipt);
547 break;
548 case OSPF_OPAQUE_AREA_LSA:
549 oipt->owner = new->area;
550 listnode_add (new->area->opaque_lsa_self, oipt);
551 break;
552 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +0000553 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000554 if (new->area != NULL && (top = new->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +0000555 {
556 free_opaque_info_per_type ((void *) oipt);
557 oipt = NULL;
558 goto out; /* This case may not exist. */
559 }
560 oipt->owner = top;
561 listnode_add (top->opaque_lsa_self, oipt);
562 break;
563 default:
paul09e4efd2003-01-18 00:12:02 +0000564 zlog_warn ("register_opaque_info_per_type: Unexpected LSA-type(%u)", new->data->type);
paul718e3742002-12-13 20:15:29 +0000565 free_opaque_info_per_type ((void *) oipt);
566 oipt = NULL;
567 goto out; /* This case may not exist. */
568 }
569
paul09e4efd2003-01-18 00:12:02 +0000570 oipt->lsa_type = new->data->type;
paul718e3742002-12-13 20:15:29 +0000571 oipt->opaque_type = GET_OPAQUE_TYPE (ntohl (new->data->id.s_addr));
572 oipt->status = PROC_NORMAL;
573 oipt->t_opaque_lsa_self = NULL;
574 oipt->functab = functab;
575 functab->oipt = oipt;
576 oipt->id_list = list_new ();
577 oipt->id_list->del = free_opaque_info_per_id;
578
579out:
580 return oipt;
581}
582
583static void
584free_opaque_info_per_type (void *val)
585{
586 struct opaque_info_per_type *oipt = (struct opaque_info_per_type *) val;
587 struct opaque_info_per_id *oipi;
588 struct ospf_lsa *lsa;
paul87d6f872004-09-24 08:01:38 +0000589 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000590
591 /* Control information per opaque-id may still exist. */
592 for (node = listhead (oipt->id_list); node; nextnode (node))
593 {
594 if ((oipi = getdata (node)) == NULL)
595 continue;
596 if ((lsa = oipi->lsa) == NULL)
597 continue;
598 if (IS_LSA_MAXAGE (lsa))
599 continue;
600 ospf_opaque_lsa_flush_schedule (lsa);
601 }
602
paul09e4efd2003-01-18 00:12:02 +0000603 /* Remove "oipt" from its owner's self-originated LSA list. */
604 switch (oipt->lsa_type)
605 {
606 case OSPF_OPAQUE_LINK_LSA:
607 {
608 struct ospf_interface *oi = (struct ospf_interface *)(oipt->owner);
609 listnode_delete (oi->opaque_lsa_self, oipt);
610 break;
611 }
612 case OSPF_OPAQUE_AREA_LSA:
613 {
614 struct ospf_area *area = (struct ospf_area *)(oipt->owner);
615 listnode_delete (area->opaque_lsa_self, oipt);
616 break;
617 }
618 case OSPF_OPAQUE_AS_LSA:
619 {
620 struct ospf *top = (struct ospf *)(oipt->owner);
621 listnode_delete (top->opaque_lsa_self, oipt);
622 break;
623 }
624 default:
625 zlog_warn ("free_opaque_info_per_type: Unexpected LSA-type(%u)", oipt->lsa_type);
626 break; /* This case may not exist. */
627 }
628
paul718e3742002-12-13 20:15:29 +0000629 OSPF_TIMER_OFF (oipt->t_opaque_lsa_self);
630 list_delete (oipt->id_list);
631 XFREE (MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
632 return;
633}
634
635static struct opaque_info_per_type *
636lookup_opaque_info_by_type (struct ospf_lsa *lsa)
637{
638 struct ospf *top;
639 struct ospf_area *area;
640 struct ospf_interface *oi;
paul87d6f872004-09-24 08:01:38 +0000641 struct list *listtop = NULL;
642 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000643 struct opaque_info_per_type *oipt = NULL;
644 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
645
646 switch (lsa->data->type)
647 {
648 case OSPF_OPAQUE_LINK_LSA:
649 if ((oi = lsa->oi) != NULL)
650 listtop = oi->opaque_lsa_self;
651 else
652 zlog_warn ("Type-9 Opaque-LSA: Reference to OI is missing?");
653 break;
654 case OSPF_OPAQUE_AREA_LSA:
655 if ((area = lsa->area) != NULL)
656 listtop = area->opaque_lsa_self;
657 else
658 zlog_warn ("Type-10 Opaque-LSA: Reference to AREA is missing?");
659 break;
660 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +0000661 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000662 if ((area = lsa->area) != NULL && (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +0000663 {
664 zlog_warn ("Type-11 Opaque-LSA: Reference to OSPF is missing?");
665 break; /* Unlikely to happen. */
666 }
667 listtop = top->opaque_lsa_self;
668 break;
669 default:
670 zlog_warn ("lookup_opaque_info_by_type: Unexpected LSA-type(%u)", lsa->data->type);
671 break;
672 }
673
674 if (listtop != NULL)
paul87d6f872004-09-24 08:01:38 +0000675 LIST_LOOP (listtop, oipt, node)
676 if (oipt->opaque_type == key)
677 return oipt;
paul718e3742002-12-13 20:15:29 +0000678
679 return NULL;
680}
681
682static struct opaque_info_per_id *
683register_opaque_info_per_id (struct opaque_info_per_type *oipt,
684 struct ospf_lsa *new)
685{
686 struct opaque_info_per_id *oipi;
687
688 if ((oipi = XCALLOC (MTYPE_OPAQUE_INFO_PER_ID,
689 sizeof (struct opaque_info_per_id))) == NULL)
690 {
691 zlog_warn ("register_opaque_info_per_id: XMALLOC: %s", strerror (errno));
692 goto out;
693 }
694 oipi->opaque_id = GET_OPAQUE_ID (ntohl (new->data->id.s_addr));
695 oipi->t_opaque_lsa_self = NULL;
696 oipi->opqctl_type = oipt;
697 oipi->lsa = ospf_lsa_lock (new);
698
699 listnode_add (oipt->id_list, oipi);
700
701out:
702 return oipi;
703}
704
705static void
706free_opaque_info_per_id (void *val)
707{
708 struct opaque_info_per_id *oipi = (struct opaque_info_per_id *) val;
709
710 OSPF_TIMER_OFF (oipi->t_opaque_lsa_self);
711 if (oipi->lsa != NULL)
712 ospf_lsa_unlock (oipi->lsa);
713 XFREE (MTYPE_OPAQUE_INFO_PER_ID, oipi);
714 return;
715}
716
717static struct opaque_info_per_id *
718lookup_opaque_info_by_id (struct opaque_info_per_type *oipt,
719 struct ospf_lsa *lsa)
720{
paul87d6f872004-09-24 08:01:38 +0000721 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000722 struct opaque_info_per_id *oipi;
723 u_int32_t key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
724
paul87d6f872004-09-24 08:01:38 +0000725 LIST_LOOP (oipt->id_list, oipi, node)
726 if (oipi->opaque_id == key)
727 return oipi;
paul718e3742002-12-13 20:15:29 +0000728
729 return NULL;
730}
731
732static struct opaque_info_per_id *
733register_opaque_lsa (struct ospf_lsa *new)
734{
735 struct ospf_opaque_functab *functab;
736 struct opaque_info_per_type *oipt;
737 struct opaque_info_per_id *oipi = NULL;
738
739 if ((functab = ospf_opaque_functab_lookup (new)) == NULL)
740 goto out;
741
742 if ((oipt = lookup_opaque_info_by_type (new)) == NULL
743 && (oipt = register_opaque_info_per_type (functab, new)) == NULL)
744 goto out;
745
746 if ((oipi = register_opaque_info_per_id (oipt, new)) == NULL)
747 goto out;
748
749out:
750 return oipi;
751}
752
753/*------------------------------------------------------------------------*
754 * Followings are (vty) configuration functions for Opaque-LSAs handling.
755 *------------------------------------------------------------------------*/
756
757DEFUN (capability_opaque,
758 capability_opaque_cmd,
759 "capability opaque",
760 "Enable specific OSPF feature\n"
761 "Opaque LSA\n")
762{
763 struct ospf *ospf = (struct ospf *) vty->index;
764
765 /* Turn on the "master switch" of opaque-lsa capability. */
766 if (!CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
767 {
768 if (IS_DEBUG_OSPF_EVENT)
769 zlog_info ("Opaque capability: OFF -> ON");
770
771 SET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
772 ospf_renegotiate_optional_capabilities (ospf);
773 }
774 return CMD_SUCCESS;
775}
776
777ALIAS (capability_opaque,
778 ospf_opaque_capable_cmd,
779 "ospf opaque-lsa",
780 "OSPF specific commands\n"
781 "Enable the Opaque-LSA capability (rfc2370)\n")
782
783DEFUN (no_capability_opaque,
784 no_capability_opaque_cmd,
785 "no capability opaque",
786 NO_STR
787 "Enable specific OSPF feature\n"
788 "Opaque LSA\n")
789{
790 struct ospf *ospf = (struct ospf *) vty->index;
791
792 /* Turn off the "master switch" of opaque-lsa capability. */
793 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
794 {
795 if (IS_DEBUG_OSPF_EVENT)
796 zlog_info ("Opaque capability: ON -> OFF");
797
798 UNSET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
799 ospf_renegotiate_optional_capabilities (ospf);
800 }
801 return CMD_SUCCESS;
802}
803
804ALIAS (no_capability_opaque,
805 no_ospf_opaque_capable_cmd,
806 "no ospf opaque-lsa",
807 NO_STR
808 "OSPF specific commands\n"
809 "Disable the Opaque-LSA capability (rfc2370)\n")
810
811static void
812ospf_opaque_register_vty (void)
813{
814 install_element (OSPF_NODE, &capability_opaque_cmd);
815 install_element (OSPF_NODE, &no_capability_opaque_cmd);
816 install_element (OSPF_NODE, &ospf_opaque_capable_cmd);
817 install_element (OSPF_NODE, &no_ospf_opaque_capable_cmd);
818 return;
819}
820
821/*------------------------------------------------------------------------*
822 * Followings are collection of user-registered function callers.
823 *------------------------------------------------------------------------*/
824
825static int
paul87d6f872004-09-24 08:01:38 +0000826opaque_lsa_new_if_callback (struct list *funclist, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000827{
paul87d6f872004-09-24 08:01:38 +0000828 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000829 struct ospf_opaque_functab *functab;
830 int rc = -1;
831
paul87d6f872004-09-24 08:01:38 +0000832 LIST_LOOP (funclist, functab, node)
833 if (functab->new_if_hook != NULL)
834 if ((* functab->new_if_hook)(ifp) != 0)
835 goto out;
paul718e3742002-12-13 20:15:29 +0000836 rc = 0;
837out:
838 return rc;
839}
840
841static int
paul87d6f872004-09-24 08:01:38 +0000842opaque_lsa_del_if_callback (struct list *funclist, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000843{
paul87d6f872004-09-24 08:01:38 +0000844 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000845 struct ospf_opaque_functab *functab;
846 int rc = -1;
847
paul87d6f872004-09-24 08:01:38 +0000848 LIST_LOOP (funclist, functab, node)
849 if (functab->del_if_hook != NULL)
850 if ((* functab->del_if_hook)(ifp) != 0)
851 goto out;
paul718e3742002-12-13 20:15:29 +0000852 rc = 0;
853out:
854 return rc;
855}
856
857static void
paul87d6f872004-09-24 08:01:38 +0000858opaque_lsa_ism_change_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000859 struct ospf_interface *oi, int old_status)
860{
paul87d6f872004-09-24 08:01:38 +0000861 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000862 struct ospf_opaque_functab *functab;
863
paul87d6f872004-09-24 08:01:38 +0000864 LIST_LOOP (funclist, functab, node)
865 if (functab->ism_change_hook != NULL)
866 (* functab->ism_change_hook)(oi, old_status);
867
paul718e3742002-12-13 20:15:29 +0000868 return;
869}
870
871static void
paul87d6f872004-09-24 08:01:38 +0000872opaque_lsa_nsm_change_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000873 struct ospf_neighbor *nbr, int old_status)
874{
paul87d6f872004-09-24 08:01:38 +0000875 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000876 struct ospf_opaque_functab *functab;
877
paul87d6f872004-09-24 08:01:38 +0000878 LIST_LOOP (funclist, functab, node)
879 if (functab->nsm_change_hook != NULL)
880 (* functab->nsm_change_hook)(nbr, old_status);
paul718e3742002-12-13 20:15:29 +0000881 return;
882}
883
884static void
paul87d6f872004-09-24 08:01:38 +0000885opaque_lsa_config_write_router_callback (struct list *funclist,
886 struct vty *vty)
paul718e3742002-12-13 20:15:29 +0000887{
paul87d6f872004-09-24 08:01:38 +0000888 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000889 struct ospf_opaque_functab *functab;
890
paul87d6f872004-09-24 08:01:38 +0000891 LIST_LOOP (funclist, functab, node)
892 if (functab->config_write_router != NULL)
893 (* functab->config_write_router)(vty);
paul718e3742002-12-13 20:15:29 +0000894 return;
895}
896
897static void
paul87d6f872004-09-24 08:01:38 +0000898opaque_lsa_config_write_if_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000899 struct vty *vty, struct interface *ifp)
900{
paul87d6f872004-09-24 08:01:38 +0000901 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000902 struct ospf_opaque_functab *functab;
903
paul87d6f872004-09-24 08:01:38 +0000904 LIST_LOOP (funclist, functab, node)
905 if (functab->config_write_if != NULL)
906 (* functab->config_write_if)(vty, ifp);
paul718e3742002-12-13 20:15:29 +0000907 return;
908}
909
910static void
paul87d6f872004-09-24 08:01:38 +0000911opaque_lsa_config_write_debug_callback (struct list *funclist, struct vty *vty)
paul718e3742002-12-13 20:15:29 +0000912{
paul87d6f872004-09-24 08:01:38 +0000913 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000914 struct ospf_opaque_functab *functab;
915
paul87d6f872004-09-24 08:01:38 +0000916 LIST_LOOP (funclist, functab, node)
917 if (functab->config_write_debug != NULL)
918 (* functab->config_write_debug)(vty);
paul718e3742002-12-13 20:15:29 +0000919 return;
920}
921
922static int
paul87d6f872004-09-24 08:01:38 +0000923opaque_lsa_originate_callback (struct list *funclist, void *lsa_type_dependent)
paul718e3742002-12-13 20:15:29 +0000924{
paul87d6f872004-09-24 08:01:38 +0000925 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000926 struct ospf_opaque_functab *functab;
927 int rc = -1;
928
paul87d6f872004-09-24 08:01:38 +0000929 LIST_LOOP (funclist, functab, node)
930 if (functab->lsa_originator != NULL)
931 if ((* functab->lsa_originator)(lsa_type_dependent) != 0)
932 goto out;
paul718e3742002-12-13 20:15:29 +0000933 rc = 0;
934out:
935 return rc;
936}
937
938static int
paul87d6f872004-09-24 08:01:38 +0000939new_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000940{
paul87d6f872004-09-24 08:01:38 +0000941 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000942 struct ospf_opaque_functab *functab;
943 int rc = -1;
944
945 /* This function handles ALL types of LSAs, not only opaque ones. */
paul87d6f872004-09-24 08:01:38 +0000946 LIST_LOOP (funclist, functab, node)
947 if (functab->new_lsa_hook != NULL)
948 if ((* functab->new_lsa_hook)(lsa) != 0)
949 goto out;
paul718e3742002-12-13 20:15:29 +0000950 rc = 0;
951out:
952 return rc;
953}
954
955static int
paul87d6f872004-09-24 08:01:38 +0000956del_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000957{
paul87d6f872004-09-24 08:01:38 +0000958 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000959 struct ospf_opaque_functab *functab;
960 int rc = -1;
961
962 /* This function handles ALL types of LSAs, not only opaque ones. */
paul87d6f872004-09-24 08:01:38 +0000963 LIST_LOOP (funclist, functab, node)
964 if (functab->del_lsa_hook != NULL)
965 if ((* functab->del_lsa_hook)(lsa) != 0)
966 goto out;
paul718e3742002-12-13 20:15:29 +0000967 rc = 0;
968out:
969 return rc;
970}
971
972/*------------------------------------------------------------------------*
973 * Followings are glue functions to call Opaque-LSA specific processing.
974 *------------------------------------------------------------------------*/
975
976int
977ospf_opaque_new_if (struct interface *ifp)
978{
paul87d6f872004-09-24 08:01:38 +0000979 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000980 int rc = -1;
981
paul09e4efd2003-01-18 00:12:02 +0000982 funclist = ospf_opaque_wildcard_funclist;
983 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
984 goto out;
985
paul718e3742002-12-13 20:15:29 +0000986 funclist = ospf_opaque_type9_funclist;
987 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
988 goto out;
989
990 funclist = ospf_opaque_type10_funclist;
991 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
992 goto out;
993
994 funclist = ospf_opaque_type11_funclist;
995 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
996 goto out;
997
998 rc = 0;
999out:
1000 return rc;
1001}
1002
1003int
1004ospf_opaque_del_if (struct interface *ifp)
1005{
paul87d6f872004-09-24 08:01:38 +00001006 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001007 int rc = -1;
1008
paul09e4efd2003-01-18 00:12:02 +00001009 funclist = ospf_opaque_wildcard_funclist;
1010 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1011 goto out;
1012
paul718e3742002-12-13 20:15:29 +00001013 funclist = ospf_opaque_type9_funclist;
1014 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1015 goto out;
1016
1017 funclist = ospf_opaque_type10_funclist;
1018 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1019 goto out;
1020
1021 funclist = ospf_opaque_type11_funclist;
1022 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1023 goto out;
1024
1025 rc = 0;
1026out:
1027 return rc;
1028}
1029
1030void
1031ospf_opaque_ism_change (struct ospf_interface *oi, int old_status)
1032{
paul87d6f872004-09-24 08:01:38 +00001033 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001034
paul09e4efd2003-01-18 00:12:02 +00001035 funclist = ospf_opaque_wildcard_funclist;
1036 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1037
paul718e3742002-12-13 20:15:29 +00001038 funclist = ospf_opaque_type9_funclist;
1039 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1040
1041 funclist = ospf_opaque_type10_funclist;
1042 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1043
1044 funclist = ospf_opaque_type11_funclist;
1045 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1046
1047 return;
1048}
1049
1050void
1051ospf_opaque_nsm_change (struct ospf_neighbor *nbr, int old_state)
1052{
1053 struct ospf *top;
paul87d6f872004-09-24 08:01:38 +00001054 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001055
1056 if ((top = oi_to_top (nbr->oi)) == NULL)
1057 goto out;
1058
1059 if (old_state != NSM_Full && nbr->state == NSM_Full)
1060 {
1061 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
1062 {
1063 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1064 {
1065 if (IS_DEBUG_OSPF_EVENT)
1066 zlog_info ("Opaque-LSA: Now get operational!");
1067
1068 SET_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT);
1069 }
1070
1071 ospf_opaque_lsa_originate_schedule (nbr->oi, NULL);
1072 }
1073 }
1074 else
1075 if (old_state == NSM_Full && nbr->state != NSM_Full)
1076 {
1077#ifdef NOTYET
1078 /*
1079 * If no more opaque-capable full-state neighbor remains in the
1080 * flooding scope which corresponds to Opaque-LSA type, periodic
1081 * LS flooding should be stopped.
1082 */
1083#endif /* NOTYET */
1084 ;
1085 }
1086
paul09e4efd2003-01-18 00:12:02 +00001087 funclist = ospf_opaque_wildcard_funclist;
1088 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1089
paul718e3742002-12-13 20:15:29 +00001090 funclist = ospf_opaque_type9_funclist;
1091 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1092
1093 funclist = ospf_opaque_type10_funclist;
1094 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1095
1096 funclist = ospf_opaque_type11_funclist;
1097 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1098
1099out:
1100 return;
1101}
1102
1103void
1104ospf_opaque_config_write_router (struct vty *vty, struct ospf *ospf)
1105{
paul87d6f872004-09-24 08:01:38 +00001106 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001107
1108 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
1109 vty_out (vty, " capability opaque%s", VTY_NEWLINE);
1110
paul09e4efd2003-01-18 00:12:02 +00001111 funclist = ospf_opaque_wildcard_funclist;
1112 opaque_lsa_config_write_router_callback (funclist, vty);
1113
paul718e3742002-12-13 20:15:29 +00001114 funclist = ospf_opaque_type9_funclist;
1115 opaque_lsa_config_write_router_callback (funclist, vty);
1116
1117 funclist = ospf_opaque_type10_funclist;
1118 opaque_lsa_config_write_router_callback (funclist, vty);
1119
1120 funclist = ospf_opaque_type11_funclist;
1121 opaque_lsa_config_write_router_callback (funclist, vty);
1122
1123 return;
1124}
1125
1126void
1127ospf_opaque_config_write_if (struct vty *vty, struct interface *ifp)
1128{
paul87d6f872004-09-24 08:01:38 +00001129 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001130
paul09e4efd2003-01-18 00:12:02 +00001131 funclist = ospf_opaque_wildcard_funclist;
1132 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1133
paul718e3742002-12-13 20:15:29 +00001134 funclist = ospf_opaque_type9_funclist;
1135 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1136
1137 funclist = ospf_opaque_type10_funclist;
1138 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1139
1140 funclist = ospf_opaque_type11_funclist;
1141 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1142
1143 return;
1144}
1145
1146void
1147ospf_opaque_config_write_debug (struct vty *vty)
1148{
paul87d6f872004-09-24 08:01:38 +00001149 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001150
paul09e4efd2003-01-18 00:12:02 +00001151 funclist = ospf_opaque_wildcard_funclist;
1152 opaque_lsa_config_write_debug_callback (funclist, vty);
1153
paul718e3742002-12-13 20:15:29 +00001154 funclist = ospf_opaque_type9_funclist;
1155 opaque_lsa_config_write_debug_callback (funclist, vty);
1156
1157 funclist = ospf_opaque_type10_funclist;
1158 opaque_lsa_config_write_debug_callback (funclist, vty);
1159
1160 funclist = ospf_opaque_type11_funclist;
1161 opaque_lsa_config_write_debug_callback (funclist, vty);
1162
1163 return;
1164}
1165
1166void
1167show_opaque_info_detail (struct vty *vty, struct ospf_lsa *lsa)
1168{
1169 struct lsa_header *lsah = (struct lsa_header *) lsa->data;
1170 u_int32_t lsid = ntohl (lsah->id.s_addr);
1171 u_char opaque_type = GET_OPAQUE_TYPE (lsid);
1172 u_int32_t opaque_id = GET_OPAQUE_ID (lsid);
1173 struct ospf_opaque_functab *functab;
1174
1175 /* Switch output functionality by vty address. */
1176 if (vty != NULL)
1177 {
paul020709f2003-04-04 02:44:16 +00001178 vty_out (vty, " Opaque-Type %u (%s)%s", opaque_type,
1179 ospf_opaque_type_name (opaque_type), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001180 vty_out (vty, " Opaque-ID 0x%x%s", opaque_id, VTY_NEWLINE);
1181
1182 vty_out (vty, " Opaque-Info: %u octets of data%s%s",
1183 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1184 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)",
1185 VTY_NEWLINE);
1186 }
1187 else
1188 {
paul020709f2003-04-04 02:44:16 +00001189 zlog_info (" Opaque-Type %u (%s)", opaque_type,
1190 ospf_opaque_type_name (opaque_type));
paul718e3742002-12-13 20:15:29 +00001191 zlog_info (" Opaque-ID 0x%x", opaque_id);
1192
1193 zlog_info (" Opaque-Info: %u octets of data%s",
1194 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1195 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)");
1196 }
1197
1198 /* Call individual output functions. */
1199 if ((functab = ospf_opaque_functab_lookup (lsa)) != NULL)
1200 if (functab->show_opaque_info != NULL)
1201 (* functab->show_opaque_info)(vty, lsa);
1202
1203 return;
1204}
1205
1206void
1207ospf_opaque_lsa_dump (struct stream *s, u_int16_t length)
1208{
1209 struct ospf_lsa lsa;
1210
1211 lsa.data = (struct lsa_header *) STREAM_PNT (s);
1212 show_opaque_info_detail (NULL, &lsa);
1213 return;
1214}
1215
1216static int
1217ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa)
1218{
paul87d6f872004-09-24 08:01:38 +00001219 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001220 int rc = -1;
1221
1222 /*
1223 * Some Opaque-LSA user may want to monitor every LSA installation
1224 * into the LSDB, regardless with target LSA type.
1225 */
paul09e4efd2003-01-18 00:12:02 +00001226 funclist = ospf_opaque_wildcard_funclist;
1227 if (new_lsa_callback (funclist, lsa) != 0)
1228 goto out;
1229
paul718e3742002-12-13 20:15:29 +00001230 funclist = ospf_opaque_type9_funclist;
1231 if (new_lsa_callback (funclist, lsa) != 0)
1232 goto out;
1233
1234 funclist = ospf_opaque_type10_funclist;
1235 if (new_lsa_callback (funclist, lsa) != 0)
1236 goto out;
1237
1238 funclist = ospf_opaque_type11_funclist;
1239 if (new_lsa_callback (funclist, lsa) != 0)
1240 goto out;
1241
1242 rc = 0;
1243out:
1244 return rc;
1245}
1246
1247static int
1248ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa)
1249{
paul87d6f872004-09-24 08:01:38 +00001250 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001251 int rc = -1;
1252
1253 /*
1254 * Some Opaque-LSA user may want to monitor every LSA deletion
1255 * from the LSDB, regardless with target LSA type.
1256 */
paul09e4efd2003-01-18 00:12:02 +00001257 funclist = ospf_opaque_wildcard_funclist;
1258 if (del_lsa_callback (funclist, lsa) != 0)
1259 goto out;
1260
paul718e3742002-12-13 20:15:29 +00001261 funclist = ospf_opaque_type9_funclist;
1262 if (del_lsa_callback (funclist, lsa) != 0)
1263 goto out;
1264
1265 funclist = ospf_opaque_type10_funclist;
1266 if (del_lsa_callback (funclist, lsa) != 0)
1267 goto out;
1268
1269 funclist = ospf_opaque_type11_funclist;
1270 if (del_lsa_callback (funclist, lsa) != 0)
1271 goto out;
1272
1273 rc = 0;
1274out:
1275 return rc;
1276}
1277
1278/*------------------------------------------------------------------------*
1279 * Followings are Opaque-LSA origination/refresh management functions.
1280 *------------------------------------------------------------------------*/
1281
1282static int ospf_opaque_type9_lsa_originate (struct thread *t);
1283static int ospf_opaque_type10_lsa_originate (struct thread *t);
1284static int ospf_opaque_type11_lsa_originate (struct thread *t);
paul87d6f872004-09-24 08:01:38 +00001285static void ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg);
paul718e3742002-12-13 20:15:29 +00001286
1287void
1288ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0)
1289{
1290 struct ospf *top;
1291 struct ospf_area *area;
paul87d6f872004-09-24 08:01:38 +00001292 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001293 struct opaque_info_per_type *oipt;
1294 int delay = 0;
1295
1296 if ((top = oi_to_top (oi)) == NULL || (area = oi->area) == NULL)
1297 {
1298 zlog_warn ("ospf_opaque_lsa_originate_schedule: Invalid argument?");
1299 goto out;
1300 }
1301
1302 /* It may not a right time to schedule origination now. */
1303 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1304 {
1305 if (IS_DEBUG_OSPF_EVENT)
1306 zlog_info ("ospf_opaque_lsa_originate_schedule: Not operational.");
1307 goto out; /* This is not an error. */
1308 }
1309 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
1310 {
1311 if (IS_DEBUG_OSPF_EVENT)
1312 zlog_info ("ospf_opaque_lsa_originate_schedule: Under blockade.");
1313 goto out; /* This is not an error, too. */
1314 }
1315
1316 if (delay0 != NULL)
1317 delay = *delay0;
1318
1319 /*
1320 * There might be some entries that have been waiting for triggering
1321 * of per opaque-type re-origination get resumed.
1322 */
1323 ospf_opaque_lsa_reoriginate_resume ( oi->opaque_lsa_self, (void *) oi);
1324 ospf_opaque_lsa_reoriginate_resume (area->opaque_lsa_self, (void *) area);
1325 ospf_opaque_lsa_reoriginate_resume ( top->opaque_lsa_self, (void *) top);
1326
1327 /*
1328 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1329 */
1330 if (! list_isempty (ospf_opaque_type9_funclist)
1331 && list_isempty (oi->opaque_lsa_self)
1332 && oi->t_opaque_lsa_self == NULL)
1333 {
1334 if (IS_DEBUG_OSPF_EVENT)
1335 zlog_info ("Schedule Type-9 Opaque-LSA origination in %d sec later.", delay);
1336 oi->t_opaque_lsa_self =
1337 thread_add_timer (master, ospf_opaque_type9_lsa_originate, oi, delay);
1338 delay += OSPF_MIN_LS_INTERVAL;
1339 }
1340
1341 if (! list_isempty (ospf_opaque_type10_funclist)
1342 && list_isempty (area->opaque_lsa_self)
1343 && area->t_opaque_lsa_self == NULL)
1344 {
1345 /*
1346 * One AREA may contain multiple OIs, but above 2nd and 3rd
1347 * conditions prevent from scheduling the originate function
1348 * again and again.
1349 */
1350 if (IS_DEBUG_OSPF_EVENT)
1351 zlog_info ("Schedule Type-10 Opaque-LSA origination in %d sec later.", delay);
1352 area->t_opaque_lsa_self =
1353 thread_add_timer (master, ospf_opaque_type10_lsa_originate,
1354 area, delay);
1355 delay += OSPF_MIN_LS_INTERVAL;
1356 }
1357
1358 if (! list_isempty (ospf_opaque_type11_funclist)
1359 && list_isempty (top->opaque_lsa_self)
1360 && top->t_opaque_lsa_self == NULL)
1361 {
1362 /*
1363 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1364 * conditions prevent from scheduling the originate function
1365 * again and again.
1366 */
1367 if (IS_DEBUG_OSPF_EVENT)
1368 zlog_info ("Schedule Type-11 Opaque-LSA origination in %d sec later.", delay);
1369 top->t_opaque_lsa_self =
1370 thread_add_timer (master, ospf_opaque_type11_lsa_originate,
1371 top, delay);
1372 delay += OSPF_MIN_LS_INTERVAL;
1373 }
1374
1375 /*
1376 * Following section treats a special situation that this node's
1377 * opaque capability has changed as "ON -> OFF -> ON".
1378 */
1379 if (! list_isempty (ospf_opaque_type9_funclist)
1380 && ! list_isempty (oi->opaque_lsa_self))
1381 {
1382 for (node = listhead (oi->opaque_lsa_self); node; nextnode (node))
1383 {
hasso0d85b992004-03-18 19:18:33 +00001384 /*
1385 * removed the test for
1386 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1387 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1388 * not being empty.
1389 */
paul718e3742002-12-13 20:15:29 +00001390 if ((oipt = getdata (node)) == NULL /* Something wrong? */
1391 || oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
hasso0d85b992004-03-18 19:18:33 +00001392 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001393 continue;
1394
1395 ospf_opaque_lsa_reoriginate_schedule ((void *) oi,
1396 OSPF_OPAQUE_LINK_LSA, oipt->opaque_type);
1397 }
1398 }
1399
1400 if (! list_isempty (ospf_opaque_type10_funclist)
1401 && ! list_isempty (area->opaque_lsa_self))
1402 {
1403 for (node = listhead (area->opaque_lsa_self); node; nextnode (node))
1404 {
hasso0d85b992004-03-18 19:18:33 +00001405 /*
1406 * removed the test for
1407 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1408 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1409 * not being empty.
1410 */
paul718e3742002-12-13 20:15:29 +00001411 if ((oipt = getdata (node)) == NULL /* Something wrong? */
1412 || oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
hasso0d85b992004-03-18 19:18:33 +00001413 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001414 continue;
1415
1416 ospf_opaque_lsa_reoriginate_schedule ((void *) area,
1417 OSPF_OPAQUE_AREA_LSA, oipt->opaque_type);
1418 }
1419 }
1420
1421 if (! list_isempty (ospf_opaque_type11_funclist)
1422 && ! list_isempty (top->opaque_lsa_self))
1423 {
1424 for (node = listhead (top->opaque_lsa_self); node; nextnode (node))
1425 {
hasso0d85b992004-03-18 19:18:33 +00001426 /*
1427 * removed the test for
1428 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1429 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1430 * not being empty.
1431 */
paul718e3742002-12-13 20:15:29 +00001432 if ((oipt = getdata (node)) == NULL /* Something wrong? */
1433 || oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
hasso0d85b992004-03-18 19:18:33 +00001434 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001435 continue;
1436
1437 ospf_opaque_lsa_reoriginate_schedule ((void *) top,
1438 OSPF_OPAQUE_AS_LSA, oipt->opaque_type);
1439 }
1440 }
1441
1442 if (delay0 != NULL)
1443 *delay0 = delay;
1444
1445out:
1446 return;
1447}
1448
1449static int
1450ospf_opaque_type9_lsa_originate (struct thread *t)
1451{
1452 struct ospf_interface *oi;
1453 int rc;
1454
1455 oi = THREAD_ARG (t);
1456 oi->t_opaque_lsa_self = NULL;
1457
1458 if (IS_DEBUG_OSPF_EVENT)
1459 zlog_info ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
1460 IF_NAME (oi));
1461
1462 rc = opaque_lsa_originate_callback (ospf_opaque_type9_funclist, oi);
1463
1464 return rc;
1465}
1466
1467static int
1468ospf_opaque_type10_lsa_originate (struct thread *t)
1469{
1470 struct ospf_area *area;
1471 int rc;
1472
1473 area = THREAD_ARG (t);
1474 area->t_opaque_lsa_self = NULL;
1475
1476 if (IS_DEBUG_OSPF_EVENT)
1477 zlog_info ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
1478 inet_ntoa (area->area_id));
1479
1480 rc = opaque_lsa_originate_callback (ospf_opaque_type10_funclist, area);
1481
1482 return rc;
1483}
1484
1485static int
1486ospf_opaque_type11_lsa_originate (struct thread *t)
1487{
1488 struct ospf *top;
1489 int rc;
1490
1491 top = THREAD_ARG (t);
1492 top->t_opaque_lsa_self = NULL;
1493
1494 if (IS_DEBUG_OSPF_EVENT)
1495 zlog_info ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
1496
1497 rc = opaque_lsa_originate_callback (ospf_opaque_type11_funclist, top);
1498
1499 return rc;
1500}
1501
1502static void
paul87d6f872004-09-24 08:01:38 +00001503ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg)
paul718e3742002-12-13 20:15:29 +00001504{
paul87d6f872004-09-24 08:01:38 +00001505 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001506 struct opaque_info_per_type *oipt;
1507 struct ospf_opaque_functab *functab;
1508
1509 if (listtop == NULL)
1510 goto out;
1511
1512 /*
1513 * Pickup oipt entries those which in SUSPEND status, and give
1514 * them a chance to start re-origination now.
1515 */
paul87d6f872004-09-24 08:01:38 +00001516 LIST_LOOP (listtop, oipt, node)
paul718e3742002-12-13 20:15:29 +00001517 {
paul87d6f872004-09-24 08:01:38 +00001518 if (oipt->status != PROC_SUSPEND)
paul718e3742002-12-13 20:15:29 +00001519 continue;
1520
1521 oipt->status = PROC_NORMAL;
1522
1523 if ((functab = oipt->functab) == NULL
paul87d6f872004-09-24 08:01:38 +00001524 || functab->lsa_originator == NULL)
paul718e3742002-12-13 20:15:29 +00001525 continue;
1526
1527 if ((* functab->lsa_originator)(arg) != 0)
1528 {
1529 zlog_warn ("ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", oipt->opaque_type);
1530 continue;
1531 }
1532 }
1533
1534out:
1535 return;
1536}
1537
1538struct ospf_lsa *
1539ospf_opaque_lsa_install (struct ospf_lsa *lsa, int rt_recalc)
1540{
1541 struct ospf_lsa *new = NULL;
1542 struct opaque_info_per_type *oipt;
1543 struct opaque_info_per_id *oipi;
1544 struct ospf *top;
1545
1546 /* Don't take "rt_recalc" into consideration for now. *//* XXX */
1547
1548 if (! IS_LSA_SELF (lsa))
1549 {
1550 new = lsa; /* Don't touch this LSA. */
1551 goto out;
1552 }
1553
1554 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
1555 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)));
1556
1557 /* Replace the existing lsa with the new one. */
1558 if ((oipt = lookup_opaque_info_by_type (lsa)) != NULL
paul87d6f872004-09-24 08:01:38 +00001559 && (oipi = lookup_opaque_info_by_id (oipt, lsa)) != NULL)
paul718e3742002-12-13 20:15:29 +00001560 {
1561 ospf_lsa_unlock (oipi->lsa);
1562 oipi->lsa = ospf_lsa_lock (lsa);
1563 }
1564 /* Register the new lsa entry and get its control info. */
1565 else
1566 if ((oipi = register_opaque_lsa (lsa)) == NULL)
1567 {
1568 zlog_warn ("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1569 goto out;
1570 }
1571
1572 /*
1573 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1574 * for periodic refresh of self-originated Opaque-LSAs.
1575 */
1576 switch (lsa->data->type)
1577 {
1578 case OSPF_OPAQUE_LINK_LSA:
paul09e4efd2003-01-18 00:12:02 +00001579 if ((top = oi_to_top (lsa->oi)) == NULL)
1580 {
1581 /* Above conditions must have passed. */
1582 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1583 goto out;
1584 }
1585 break;
paul718e3742002-12-13 20:15:29 +00001586 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00001587 if (lsa->area == NULL || (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001588 {
1589 /* Above conditions must have passed. */
1590 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1591 goto out;
1592 }
1593 break;
1594 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +00001595 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001596 if (lsa->area != NULL && (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001597 {
1598 /* Above conditions must have passed. */
1599 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1600 goto out;
1601 }
1602 break;
1603 default:
1604 zlog_warn ("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", lsa->data->type);
1605 goto out;
1606 }
1607
1608 ospf_refresher_register_lsa (top, lsa);
1609 new = lsa;
1610
1611out:
1612 return new;
1613}
1614
1615void
1616ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
1617{
paul020709f2003-04-04 02:44:16 +00001618 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001619 struct ospf_opaque_functab *functab;
1620
paul020709f2003-04-04 02:44:16 +00001621 ospf = ospf_lookup ();
1622
paul718e3742002-12-13 20:15:29 +00001623 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL
paul87d6f872004-09-24 08:01:38 +00001624 || functab->lsa_refresher == NULL)
paul718e3742002-12-13 20:15:29 +00001625 {
1626 /*
1627 * Though this LSA seems to have originated on this node, the
1628 * handling module for this "lsa-type and opaque-type" was
1629 * already deleted sometime ago.
1630 * Anyway, this node still has a responsibility to flush this
1631 * LSA from the routing domain.
1632 */
1633 if (IS_DEBUG_OSPF_EVENT)
1634 zlog_info ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id));
1635
1636 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
paul68980082003-03-25 05:07:42 +00001637 ospf_lsa_maxage (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00001638 }
1639 else
1640 (* functab->lsa_refresher)(lsa);
1641
1642 return;
1643}
1644
1645/*------------------------------------------------------------------------*
1646 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1647 * triggered by external interventions (vty session, signaling, etc).
1648 *------------------------------------------------------------------------*/
1649
1650#define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
1651 if (!(T)) \
1652 (T) = thread_add_timer (master, (F), (L), (V))
1653
1654static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type);
1655static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t);
1656static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t);
1657static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t);
1658static int ospf_opaque_lsa_refresh_timer (struct thread *t);
1659
1660void
1661ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
1662 u_char lsa_type, u_char opaque_type)
1663{
1664 struct ospf *top;
1665 struct ospf_area dummy, *area = NULL;
1666 struct ospf_interface *oi = NULL;
1667
1668 struct ospf_lsa *lsa;
1669 struct opaque_info_per_type *oipt;
paul87d6f872004-09-24 08:01:38 +00001670 int (*func) (struct thread * t) = NULL;
paul718e3742002-12-13 20:15:29 +00001671 int delay;
1672
1673 switch (lsa_type)
1674 {
1675 case OSPF_OPAQUE_LINK_LSA:
1676 if ((oi = (struct ospf_interface *) lsa_type_dependent) == NULL)
1677 {
paul87d6f872004-09-24 08:01:38 +00001678 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1679 " Type-9 Opaque-LSA: Invalid parameter?");
1680 goto out;
paul718e3742002-12-13 20:15:29 +00001681 }
1682 if ((top = oi_to_top (oi)) == NULL)
1683 {
paul87d6f872004-09-24 08:01:38 +00001684 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1685 IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001686 goto out;
1687 }
paul87d6f872004-09-24 08:01:38 +00001688 if (!list_isempty (ospf_opaque_type9_funclist)
1689 && list_isempty (oi->opaque_lsa_self)
1690 && oi->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001691 {
paul87d6f872004-09-24 08:01:38 +00001692 zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u):"
1693 " Common origination for OI(%s) has already started",
1694 opaque_type, IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001695 goto out;
1696 }
1697 func = ospf_opaque_type9_lsa_reoriginate_timer;
1698 break;
1699 case OSPF_OPAQUE_AREA_LSA:
1700 if ((area = (struct ospf_area *) lsa_type_dependent) == NULL)
1701 {
paul87d6f872004-09-24 08:01:38 +00001702 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1703 " Type-10 Opaque-LSA: Invalid parameter?");
paul718e3742002-12-13 20:15:29 +00001704 goto out;
1705 }
paul68980082003-03-25 05:07:42 +00001706 if ((top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001707 {
paul87d6f872004-09-24 08:01:38 +00001708 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1709 " AREA(%s) -> TOP?", inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001710 goto out;
1711 }
paul87d6f872004-09-24 08:01:38 +00001712 if (!list_isempty (ospf_opaque_type10_funclist)
1713 && list_isempty (area->opaque_lsa_self)
1714 && area->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001715 {
paul87d6f872004-09-24 08:01:38 +00001716 zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u):"
1717 " Common origination for AREA(%s) has already started",
1718 opaque_type, inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001719 goto out;
1720 }
1721 func = ospf_opaque_type10_lsa_reoriginate_timer;
1722 break;
1723 case OSPF_OPAQUE_AS_LSA:
1724 if ((top = (struct ospf *) lsa_type_dependent) == NULL)
1725 {
paul87d6f872004-09-24 08:01:38 +00001726 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1727 " Type-11 Opaque-LSA: Invalid parameter?");
1728 goto out;
paul718e3742002-12-13 20:15:29 +00001729 }
paul87d6f872004-09-24 08:01:38 +00001730 if (!list_isempty (ospf_opaque_type11_funclist)
1731 && list_isempty (top->opaque_lsa_self)
1732 && top->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001733 {
paul87d6f872004-09-24 08:01:38 +00001734 zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u):"
1735 " Common origination has already started", opaque_type);
paul718e3742002-12-13 20:15:29 +00001736 goto out;
1737 }
1738
1739 /* Fake "area" to pass "ospf" to a lookup function later. */
paul68980082003-03-25 05:07:42 +00001740 dummy.ospf = top;
paul718e3742002-12-13 20:15:29 +00001741 area = &dummy;
1742
1743 func = ospf_opaque_type11_lsa_reoriginate_timer;
1744 break;
1745 default:
paul87d6f872004-09-24 08:01:38 +00001746 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1747 " Unexpected LSA-type(%u)",
1748 lsa_type);
paul718e3742002-12-13 20:15:29 +00001749 goto out;
1750 }
1751
1752 /* It may not a right time to schedule reorigination now. */
paul87d6f872004-09-24 08:01:38 +00001753 if (!CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
paul718e3742002-12-13 20:15:29 +00001754 {
1755 if (IS_DEBUG_OSPF_EVENT)
1756 zlog_info ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
paul87d6f872004-09-24 08:01:38 +00001757 goto out; /* This is not an error. */
paul718e3742002-12-13 20:15:29 +00001758 }
1759 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
1760 {
1761 if (IS_DEBUG_OSPF_EVENT)
1762 zlog_info ("ospf_opaque_lsa_reoriginate_schedule: Under blockade.");
paul87d6f872004-09-24 08:01:38 +00001763 goto out; /* This is not an error, too. */
paul718e3742002-12-13 20:15:29 +00001764 }
1765
1766 /* Generate a dummy lsa to be passed for a lookup function. */
1767 lsa = pseudo_lsa (oi, area, lsa_type, opaque_type);
1768
1769 if ((oipt = lookup_opaque_info_by_type (lsa)) == NULL)
1770 {
1771 struct ospf_opaque_functab *functab;
1772 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL)
1773 {
paul87d6f872004-09-24 08:01:38 +00001774 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1775 " No associated function?: lsa_type(%u),"
1776 " opaque_type(%u)",
1777 lsa_type, opaque_type);
paul718e3742002-12-13 20:15:29 +00001778 goto out;
1779 }
1780 if ((oipt = register_opaque_info_per_type (functab, lsa)) == NULL)
1781 {
paul87d6f872004-09-24 08:01:38 +00001782 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1783 " Cannot get a control info?: lsa_type(%u),"
1784 " opaque_type(%u)",
1785 lsa_type, opaque_type);
paul718e3742002-12-13 20:15:29 +00001786 goto out;
1787 }
1788 }
1789
1790 if (oipt->t_opaque_lsa_self != NULL)
1791 {
1792 if (IS_DEBUG_OSPF_EVENT)
paul87d6f872004-09-24 08:01:38 +00001793 zlog_info ("Type-%u Opaque-LSA has already scheduled to"
1794 " RE-ORIGINATE: [opaque-type=%u]",
1795 lsa_type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
paul718e3742002-12-13 20:15:29 +00001796 goto out;
1797 }
1798
1799 /*
1800 * Different from initial origination time, in which various conditions
1801 * (opaque capability, neighbor status etc) are assured by caller of
1802 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1803 * it is highly possible that these conditions might not be satisfied
1804 * at the time of re-origination function is to be called.
1805 */
1806 delay = OSPF_MIN_LS_INTERVAL; /* XXX */
1807
1808 if (IS_DEBUG_OSPF_EVENT)
paul87d6f872004-09-24 08:01:38 +00001809 zlog_info ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
1810 " sec later: [opaque-type=%u]",
1811 lsa_type, delay,
1812 GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
paul718e3742002-12-13 20:15:29 +00001813
1814 OSPF_OPAQUE_TIMER_ON (oipt->t_opaque_lsa_self, func, oipt, delay);
1815
1816out:
1817 return;
1818}
1819
1820static struct ospf_lsa *
1821pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area,
1822 u_char lsa_type, u_char opaque_type)
1823{
1824 static struct ospf_lsa lsa = { 0 };
1825 static struct lsa_header lsah = { 0 };
1826 u_int32_t tmp;
1827
1828 lsa.oi = oi;
1829 lsa.area = area;
1830 lsa.data = &lsah;
1831
1832 lsah.type = lsa_type;
1833 tmp = SET_OPAQUE_LSID (opaque_type, 0); /* Opaque-ID is unused here. */
1834 lsah.id.s_addr = htonl (tmp);
1835
1836 return &lsa;
1837}
1838
1839static int
1840ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t)
1841{
1842 struct opaque_info_per_type *oipt;
1843 struct ospf_opaque_functab *functab;
1844 struct ospf *top;
1845 struct ospf_interface *oi;
1846 int rc = -1;
1847
1848 oipt = THREAD_ARG (t);
1849 oipt->t_opaque_lsa_self = NULL;
1850
1851 if ((functab = oipt->functab) == NULL
1852 || functab->lsa_originator == NULL)
1853 {
1854 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1855 goto out;
1856 }
1857
1858 oi = (struct ospf_interface *) oipt->owner;
1859 if ((top = oi_to_top (oi)) == NULL)
1860 {
1861 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1862 goto out;
1863 }
1864
1865 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)
1866 || ! ospf_if_is_enable (oi)
paul68980082003-03-25 05:07:42 +00001867 || ospf_nbr_count_opaque_capable (oi) == 0)
paul718e3742002-12-13 20:15:29 +00001868 {
1869 if (IS_DEBUG_OSPF_EVENT)
1870 zlog_info ("Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
1871
1872 oipt->status = PROC_SUSPEND;
1873 rc = 0;
1874 goto out;
1875 }
1876
1877 if (IS_DEBUG_OSPF_EVENT)
1878 zlog_info ("Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)", oipt->opaque_type, IF_NAME (oi));
1879
1880 rc = (* functab->lsa_originator)(oi);
1881out:
1882 return rc;
1883}
1884
1885static int
1886ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t)
1887{
1888 struct opaque_info_per_type *oipt;
1889 struct ospf_opaque_functab *functab;
paul87d6f872004-09-24 08:01:38 +00001890 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001891 struct ospf *top;
1892 struct ospf_area *area;
1893 struct ospf_interface *oi;
1894 int n, rc = -1;
1895
1896 oipt = THREAD_ARG (t);
1897 oipt->t_opaque_lsa_self = NULL;
1898
1899 if ((functab = oipt->functab) == NULL
1900 || functab->lsa_originator == NULL)
1901 {
1902 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1903 goto out;
1904 }
1905
1906 area = (struct ospf_area *) oipt->owner;
paul68980082003-03-25 05:07:42 +00001907 if (area == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001908 {
1909 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1910 goto out;
1911 }
1912
1913 /* There must be at least one "opaque-capable, full-state" neighbor. */
1914 n = 0;
paul87d6f872004-09-24 08:01:38 +00001915 LIST_LOOP (area->oiflist, oi, node)
paul718e3742002-12-13 20:15:29 +00001916 {
paul68980082003-03-25 05:07:42 +00001917 if ((n = ospf_nbr_count_opaque_capable (oi)) > 0)
paul718e3742002-12-13 20:15:29 +00001918 break;
1919 }
1920
1921 if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1922 {
1923 if (IS_DEBUG_OSPF_EVENT)
paul87d6f872004-09-24 08:01:38 +00001924 zlog_info ("Suspend re-origination of Type-10 Opaque-LSAs"
1925 " (opaque-type=%u) for a while...",
1926 oipt->opaque_type);
paul718e3742002-12-13 20:15:29 +00001927
1928 oipt->status = PROC_SUSPEND;
1929 rc = 0;
1930 goto out;
1931 }
1932
1933 if (IS_DEBUG_OSPF_EVENT)
paul87d6f872004-09-24 08:01:38 +00001934 zlog_info ("Timer[Type10-LSA]: Re-originate Opaque-LSAs"
1935 " (opaque-type=%u) for Area %s",
1936 oipt->opaque_type, inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001937
1938 rc = (* functab->lsa_originator)(area);
1939out:
1940 return rc;
1941}
1942
1943static int
1944ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t)
1945{
1946 struct opaque_info_per_type *oipt;
1947 struct ospf_opaque_functab *functab;
1948 struct ospf *top;
1949 int rc = -1;
1950
1951 oipt = THREAD_ARG (t);
1952 oipt->t_opaque_lsa_self = NULL;
1953
1954 if ((functab = oipt->functab) == NULL
paul87d6f872004-09-24 08:01:38 +00001955 || functab->lsa_originator == NULL)
paul718e3742002-12-13 20:15:29 +00001956 {
paul87d6f872004-09-24 08:01:38 +00001957 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer:"
1958 " No associated function?");
paul718e3742002-12-13 20:15:29 +00001959 goto out;
1960 }
1961
1962 if ((top = (struct ospf *) oipt->owner) == NULL)
1963 {
1964 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1965 goto out;
1966 }
1967
1968 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1969 {
1970 if (IS_DEBUG_OSPF_EVENT)
1971 zlog_info ("Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
1972
1973 oipt->status = PROC_SUSPEND;
1974 rc = 0;
1975 goto out;
1976 }
1977
1978 if (IS_DEBUG_OSPF_EVENT)
1979 zlog_info ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type);
1980
1981 rc = (* functab->lsa_originator)(top);
1982out:
1983 return rc;
1984}
1985
1986extern int ospf_lsa_refresh_delay (struct ospf_lsa *); /* ospf_lsa.c */
1987
1988void
1989ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
1990{
paul020709f2003-04-04 02:44:16 +00001991 struct ospf *ospf = ospf;
paul718e3742002-12-13 20:15:29 +00001992 struct opaque_info_per_type *oipt;
1993 struct opaque_info_per_id *oipi;
1994 struct ospf_lsa *lsa;
1995 int delay;
1996
paul020709f2003-04-04 02:44:16 +00001997 ospf = ospf_lookup ();
1998
paul718e3742002-12-13 20:15:29 +00001999 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
2000 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
2001 {
2002 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
2003 goto out;
2004 }
2005
2006 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2007 if ((lsa = oipi->lsa) == NULL)
2008 {
2009 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
2010 goto out;
2011 }
2012
2013 if (oipi->t_opaque_lsa_self != NULL)
2014 {
2015 if (IS_DEBUG_OSPF_EVENT)
2016 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)));
2017 goto out;
2018 }
2019
2020 /* Delete this lsa from neighbor retransmit-list. */
2021 switch (lsa->data->type)
2022 {
2023 case OSPF_OPAQUE_LINK_LSA:
2024 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002025 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002026 break;
2027 case OSPF_OPAQUE_AS_LSA:
paul68980082003-03-25 05:07:42 +00002028 ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002029 break;
2030 default:
2031 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2032 goto out;
2033 }
2034
2035 delay = ospf_lsa_refresh_delay (lsa);
2036
2037 if (IS_DEBUG_OSPF_EVENT)
2038 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)));
2039
2040 OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self,
2041 ospf_opaque_lsa_refresh_timer, oipi, delay);
2042out:
2043 return;
2044}
2045
2046static int
2047ospf_opaque_lsa_refresh_timer (struct thread *t)
2048{
2049 struct opaque_info_per_id *oipi;
2050 struct ospf_opaque_functab *functab;
2051 struct ospf_lsa *lsa;
2052
2053 if (IS_DEBUG_OSPF_EVENT)
2054 zlog_info ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
2055
2056 oipi = THREAD_ARG (t);
2057 oipi->t_opaque_lsa_self = NULL;
2058
2059 if ((lsa = oipi->lsa) != NULL)
2060 if ((functab = oipi->opqctl_type->functab) != NULL)
2061 if (functab->lsa_refresher != NULL)
2062 (* functab->lsa_refresher)(lsa);
2063
2064 return 0;
2065}
2066
2067void
2068ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
2069{
paul020709f2003-04-04 02:44:16 +00002070 struct ospf *ospf = ospf;
paul718e3742002-12-13 20:15:29 +00002071 struct opaque_info_per_type *oipt;
2072 struct opaque_info_per_id *oipi;
2073 struct ospf_lsa *lsa;
2074
paul020709f2003-04-04 02:44:16 +00002075 ospf = ospf_lookup ();
2076
paul718e3742002-12-13 20:15:29 +00002077 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
2078 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
2079 {
2080 zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2081 goto out;
2082 }
2083
2084 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2085 if ((lsa = oipi->lsa) == NULL)
2086 {
2087 zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
2088 goto out;
2089 }
2090
2091 /* Delete this lsa from neighbor retransmit-list. */
2092 switch (lsa->data->type)
2093 {
2094 case OSPF_OPAQUE_LINK_LSA:
2095 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002096 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002097 break;
2098 case OSPF_OPAQUE_AS_LSA:
paul68980082003-03-25 05:07:42 +00002099 ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002100 break;
2101 default:
2102 zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2103 goto out;
2104 }
2105
2106 /* Dequeue listnode entry from the list. */
2107 listnode_delete (oipt->id_list, oipi);
2108
2109 /* Avoid misjudgement in the next lookup. */
2110 if (listcount (oipt->id_list) == 0)
2111 oipt->id_list->head = oipt->id_list->tail = NULL;
2112
2113 /* Disassociate internal control information with the given lsa. */
paul718e3742002-12-13 20:15:29 +00002114 free_opaque_info_per_id ((void *) oipi);
2115
2116 /* Force given lsa's age to MaxAge. */
2117 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2118
2119 if (IS_DEBUG_OSPF_EVENT)
2120 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)));
2121
2122 /* This lsa will be flushed and removed eventually. */
paul68980082003-03-25 05:07:42 +00002123 ospf_lsa_maxage (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002124
2125out:
2126 return;
2127}
2128
2129/*------------------------------------------------------------------------*
2130 * Followings are control functions to block origination after restart.
2131 *------------------------------------------------------------------------*/
2132
2133static void ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs, struct ospf_neighbor *inbr, struct ospf_lsa *lsa);
2134static void ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi);
2135static void ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area);
2136static void ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top);
2137static unsigned long ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type);
2138
2139void
paul87d6f872004-09-24 08:01:38 +00002140ospf_opaque_adjust_lsreq (struct ospf_neighbor *nbr, struct list *lsas)
paul718e3742002-12-13 20:15:29 +00002141{
2142 struct ospf *top;
2143 struct ospf_area *area;
2144 struct ospf_interface *oi;
paul87d6f872004-09-24 08:01:38 +00002145 struct listnode *node1, *node2;
paul718e3742002-12-13 20:15:29 +00002146 struct ospf_lsa *lsa;
2147
2148 if ((top = oi_to_top (nbr->oi)) == NULL)
2149 goto out;
2150
2151 /*
2152 * If an instance of self-originated Opaque-LSA is found in the given
2153 * LSA list, and it is not installed to LSDB yet, exclude it from the
2154 * list "nbr->ls_req". In this way, it is assured that an LSReq message,
2155 * which might be sent in the process of flooding, will not request for
2156 * the LSA to be flushed immediately; otherwise, depending on timing,
2157 * an LSUpd message will carry instances of target LSAs with MaxAge,
2158 * while other LSUpd message might carry old LSA instances (non-MaxAge).
2159 * Obviously, the latter would trigger miserable situations that repeat
2160 * installation and removal of unwanted LSAs indefinitely.
2161 */
2162 for (node1 = listhead (lsas); node1; nextnode (node1))
2163 {
2164 if ((lsa = getdata (node1)) == NULL)
2165 continue;
2166
2167 /* Filter out unwanted LSAs. */
2168 if (! IS_OPAQUE_LSA (lsa->data->type))
2169 continue;
2170 if (! IPV4_ADDR_SAME (&lsa->data->adv_router, &top->router_id))
2171 continue;
2172
2173 /*
2174 * Don't touch an LSA which has MaxAge; two possible cases.
2175 *
2176 * 1) This LSA has originally flushed by myself (received LSUpd
2177 * message's router-id is equal to my router-id), and flooded
2178 * back by an opaque-capable router.
2179 *
2180 * 2) This LSA has expired in an opaque-capable router and thus
2181 * flushed by the router.
2182 */
2183 if (IS_LSA_MAXAGE (lsa))
2184 continue;
2185
2186 /* If the LSA has installed in the LSDB, nothing to do here. */
2187 if (ospf_lsa_lookup_by_header (nbr->oi->area, lsa->data) != NULL)
2188 continue;
2189
2190 /* Ok, here we go. */
2191 switch (lsa->data->type)
2192 {
2193 case OSPF_OPAQUE_LINK_LSA:
2194 oi = nbr->oi;
2195 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2196 break;
2197 case OSPF_OPAQUE_AREA_LSA:
2198 area = nbr->oi->area;
2199 for (node2 = listhead (area->oiflist); node2; nextnode (node2))
2200 {
2201 if ((oi = getdata (node2)) == NULL)
2202 continue;
2203 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2204 }
2205 break;
2206 case OSPF_OPAQUE_AS_LSA:
2207 for (node2 = listhead (top->oiflist); node2; nextnode (node2))
2208 {
2209 if ((oi = getdata (node2)) == NULL)
2210 continue;
2211 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2212 }
2213 break;
2214 default:
2215 break;
2216 }
2217 }
2218
2219out:
2220 return;
2221}
2222
2223static void
2224ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs,
2225 struct ospf_neighbor *inbr,
2226 struct ospf_lsa *lsa)
2227{
2228 struct route_node *rn;
2229 struct ospf_neighbor *onbr;
2230 struct ospf_lsa *ls_req;
2231
2232 for (rn = route_top (nbrs); rn; rn = route_next (rn))
2233 {
2234 if ((onbr = rn->info) == NULL)
2235 continue;
2236 if (onbr == inbr)
2237 continue;
2238 if ((ls_req = ospf_ls_request_lookup (onbr, lsa)) == NULL)
2239 continue;
2240
2241 if (IS_DEBUG_OSPF_EVENT)
2242 zlog_info ("LSA[%s]: Exclude this entry from LSReq to send.", dump_lsa_key (lsa));
2243
2244 ospf_ls_request_delete (onbr, ls_req);
2245/* ospf_check_nbr_loading (onbr);*//* XXX */
2246 }
2247
2248 return;
2249}
2250
2251void
paul87d6f872004-09-24 08:01:38 +00002252ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr,
2253 struct list *lsas)
paul718e3742002-12-13 20:15:29 +00002254{
2255 struct ospf *top;
paul87d6f872004-09-24 08:01:38 +00002256 struct listnode *node, *next;
paul718e3742002-12-13 20:15:29 +00002257 struct ospf_lsa *lsa;
2258 u_char before;
2259
2260 if ((top = oi_to_top (nbr->oi)) == NULL)
2261 goto out;
2262
2263 before = IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque);
2264
2265 for (node = listhead (lsas); node; node = next)
2266 {
2267 next = node->next;
2268
2269 if ((lsa = getdata (node)) == NULL)
2270 continue;
2271
2272 listnode_delete (lsas, lsa);
2273
2274 /*
2275 * Since these LSA entries are not yet installed into corresponding
2276 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2277 */
2278 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2279 switch (lsa->data->type)
2280 {
2281 case OSPF_OPAQUE_LINK_LSA:
2282 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
2283 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2284 break;
2285 case OSPF_OPAQUE_AREA_LSA:
2286 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
2287 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2288 break;
2289 case OSPF_OPAQUE_AS_LSA:
2290 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
paul68980082003-03-25 05:07:42 +00002291 ospf_flood_through_as (top, NULL/*inbr*/, lsa);
paul718e3742002-12-13 20:15:29 +00002292 break;
2293 default:
2294 zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
2295 goto out;
2296 }
2297
2298 ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */
2299 }
2300
2301 if (before == 0 && IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2302 {
2303 if (IS_DEBUG_OSPF_EVENT)
2304 zlog_info ("Block Opaque-LSA origination: OFF -> ON");
2305 }
2306
2307out:
2308 return;
2309}
2310
2311void
paul87d6f872004-09-24 08:01:38 +00002312ospf_opaque_ls_ack_received (struct ospf_neighbor *nbr, struct list *acks)
paul718e3742002-12-13 20:15:29 +00002313{
2314 struct ospf *top;
paul87d6f872004-09-24 08:01:38 +00002315 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002316 struct ospf_lsa *lsa;
2317 char type9_lsa_rcv = 0, type10_lsa_rcv = 0, type11_lsa_rcv = 0;
2318
2319 if ((top = oi_to_top (nbr->oi)) == NULL)
2320 goto out;
2321
paul87d6f872004-09-24 08:01:38 +00002322 LIST_LOOP (acks, lsa, node)
paul718e3742002-12-13 20:15:29 +00002323 {
paul718e3742002-12-13 20:15:29 +00002324 switch (lsa->data->type)
2325 {
2326 case OSPF_OPAQUE_LINK_LSA:
2327 type9_lsa_rcv = 1;
2328 /* Callback function... */
2329 break;
2330 case OSPF_OPAQUE_AREA_LSA:
2331 type10_lsa_rcv = 1;
2332 /* Callback function... */
2333 break;
2334 case OSPF_OPAQUE_AS_LSA:
2335 type11_lsa_rcv = 1;
2336 /* Callback function... */
2337 break;
2338 default:
2339 zlog_warn ("ospf_opaque_ls_ack_received: Unexpected LSA-type(%u)", lsa->data->type);
2340 goto out;
2341 }
2342 }
2343
2344 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2345 {
2346 int delay;
2347 struct ospf_interface *oi;
2348
2349 if (type9_lsa_rcv
2350 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT))
2351 ospf_opaque_type9_lsa_rxmt_nbr_check (nbr->oi);
2352
2353 if (type10_lsa_rcv
2354 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT))
2355 ospf_opaque_type10_lsa_rxmt_nbr_check (nbr->oi->area);
2356
2357 if (type11_lsa_rcv
2358 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT))
2359 ospf_opaque_type11_lsa_rxmt_nbr_check (top);
2360
2361 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2362 goto out; /* Blocking still in progress. */
2363
2364 if (IS_DEBUG_OSPF_EVENT)
2365 zlog_info ("Block Opaque-LSA origination: ON -> OFF");
2366
2367 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
2368 goto out; /* Opaque capability condition must have changed. */
2369
2370 /* Ok, let's start origination of Opaque-LSAs. */
2371 delay = OSPF_MIN_LS_INTERVAL;
paul718e3742002-12-13 20:15:29 +00002372
paul87d6f872004-09-24 08:01:38 +00002373 LIST_LOOP (top->oiflist, oi, node)
2374 {
paul718e3742002-12-13 20:15:29 +00002375 if (! ospf_if_is_enable (oi)
paul87d6f872004-09-24 08:01:38 +00002376 || ospf_nbr_count_opaque_capable (oi) == 0)
paul718e3742002-12-13 20:15:29 +00002377 continue;
2378
2379 ospf_opaque_lsa_originate_schedule (oi, &delay);
2380 }
2381 }
2382
2383out:
2384 return;
2385}
2386
2387static void
2388ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi)
2389{
2390 unsigned long n;
2391
2392 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_LINK_LSA);
2393 if (n == 0)
2394 {
2395 if (IS_DEBUG_OSPF_EVENT)
2396 zlog_info ("Self-originated type-9 Opaque-LSAs: OI(%s): Flush completed", IF_NAME (oi));
2397
paul68980082003-03-25 05:07:42 +00002398 UNSET_FLAG (oi->area->ospf->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
paul718e3742002-12-13 20:15:29 +00002399 }
2400 return;
2401}
2402
2403static void
2404ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area)
2405{
paul87d6f872004-09-24 08:01:38 +00002406 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002407 struct ospf_interface *oi;
2408 unsigned long n = 0;
2409
2410 for (node = listhead (area->oiflist); node; nextnode (node))
2411 {
2412 if ((oi = getdata (node)) == NULL)
2413 continue;
2414
2415 if (area->area_id.s_addr != OSPF_AREA_BACKBONE
2416 && oi->type == OSPF_IFTYPE_VIRTUALLINK)
2417 continue;
2418
2419 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AREA_LSA);
2420 if (n > 0)
2421 break;
2422 }
2423
2424 if (n == 0)
2425 {
2426 if (IS_DEBUG_OSPF_EVENT)
2427 zlog_info ("Self-originated type-10 Opaque-LSAs: AREA(%s): Flush completed", inet_ntoa (area->area_id));
2428
paul68980082003-03-25 05:07:42 +00002429 UNSET_FLAG (area->ospf->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
paul718e3742002-12-13 20:15:29 +00002430 }
2431
2432 return;
2433}
2434
2435static void
2436ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top)
2437{
paul87d6f872004-09-24 08:01:38 +00002438 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002439 struct ospf_interface *oi;
2440 unsigned long n = 0;
2441
2442 for (node = listhead (top->oiflist); node; nextnode (node))
2443 {
2444 if ((oi = getdata (node)) == NULL)
2445 continue;
2446
2447 switch (oi->type)
2448 {
2449 case OSPF_IFTYPE_VIRTUALLINK:
2450 continue;
2451 default:
2452 break;
2453 }
2454
2455 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AS_LSA);
2456 if (n > 0)
2457 goto out;
2458 }
2459
2460 if (n == 0)
2461 {
2462 if (IS_DEBUG_OSPF_EVENT)
2463 zlog_info ("Self-originated type-11 Opaque-LSAs: Flush completed");
2464
2465 UNSET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
2466 }
2467
2468out:
2469 return;
2470}
2471
2472static unsigned long
2473ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type)
2474{
2475 struct route_node *rn;
2476 struct ospf_neighbor *nbr;
2477 struct ospf *top;
2478 unsigned long n = 0;
2479
2480 for (rn = route_top (nbrs); rn; rn = route_next (rn))
2481 {
2482 if ((nbr = rn->info) == NULL)
2483 continue;
2484 if ((top = oi_to_top (nbr->oi)) == NULL)
2485 continue;
2486 if (IPV4_ADDR_SAME (&nbr->router_id, &top->router_id))
2487 continue;
2488 n += ospf_ls_retransmit_count_self (nbr, lsa_type);
2489 }
2490
2491 return n;
2492}
2493
2494/*------------------------------------------------------------------------*
2495 * Followings are util functions; probably be used by Opaque-LSAs only...
2496 *------------------------------------------------------------------------*/
2497
2498void
2499htonf (float *src, float *dst)
2500{
2501 u_int32_t lu1, lu2;
2502
2503 memcpy (&lu1, src, sizeof (u_int32_t));
2504 lu2 = htonl (lu1);
2505 memcpy (dst, &lu2, sizeof (u_int32_t));
2506 return;
2507}
2508
2509void
2510ntohf (float *src, float *dst)
2511{
2512 u_int32_t lu1, lu2;
2513
2514 memcpy (&lu1, src, sizeof (u_int32_t));
2515 lu2 = ntohl (lu1);
2516 memcpy (dst, &lu2, sizeof (u_int32_t));
2517 return;
2518}
2519
2520struct ospf *
2521oi_to_top (struct ospf_interface *oi)
2522{
2523 struct ospf *top = NULL;
2524 struct ospf_area *area;
2525
paul68980082003-03-25 05:07:42 +00002526 if (oi == NULL || (area = oi->area) == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00002527 zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");
2528
2529 return top;
2530}
2531
2532#endif /* HAVE_OPAQUE_LSA */