blob: 414ec743912b6145c5dde915f6d726f2388c79d2 [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);
72#endif /* SUPPORT_OSPF_API */
73
paul718e3742002-12-13 20:15:29 +000074static void ospf_opaque_register_vty (void);
75static void ospf_opaque_funclist_init (void);
76static void ospf_opaque_funclist_term (void);
77static void free_opaque_info_per_type (void *val);
78static void free_opaque_info_per_id (void *val);
79static int ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa);
80static int ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa);
81
82void
83ospf_opaque_init (void)
84{
85 ospf_opaque_register_vty ();
86 ospf_opaque_funclist_init ();
87
88#ifdef HAVE_OSPF_TE
89 if (ospf_mpls_te_init () != 0)
90 exit (1);
91#endif /* HAVE_OSPF_TE */
92
paul283ae332003-03-17 01:16:55 +000093#ifdef SUPPORT_OSPF_API
94 if (ospf_apiserver_init () != 0)
95 exit (1);
96#endif /* SUPPORT_OSPF_API */
97
paul718e3742002-12-13 20:15:29 +000098 return;
99}
100
101void
102ospf_opaque_term (void)
103{
104#ifdef HAVE_OSPF_TE
105 ospf_mpls_te_term ();
106#endif /* HAVE_OSPF_TE */
107
paul283ae332003-03-17 01:16:55 +0000108#ifdef SUPPORT_OSPF_API
109 ospf_apiserver_term ();
110#endif /* SUPPORT_OSPF_API */
111
paul718e3742002-12-13 20:15:29 +0000112 ospf_opaque_funclist_term ();
113 return;
114}
115
116int
117ospf_opaque_type9_lsa_init (struct ospf_interface *oi)
118{
119 if (oi->opaque_lsa_self != NULL)
120 list_delete (oi->opaque_lsa_self);
121
122 oi->opaque_lsa_self = list_new ();
123 oi->opaque_lsa_self->del = free_opaque_info_per_type;
124 oi->t_opaque_lsa_self = NULL;
125 return 0;
126}
127
128void
129ospf_opaque_type9_lsa_term (struct ospf_interface *oi)
130{
131 OSPF_TIMER_OFF (oi->t_opaque_lsa_self);
132 if (oi->opaque_lsa_self != NULL)
133 list_delete (oi->opaque_lsa_self);
134 oi->opaque_lsa_self = NULL;
135 return;
136}
137
138int
139ospf_opaque_type10_lsa_init (struct ospf_area *area)
140{
141 if (area->opaque_lsa_self != NULL)
142 list_delete (area->opaque_lsa_self);
143
144 area->opaque_lsa_self = list_new ();
145 area->opaque_lsa_self->del = free_opaque_info_per_type;
146 area->t_opaque_lsa_self = NULL;
147
148#ifdef MONITOR_LSDB_CHANGE
149 area->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
150 area->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
151#endif /* MONITOR_LSDB_CHANGE */
152 return 0;
153}
154
155void
156ospf_opaque_type10_lsa_term (struct ospf_area *area)
157{
158#ifdef MONITOR_LSDB_CHANGE
159 area->lsdb->new_lsa_hook =
160 area->lsdb->del_lsa_hook = NULL;
161#endif /* MONITOR_LSDB_CHANGE */
162
163 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
164 if (area->opaque_lsa_self != NULL)
165 list_delete (area->opaque_lsa_self);
166 area->opaque_lsa_self = NULL;
167 return;
168}
169
170int
171ospf_opaque_type11_lsa_init (struct ospf *top)
172{
173 if (top->opaque_lsa_self != NULL)
174 list_delete (top->opaque_lsa_self);
175
176 top->opaque_lsa_self = list_new ();
177 top->opaque_lsa_self->del = free_opaque_info_per_type;
178 top->t_opaque_lsa_self = NULL;
179
180#ifdef MONITOR_LSDB_CHANGE
181 top->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
182 top->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
183#endif /* MONITOR_LSDB_CHANGE */
184 return 0;
185}
186
187void
188ospf_opaque_type11_lsa_term (struct ospf *top)
189{
190#ifdef MONITOR_LSDB_CHANGE
191 top->lsdb->new_lsa_hook =
192 top->lsdb->del_lsa_hook = NULL;
193#endif /* MONITOR_LSDB_CHANGE */
194
195 OSPF_TIMER_OFF (top->t_opaque_lsa_self);
196 if (top->opaque_lsa_self != NULL)
197 list_delete (top->opaque_lsa_self);
198 top->opaque_lsa_self = NULL;
199 return;
200}
201
202static const char *
203ospf_opaque_type_name (u_char opaque_type)
204{
205 const char *name = "Unknown";
206
207 switch (opaque_type)
208 {
209 case OPAQUE_TYPE_WILDCARD: /* This is a special assignment! */
210 name = "Wildcard";
211 break;
212 case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA:
213 name = "Traffic Engineering LSA";
214 break;
215 case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC:
216 name = "Sycamore optical topology description";
217 break;
218 case OPAQUE_TYPE_GRACE_LSA:
219 name = "Grace-LSA";
220 break;
221 default:
222 if (OPAQUE_TYPE_RANGE_UNASSIGNED (opaque_type))
223 name = "Unassigned";
224 else if (OPAQUE_TYPE_RANGE_RESERVED (opaque_type))
225 name = "Private/Experimental";
226 break;
227 }
228 return name;
229}
230
231/*------------------------------------------------------------------------*
232 * Followings are management functions to store user specified callbacks.
233 *------------------------------------------------------------------------*/
234
235struct opaque_info_per_type; /* Forward declaration. */
236
237struct ospf_opaque_functab
238{
239 u_char opaque_type;
240 struct opaque_info_per_type *oipt;
241
242 int (* new_if_hook)(struct interface *ifp);
243 int (* del_if_hook)(struct interface *ifp);
244 void (* ism_change_hook)(struct ospf_interface *oi, int old_status);
245 void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status);
246 void (* config_write_router)(struct vty *vty);
247 void (* config_write_if )(struct vty *vty, struct interface *ifp);
248 void (* config_write_debug )(struct vty *vty);
249 void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa);
250 int (* lsa_originator)(void *arg);
251 void (* lsa_refresher )(struct ospf_lsa *lsa);
252 int (* new_lsa_hook)(struct ospf_lsa *lsa);
253 int (* del_lsa_hook)(struct ospf_lsa *lsa);
254};
255
paul87d6f872004-09-24 08:01:38 +0000256/* Handle LSA-9/10/11 altogether. */
257static struct list *ospf_opaque_wildcard_funclist;
258static struct list *ospf_opaque_type9_funclist;
259static struct list *ospf_opaque_type10_funclist;
260static struct list *ospf_opaque_type11_funclist;
paul718e3742002-12-13 20:15:29 +0000261
262static void
263ospf_opaque_del_functab (void *val)
264{
265 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, val);
266 return;
267}
268
269static void
270ospf_opaque_funclist_init (void)
271{
paul87d6f872004-09-24 08:01:38 +0000272 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000273
paul09e4efd2003-01-18 00:12:02 +0000274 funclist = ospf_opaque_wildcard_funclist = list_new ();
275 funclist->del = ospf_opaque_del_functab;
276
paul718e3742002-12-13 20:15:29 +0000277 funclist = ospf_opaque_type9_funclist = list_new ();
278 funclist->del = ospf_opaque_del_functab;
279
280 funclist = ospf_opaque_type10_funclist = list_new ();
281 funclist->del = ospf_opaque_del_functab;
282
283 funclist = ospf_opaque_type11_funclist = list_new ();
284 funclist->del = ospf_opaque_del_functab;
285 return;
286}
287
288static void
289ospf_opaque_funclist_term (void)
290{
paul87d6f872004-09-24 08:01:38 +0000291 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000292
paul09e4efd2003-01-18 00:12:02 +0000293 funclist = ospf_opaque_wildcard_funclist;
294 list_delete (funclist);
295
paul718e3742002-12-13 20:15:29 +0000296 funclist = ospf_opaque_type9_funclist;
297 list_delete (funclist);
298
299 funclist = ospf_opaque_type10_funclist;
300 list_delete (funclist);
301
302 funclist = ospf_opaque_type11_funclist;
303 list_delete (funclist);
304 return;
305}
306
paul87d6f872004-09-24 08:01:38 +0000307static struct list *
paul718e3742002-12-13 20:15:29 +0000308ospf_get_opaque_funclist (u_char lsa_type)
309{
paul87d6f872004-09-24 08:01:38 +0000310 struct list *funclist = NULL;
paul718e3742002-12-13 20:15:29 +0000311
312 switch (lsa_type)
313 {
paul09e4efd2003-01-18 00:12:02 +0000314 case OPAQUE_TYPE_WILDCARD:
315 /* XXX
316 * This is an ugly trick to handle type-9/10/11 LSA altogether.
317 * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor
318 * an officially assigned opaque-type.
319 * Though it is possible that the value might be officially used
320 * in the future, we use it internally as a special label, for now.
321 */
322 funclist = ospf_opaque_wildcard_funclist;
323 break;
paul718e3742002-12-13 20:15:29 +0000324 case OSPF_OPAQUE_LINK_LSA:
325 funclist = ospf_opaque_type9_funclist;
326 break;
327 case OSPF_OPAQUE_AREA_LSA:
328 funclist = ospf_opaque_type10_funclist;
329 break;
330 case OSPF_OPAQUE_AS_LSA:
331 funclist = ospf_opaque_type11_funclist;
332 break;
333 default:
334 zlog_warn ("ospf_get_opaque_funclist: Unexpected LSA-type(%u)", lsa_type);
335 break;
336 }
337 return funclist;
338}
339
paul87d6f872004-09-24 08:01:38 +0000340/* XXX: such a huge argument list can /not/ be healthy... */
paul718e3742002-12-13 20:15:29 +0000341int
342ospf_register_opaque_functab (
343 u_char lsa_type,
344 u_char opaque_type,
345 int (* new_if_hook)(struct interface *ifp),
346 int (* del_if_hook)(struct interface *ifp),
347 void (* ism_change_hook)(struct ospf_interface *oi, int old_status),
348 void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status),
349 void (* config_write_router)(struct vty *vty),
350 void (* config_write_if )(struct vty *vty, struct interface *ifp),
351 void (* config_write_debug )(struct vty *vty),
352 void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa),
353 int (* lsa_originator)(void *arg),
354 void (* lsa_refresher )(struct ospf_lsa *lsa),
355 int (* new_lsa_hook)(struct ospf_lsa *lsa),
356 int (* del_lsa_hook)(struct ospf_lsa *lsa))
357{
paul87d6f872004-09-24 08:01:38 +0000358 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000359 struct ospf_opaque_functab *new;
360 int rc = -1;
361
362 if ((funclist = ospf_get_opaque_funclist (lsa_type)) == NULL)
363 {
paul87d6f872004-09-24 08:01:38 +0000364 zlog_warn ("ospf_register_opaque_functab: Cannot get funclist"
365 " for Type-%u LSAs?",
366 lsa_type);
paul718e3742002-12-13 20:15:29 +0000367 goto out;
368 }
369 else
370 {
paul87d6f872004-09-24 08:01:38 +0000371 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000372 struct ospf_opaque_functab *functab;
paul87d6f872004-09-24 08:01:38 +0000373
374 LIST_LOOP (funclist, functab, node)
375 if (functab->opaque_type == opaque_type)
376 {
377 zlog_warn ("ospf_register_opaque_functab: Duplicated entry?:"
378 " lsa_type(%u), opaque_type(%u)",
379 lsa_type, opaque_type);
380 goto out;
381 }
paul718e3742002-12-13 20:15:29 +0000382 }
383
384 if ((new = XCALLOC (MTYPE_OSPF_OPAQUE_FUNCTAB,
385 sizeof (struct ospf_opaque_functab))) == NULL)
386 {
paul87d6f872004-09-24 08:01:38 +0000387 zlog_warn ("ospf_register_opaque_functab: XMALLOC: %s",
388 strerror (errno));
paul718e3742002-12-13 20:15:29 +0000389 goto out;
390 }
391
392 new->opaque_type = opaque_type;
393 new->oipt = NULL;
394 new->new_if_hook = new_if_hook;
395 new->del_if_hook = del_if_hook;
396 new->ism_change_hook = ism_change_hook;
397 new->nsm_change_hook = nsm_change_hook;
398 new->config_write_router = config_write_router;
399 new->config_write_if = config_write_if;
400 new->config_write_debug = config_write_debug;
401 new->show_opaque_info = show_opaque_info;
402 new->lsa_originator = lsa_originator;
403 new->lsa_refresher = lsa_refresher;
404 new->new_lsa_hook = new_lsa_hook;
405 new->del_lsa_hook = del_lsa_hook;
406
407 listnode_add (funclist, new);
408 rc = 0;
409
410out:
411 return rc;
412}
413
414void
415ospf_delete_opaque_functab (u_char lsa_type, u_char opaque_type)
416{
paul87d6f872004-09-24 08:01:38 +0000417 struct list *funclist;
418 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000419 struct ospf_opaque_functab *functab;
420
421 if ((funclist = ospf_get_opaque_funclist (lsa_type)) != NULL)
422 for (node = listhead (funclist); node; nextnode (node))
423 {
424 if ((functab = getdata (node)) != NULL
paul87d6f872004-09-24 08:01:38 +0000425 && functab->opaque_type == opaque_type)
paul718e3742002-12-13 20:15:29 +0000426 {
427 /* Cleanup internal control information, if it still remains. */
428 if (functab->oipt != NULL)
429 free_opaque_info_per_type (functab->oipt);
430
431 /* Dequeue listnode entry from the list. */
432 listnode_delete (funclist, functab);
433
434 /* Avoid misjudgement in the next lookup. */
435 if (listcount (funclist) == 0)
436 funclist->head = funclist->tail = NULL;
437
438 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, functab);
paul87d6f872004-09-24 08:01:38 +0000439 break;
paul718e3742002-12-13 20:15:29 +0000440 }
441 }
paul87d6f872004-09-24 08:01:38 +0000442
paul718e3742002-12-13 20:15:29 +0000443 return;
444}
445
446static struct ospf_opaque_functab *
447ospf_opaque_functab_lookup (struct ospf_lsa *lsa)
448{
paul87d6f872004-09-24 08:01:38 +0000449 struct list *funclist;
450 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000451 struct ospf_opaque_functab *functab;
452 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
453
454 if ((funclist = ospf_get_opaque_funclist (lsa->data->type)) != NULL)
paul87d6f872004-09-24 08:01:38 +0000455 LIST_LOOP (funclist, functab, node)
456 if (functab->opaque_type == key)
457 return functab;
paul718e3742002-12-13 20:15:29 +0000458
459 return NULL;
460}
461
462/*------------------------------------------------------------------------*
463 * Followings are management functions for self-originated LSA entries.
464 *------------------------------------------------------------------------*/
465
466/*
467 * Opaque-LSA control information per opaque-type.
468 * Single Opaque-Type may have multiple instances; each of them will be
469 * identified by their opaque-id.
470 */
471struct opaque_info_per_type
472{
paul09e4efd2003-01-18 00:12:02 +0000473 u_char lsa_type;
paul718e3742002-12-13 20:15:29 +0000474 u_char opaque_type;
475
476 enum { PROC_NORMAL, PROC_SUSPEND } status;
477
478 /*
479 * Thread for (re-)origination scheduling for this opaque-type.
480 *
481 * Initial origination of Opaque-LSAs is controlled by generic
482 * Opaque-LSA handling module so that same opaque-type entries are
483 * called all at once when certain conditions are met.
484 * However, there might be cases that some Opaque-LSA clients need
485 * to (re-)originate their own Opaque-LSAs out-of-sync with others.
486 * This thread is prepared for that specific purpose.
487 */
488 struct thread *t_opaque_lsa_self;
489
490 /*
paul09e4efd2003-01-18 00:12:02 +0000491 * Backpointer to an "owner" which is LSA-type dependent.
paul718e3742002-12-13 20:15:29 +0000492 * type-9: struct ospf_interface
493 * type-10: struct ospf_area
494 * type-11: struct ospf
495 */
496 void *owner;
497
498 /* Collection of callback functions for this opaque-type. */
499 struct ospf_opaque_functab *functab;
500
501 /* List of Opaque-LSA control informations per opaque-id. */
paul87d6f872004-09-24 08:01:38 +0000502 struct list *id_list;
paul718e3742002-12-13 20:15:29 +0000503};
504
505/* Opaque-LSA control information per opaque-id. */
506struct opaque_info_per_id
507{
508 u_int32_t opaque_id;
509
510 /* Thread for refresh/flush scheduling for this opaque-type/id. */
511 struct thread *t_opaque_lsa_self;
512
513 /* Backpointer to Opaque-LSA control information per opaque-type. */
514 struct opaque_info_per_type *opqctl_type;
515
516 /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
517 struct ospf_lsa *lsa;
518};
519
520static struct opaque_info_per_type *register_opaque_info_per_type (struct ospf_opaque_functab *functab, struct ospf_lsa *new);
521static struct opaque_info_per_type *lookup_opaque_info_by_type (struct ospf_lsa *lsa);
522static struct opaque_info_per_id *register_opaque_info_per_id (struct opaque_info_per_type *oipt, struct ospf_lsa *new);
523static struct opaque_info_per_id *lookup_opaque_info_by_id (struct opaque_info_per_type *oipt, struct ospf_lsa *lsa);
524static struct opaque_info_per_id *register_opaque_lsa (struct ospf_lsa *new);
525
526
527static struct opaque_info_per_type *
528register_opaque_info_per_type (struct ospf_opaque_functab *functab,
529 struct ospf_lsa *new)
530{
531 struct ospf *top;
532 struct opaque_info_per_type *oipt;
533
534 if ((oipt = XCALLOC (MTYPE_OPAQUE_INFO_PER_TYPE,
535 sizeof (struct opaque_info_per_type))) == NULL)
536 {
537 zlog_warn ("register_opaque_info_per_type: XMALLOC: %s", strerror (errno));
538 goto out;
539 }
540
541 switch (new->data->type)
542 {
543 case OSPF_OPAQUE_LINK_LSA:
544 oipt->owner = new->oi;
545 listnode_add (new->oi->opaque_lsa_self, oipt);
546 break;
547 case OSPF_OPAQUE_AREA_LSA:
548 oipt->owner = new->area;
549 listnode_add (new->area->opaque_lsa_self, oipt);
550 break;
551 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +0000552 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000553 if (new->area != NULL && (top = new->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +0000554 {
555 free_opaque_info_per_type ((void *) oipt);
556 oipt = NULL;
557 goto out; /* This case may not exist. */
558 }
559 oipt->owner = top;
560 listnode_add (top->opaque_lsa_self, oipt);
561 break;
562 default:
paul09e4efd2003-01-18 00:12:02 +0000563 zlog_warn ("register_opaque_info_per_type: Unexpected LSA-type(%u)", new->data->type);
paul718e3742002-12-13 20:15:29 +0000564 free_opaque_info_per_type ((void *) oipt);
565 oipt = NULL;
566 goto out; /* This case may not exist. */
567 }
568
paul09e4efd2003-01-18 00:12:02 +0000569 oipt->lsa_type = new->data->type;
paul718e3742002-12-13 20:15:29 +0000570 oipt->opaque_type = GET_OPAQUE_TYPE (ntohl (new->data->id.s_addr));
571 oipt->status = PROC_NORMAL;
572 oipt->t_opaque_lsa_self = NULL;
573 oipt->functab = functab;
574 functab->oipt = oipt;
575 oipt->id_list = list_new ();
576 oipt->id_list->del = free_opaque_info_per_id;
577
578out:
579 return oipt;
580}
581
582static void
583free_opaque_info_per_type (void *val)
584{
585 struct opaque_info_per_type *oipt = (struct opaque_info_per_type *) val;
586 struct opaque_info_per_id *oipi;
587 struct ospf_lsa *lsa;
paul87d6f872004-09-24 08:01:38 +0000588 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000589
590 /* Control information per opaque-id may still exist. */
591 for (node = listhead (oipt->id_list); node; nextnode (node))
592 {
593 if ((oipi = getdata (node)) == NULL)
594 continue;
595 if ((lsa = oipi->lsa) == NULL)
596 continue;
597 if (IS_LSA_MAXAGE (lsa))
598 continue;
599 ospf_opaque_lsa_flush_schedule (lsa);
600 }
601
paul09e4efd2003-01-18 00:12:02 +0000602 /* Remove "oipt" from its owner's self-originated LSA list. */
603 switch (oipt->lsa_type)
604 {
605 case OSPF_OPAQUE_LINK_LSA:
606 {
607 struct ospf_interface *oi = (struct ospf_interface *)(oipt->owner);
608 listnode_delete (oi->opaque_lsa_self, oipt);
609 break;
610 }
611 case OSPF_OPAQUE_AREA_LSA:
612 {
613 struct ospf_area *area = (struct ospf_area *)(oipt->owner);
614 listnode_delete (area->opaque_lsa_self, oipt);
615 break;
616 }
617 case OSPF_OPAQUE_AS_LSA:
618 {
619 struct ospf *top = (struct ospf *)(oipt->owner);
620 listnode_delete (top->opaque_lsa_self, oipt);
621 break;
622 }
623 default:
624 zlog_warn ("free_opaque_info_per_type: Unexpected LSA-type(%u)", oipt->lsa_type);
625 break; /* This case may not exist. */
626 }
627
paul718e3742002-12-13 20:15:29 +0000628 OSPF_TIMER_OFF (oipt->t_opaque_lsa_self);
629 list_delete (oipt->id_list);
630 XFREE (MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
631 return;
632}
633
634static struct opaque_info_per_type *
635lookup_opaque_info_by_type (struct ospf_lsa *lsa)
636{
637 struct ospf *top;
638 struct ospf_area *area;
639 struct ospf_interface *oi;
paul87d6f872004-09-24 08:01:38 +0000640 struct list *listtop = NULL;
641 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000642 struct opaque_info_per_type *oipt = NULL;
643 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
644
645 switch (lsa->data->type)
646 {
647 case OSPF_OPAQUE_LINK_LSA:
648 if ((oi = lsa->oi) != NULL)
649 listtop = oi->opaque_lsa_self;
650 else
651 zlog_warn ("Type-9 Opaque-LSA: Reference to OI is missing?");
652 break;
653 case OSPF_OPAQUE_AREA_LSA:
654 if ((area = lsa->area) != NULL)
655 listtop = area->opaque_lsa_self;
656 else
657 zlog_warn ("Type-10 Opaque-LSA: Reference to AREA is missing?");
658 break;
659 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +0000660 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000661 if ((area = lsa->area) != NULL && (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +0000662 {
663 zlog_warn ("Type-11 Opaque-LSA: Reference to OSPF is missing?");
664 break; /* Unlikely to happen. */
665 }
666 listtop = top->opaque_lsa_self;
667 break;
668 default:
669 zlog_warn ("lookup_opaque_info_by_type: Unexpected LSA-type(%u)", lsa->data->type);
670 break;
671 }
672
673 if (listtop != NULL)
paul87d6f872004-09-24 08:01:38 +0000674 LIST_LOOP (listtop, oipt, node)
675 if (oipt->opaque_type == key)
676 return oipt;
paul718e3742002-12-13 20:15:29 +0000677
678 return NULL;
679}
680
681static struct opaque_info_per_id *
682register_opaque_info_per_id (struct opaque_info_per_type *oipt,
683 struct ospf_lsa *new)
684{
685 struct opaque_info_per_id *oipi;
686
687 if ((oipi = XCALLOC (MTYPE_OPAQUE_INFO_PER_ID,
688 sizeof (struct opaque_info_per_id))) == NULL)
689 {
690 zlog_warn ("register_opaque_info_per_id: XMALLOC: %s", strerror (errno));
691 goto out;
692 }
693 oipi->opaque_id = GET_OPAQUE_ID (ntohl (new->data->id.s_addr));
694 oipi->t_opaque_lsa_self = NULL;
695 oipi->opqctl_type = oipt;
696 oipi->lsa = ospf_lsa_lock (new);
697
698 listnode_add (oipt->id_list, oipi);
699
700out:
701 return oipi;
702}
703
704static void
705free_opaque_info_per_id (void *val)
706{
707 struct opaque_info_per_id *oipi = (struct opaque_info_per_id *) val;
708
709 OSPF_TIMER_OFF (oipi->t_opaque_lsa_self);
710 if (oipi->lsa != NULL)
711 ospf_lsa_unlock (oipi->lsa);
712 XFREE (MTYPE_OPAQUE_INFO_PER_ID, oipi);
713 return;
714}
715
716static struct opaque_info_per_id *
717lookup_opaque_info_by_id (struct opaque_info_per_type *oipt,
718 struct ospf_lsa *lsa)
719{
paul87d6f872004-09-24 08:01:38 +0000720 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000721 struct opaque_info_per_id *oipi;
722 u_int32_t key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
723
paul87d6f872004-09-24 08:01:38 +0000724 LIST_LOOP (oipt->id_list, oipi, node)
725 if (oipi->opaque_id == key)
726 return oipi;
paul718e3742002-12-13 20:15:29 +0000727
728 return NULL;
729}
730
731static struct opaque_info_per_id *
732register_opaque_lsa (struct ospf_lsa *new)
733{
734 struct ospf_opaque_functab *functab;
735 struct opaque_info_per_type *oipt;
736 struct opaque_info_per_id *oipi = NULL;
737
738 if ((functab = ospf_opaque_functab_lookup (new)) == NULL)
739 goto out;
740
741 if ((oipt = lookup_opaque_info_by_type (new)) == NULL
742 && (oipt = register_opaque_info_per_type (functab, new)) == NULL)
743 goto out;
744
745 if ((oipi = register_opaque_info_per_id (oipt, new)) == NULL)
746 goto out;
747
748out:
749 return oipi;
750}
751
752/*------------------------------------------------------------------------*
753 * Followings are (vty) configuration functions for Opaque-LSAs handling.
754 *------------------------------------------------------------------------*/
755
756DEFUN (capability_opaque,
757 capability_opaque_cmd,
758 "capability opaque",
759 "Enable specific OSPF feature\n"
760 "Opaque LSA\n")
761{
762 struct ospf *ospf = (struct ospf *) vty->index;
763
764 /* Turn on the "master switch" of opaque-lsa capability. */
765 if (!CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
766 {
767 if (IS_DEBUG_OSPF_EVENT)
768 zlog_info ("Opaque capability: OFF -> ON");
769
770 SET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
771 ospf_renegotiate_optional_capabilities (ospf);
772 }
773 return CMD_SUCCESS;
774}
775
776ALIAS (capability_opaque,
777 ospf_opaque_capable_cmd,
778 "ospf opaque-lsa",
779 "OSPF specific commands\n"
780 "Enable the Opaque-LSA capability (rfc2370)\n")
781
782DEFUN (no_capability_opaque,
783 no_capability_opaque_cmd,
784 "no capability opaque",
785 NO_STR
786 "Enable specific OSPF feature\n"
787 "Opaque LSA\n")
788{
789 struct ospf *ospf = (struct ospf *) vty->index;
790
791 /* Turn off the "master switch" of opaque-lsa capability. */
792 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
793 {
794 if (IS_DEBUG_OSPF_EVENT)
795 zlog_info ("Opaque capability: ON -> OFF");
796
797 UNSET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
798 ospf_renegotiate_optional_capabilities (ospf);
799 }
800 return CMD_SUCCESS;
801}
802
803ALIAS (no_capability_opaque,
804 no_ospf_opaque_capable_cmd,
805 "no ospf opaque-lsa",
806 NO_STR
807 "OSPF specific commands\n"
808 "Disable the Opaque-LSA capability (rfc2370)\n")
809
810static void
811ospf_opaque_register_vty (void)
812{
813 install_element (OSPF_NODE, &capability_opaque_cmd);
814 install_element (OSPF_NODE, &no_capability_opaque_cmd);
815 install_element (OSPF_NODE, &ospf_opaque_capable_cmd);
816 install_element (OSPF_NODE, &no_ospf_opaque_capable_cmd);
817 return;
818}
819
820/*------------------------------------------------------------------------*
821 * Followings are collection of user-registered function callers.
822 *------------------------------------------------------------------------*/
823
824static int
paul87d6f872004-09-24 08:01:38 +0000825opaque_lsa_new_if_callback (struct list *funclist, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000826{
paul87d6f872004-09-24 08:01:38 +0000827 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000828 struct ospf_opaque_functab *functab;
829 int rc = -1;
830
paul87d6f872004-09-24 08:01:38 +0000831 LIST_LOOP (funclist, functab, node)
832 if (functab->new_if_hook != NULL)
833 if ((* functab->new_if_hook)(ifp) != 0)
834 goto out;
paul718e3742002-12-13 20:15:29 +0000835 rc = 0;
836out:
837 return rc;
838}
839
840static int
paul87d6f872004-09-24 08:01:38 +0000841opaque_lsa_del_if_callback (struct list *funclist, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000842{
paul87d6f872004-09-24 08:01:38 +0000843 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000844 struct ospf_opaque_functab *functab;
845 int rc = -1;
846
paul87d6f872004-09-24 08:01:38 +0000847 LIST_LOOP (funclist, functab, node)
848 if (functab->del_if_hook != NULL)
849 if ((* functab->del_if_hook)(ifp) != 0)
850 goto out;
paul718e3742002-12-13 20:15:29 +0000851 rc = 0;
852out:
853 return rc;
854}
855
856static void
paul87d6f872004-09-24 08:01:38 +0000857opaque_lsa_ism_change_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000858 struct ospf_interface *oi, int old_status)
859{
paul87d6f872004-09-24 08:01:38 +0000860 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000861 struct ospf_opaque_functab *functab;
862
paul87d6f872004-09-24 08:01:38 +0000863 LIST_LOOP (funclist, functab, node)
864 if (functab->ism_change_hook != NULL)
865 (* functab->ism_change_hook)(oi, old_status);
866
paul718e3742002-12-13 20:15:29 +0000867 return;
868}
869
870static void
paul87d6f872004-09-24 08:01:38 +0000871opaque_lsa_nsm_change_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000872 struct ospf_neighbor *nbr, int old_status)
873{
paul87d6f872004-09-24 08:01:38 +0000874 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000875 struct ospf_opaque_functab *functab;
876
paul87d6f872004-09-24 08:01:38 +0000877 LIST_LOOP (funclist, functab, node)
878 if (functab->nsm_change_hook != NULL)
879 (* functab->nsm_change_hook)(nbr, old_status);
paul718e3742002-12-13 20:15:29 +0000880 return;
881}
882
883static void
paul87d6f872004-09-24 08:01:38 +0000884opaque_lsa_config_write_router_callback (struct list *funclist,
885 struct vty *vty)
paul718e3742002-12-13 20:15:29 +0000886{
paul87d6f872004-09-24 08:01:38 +0000887 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000888 struct ospf_opaque_functab *functab;
889
paul87d6f872004-09-24 08:01:38 +0000890 LIST_LOOP (funclist, functab, node)
891 if (functab->config_write_router != NULL)
892 (* functab->config_write_router)(vty);
paul718e3742002-12-13 20:15:29 +0000893 return;
894}
895
896static void
paul87d6f872004-09-24 08:01:38 +0000897opaque_lsa_config_write_if_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000898 struct vty *vty, struct interface *ifp)
899{
paul87d6f872004-09-24 08:01:38 +0000900 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000901 struct ospf_opaque_functab *functab;
902
paul87d6f872004-09-24 08:01:38 +0000903 LIST_LOOP (funclist, functab, node)
904 if (functab->config_write_if != NULL)
905 (* functab->config_write_if)(vty, ifp);
paul718e3742002-12-13 20:15:29 +0000906 return;
907}
908
909static void
paul87d6f872004-09-24 08:01:38 +0000910opaque_lsa_config_write_debug_callback (struct list *funclist, struct vty *vty)
paul718e3742002-12-13 20:15:29 +0000911{
paul87d6f872004-09-24 08:01:38 +0000912 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000913 struct ospf_opaque_functab *functab;
914
paul87d6f872004-09-24 08:01:38 +0000915 LIST_LOOP (funclist, functab, node)
916 if (functab->config_write_debug != NULL)
917 (* functab->config_write_debug)(vty);
paul718e3742002-12-13 20:15:29 +0000918 return;
919}
920
921static int
paul87d6f872004-09-24 08:01:38 +0000922opaque_lsa_originate_callback (struct list *funclist, void *lsa_type_dependent)
paul718e3742002-12-13 20:15:29 +0000923{
paul87d6f872004-09-24 08:01:38 +0000924 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000925 struct ospf_opaque_functab *functab;
926 int rc = -1;
927
paul87d6f872004-09-24 08:01:38 +0000928 LIST_LOOP (funclist, functab, node)
929 if (functab->lsa_originator != NULL)
930 if ((* functab->lsa_originator)(lsa_type_dependent) != 0)
931 goto out;
paul718e3742002-12-13 20:15:29 +0000932 rc = 0;
933out:
934 return rc;
935}
936
937static int
paul87d6f872004-09-24 08:01:38 +0000938new_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000939{
paul87d6f872004-09-24 08:01:38 +0000940 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000941 struct ospf_opaque_functab *functab;
942 int rc = -1;
943
944 /* This function handles ALL types of LSAs, not only opaque ones. */
paul87d6f872004-09-24 08:01:38 +0000945 LIST_LOOP (funclist, functab, node)
946 if (functab->new_lsa_hook != NULL)
947 if ((* functab->new_lsa_hook)(lsa) != 0)
948 goto out;
paul718e3742002-12-13 20:15:29 +0000949 rc = 0;
950out:
951 return rc;
952}
953
954static int
paul87d6f872004-09-24 08:01:38 +0000955del_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000956{
paul87d6f872004-09-24 08:01:38 +0000957 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000958 struct ospf_opaque_functab *functab;
959 int rc = -1;
960
961 /* This function handles ALL types of LSAs, not only opaque ones. */
paul87d6f872004-09-24 08:01:38 +0000962 LIST_LOOP (funclist, functab, node)
963 if (functab->del_lsa_hook != NULL)
964 if ((* functab->del_lsa_hook)(lsa) != 0)
965 goto out;
paul718e3742002-12-13 20:15:29 +0000966 rc = 0;
967out:
968 return rc;
969}
970
971/*------------------------------------------------------------------------*
972 * Followings are glue functions to call Opaque-LSA specific processing.
973 *------------------------------------------------------------------------*/
974
975int
976ospf_opaque_new_if (struct interface *ifp)
977{
paul87d6f872004-09-24 08:01:38 +0000978 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000979 int rc = -1;
980
paul09e4efd2003-01-18 00:12:02 +0000981 funclist = ospf_opaque_wildcard_funclist;
982 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
983 goto out;
984
paul718e3742002-12-13 20:15:29 +0000985 funclist = ospf_opaque_type9_funclist;
986 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
987 goto out;
988
989 funclist = ospf_opaque_type10_funclist;
990 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
991 goto out;
992
993 funclist = ospf_opaque_type11_funclist;
994 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
995 goto out;
996
997 rc = 0;
998out:
999 return rc;
1000}
1001
1002int
1003ospf_opaque_del_if (struct interface *ifp)
1004{
paul87d6f872004-09-24 08:01:38 +00001005 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001006 int rc = -1;
1007
paul09e4efd2003-01-18 00:12:02 +00001008 funclist = ospf_opaque_wildcard_funclist;
1009 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1010 goto out;
1011
paul718e3742002-12-13 20:15:29 +00001012 funclist = ospf_opaque_type9_funclist;
1013 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1014 goto out;
1015
1016 funclist = ospf_opaque_type10_funclist;
1017 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1018 goto out;
1019
1020 funclist = ospf_opaque_type11_funclist;
1021 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1022 goto out;
1023
1024 rc = 0;
1025out:
1026 return rc;
1027}
1028
1029void
1030ospf_opaque_ism_change (struct ospf_interface *oi, int old_status)
1031{
paul87d6f872004-09-24 08:01:38 +00001032 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001033
paul09e4efd2003-01-18 00:12:02 +00001034 funclist = ospf_opaque_wildcard_funclist;
1035 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1036
paul718e3742002-12-13 20:15:29 +00001037 funclist = ospf_opaque_type9_funclist;
1038 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1039
1040 funclist = ospf_opaque_type10_funclist;
1041 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1042
1043 funclist = ospf_opaque_type11_funclist;
1044 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1045
1046 return;
1047}
1048
1049void
1050ospf_opaque_nsm_change (struct ospf_neighbor *nbr, int old_state)
1051{
1052 struct ospf *top;
paul87d6f872004-09-24 08:01:38 +00001053 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001054
1055 if ((top = oi_to_top (nbr->oi)) == NULL)
1056 goto out;
1057
1058 if (old_state != NSM_Full && nbr->state == NSM_Full)
1059 {
1060 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
1061 {
1062 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1063 {
1064 if (IS_DEBUG_OSPF_EVENT)
1065 zlog_info ("Opaque-LSA: Now get operational!");
1066
1067 SET_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT);
1068 }
1069
1070 ospf_opaque_lsa_originate_schedule (nbr->oi, NULL);
1071 }
1072 }
1073 else
1074 if (old_state == NSM_Full && nbr->state != NSM_Full)
1075 {
1076#ifdef NOTYET
1077 /*
1078 * If no more opaque-capable full-state neighbor remains in the
1079 * flooding scope which corresponds to Opaque-LSA type, periodic
1080 * LS flooding should be stopped.
1081 */
1082#endif /* NOTYET */
1083 ;
1084 }
1085
paul09e4efd2003-01-18 00:12:02 +00001086 funclist = ospf_opaque_wildcard_funclist;
1087 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1088
paul718e3742002-12-13 20:15:29 +00001089 funclist = ospf_opaque_type9_funclist;
1090 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1091
1092 funclist = ospf_opaque_type10_funclist;
1093 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1094
1095 funclist = ospf_opaque_type11_funclist;
1096 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1097
1098out:
1099 return;
1100}
1101
1102void
1103ospf_opaque_config_write_router (struct vty *vty, struct ospf *ospf)
1104{
paul87d6f872004-09-24 08:01:38 +00001105 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001106
1107 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
1108 vty_out (vty, " capability opaque%s", VTY_NEWLINE);
1109
paul09e4efd2003-01-18 00:12:02 +00001110 funclist = ospf_opaque_wildcard_funclist;
1111 opaque_lsa_config_write_router_callback (funclist, vty);
1112
paul718e3742002-12-13 20:15:29 +00001113 funclist = ospf_opaque_type9_funclist;
1114 opaque_lsa_config_write_router_callback (funclist, vty);
1115
1116 funclist = ospf_opaque_type10_funclist;
1117 opaque_lsa_config_write_router_callback (funclist, vty);
1118
1119 funclist = ospf_opaque_type11_funclist;
1120 opaque_lsa_config_write_router_callback (funclist, vty);
1121
1122 return;
1123}
1124
1125void
1126ospf_opaque_config_write_if (struct vty *vty, struct interface *ifp)
1127{
paul87d6f872004-09-24 08:01:38 +00001128 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001129
paul09e4efd2003-01-18 00:12:02 +00001130 funclist = ospf_opaque_wildcard_funclist;
1131 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1132
paul718e3742002-12-13 20:15:29 +00001133 funclist = ospf_opaque_type9_funclist;
1134 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1135
1136 funclist = ospf_opaque_type10_funclist;
1137 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1138
1139 funclist = ospf_opaque_type11_funclist;
1140 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1141
1142 return;
1143}
1144
1145void
1146ospf_opaque_config_write_debug (struct vty *vty)
1147{
paul87d6f872004-09-24 08:01:38 +00001148 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001149
paul09e4efd2003-01-18 00:12:02 +00001150 funclist = ospf_opaque_wildcard_funclist;
1151 opaque_lsa_config_write_debug_callback (funclist, vty);
1152
paul718e3742002-12-13 20:15:29 +00001153 funclist = ospf_opaque_type9_funclist;
1154 opaque_lsa_config_write_debug_callback (funclist, vty);
1155
1156 funclist = ospf_opaque_type10_funclist;
1157 opaque_lsa_config_write_debug_callback (funclist, vty);
1158
1159 funclist = ospf_opaque_type11_funclist;
1160 opaque_lsa_config_write_debug_callback (funclist, vty);
1161
1162 return;
1163}
1164
1165void
1166show_opaque_info_detail (struct vty *vty, struct ospf_lsa *lsa)
1167{
1168 struct lsa_header *lsah = (struct lsa_header *) lsa->data;
1169 u_int32_t lsid = ntohl (lsah->id.s_addr);
1170 u_char opaque_type = GET_OPAQUE_TYPE (lsid);
1171 u_int32_t opaque_id = GET_OPAQUE_ID (lsid);
1172 struct ospf_opaque_functab *functab;
1173
1174 /* Switch output functionality by vty address. */
1175 if (vty != NULL)
1176 {
paul020709f2003-04-04 02:44:16 +00001177 vty_out (vty, " Opaque-Type %u (%s)%s", opaque_type,
1178 ospf_opaque_type_name (opaque_type), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001179 vty_out (vty, " Opaque-ID 0x%x%s", opaque_id, VTY_NEWLINE);
1180
1181 vty_out (vty, " Opaque-Info: %u octets of data%s%s",
1182 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1183 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)",
1184 VTY_NEWLINE);
1185 }
1186 else
1187 {
paul020709f2003-04-04 02:44:16 +00001188 zlog_info (" Opaque-Type %u (%s)", opaque_type,
1189 ospf_opaque_type_name (opaque_type));
paul718e3742002-12-13 20:15:29 +00001190 zlog_info (" Opaque-ID 0x%x", opaque_id);
1191
1192 zlog_info (" Opaque-Info: %u octets of data%s",
1193 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1194 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)");
1195 }
1196
1197 /* Call individual output functions. */
1198 if ((functab = ospf_opaque_functab_lookup (lsa)) != NULL)
1199 if (functab->show_opaque_info != NULL)
1200 (* functab->show_opaque_info)(vty, lsa);
1201
1202 return;
1203}
1204
1205void
1206ospf_opaque_lsa_dump (struct stream *s, u_int16_t length)
1207{
1208 struct ospf_lsa lsa;
1209
1210 lsa.data = (struct lsa_header *) STREAM_PNT (s);
1211 show_opaque_info_detail (NULL, &lsa);
1212 return;
1213}
1214
1215static int
1216ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa)
1217{
paul87d6f872004-09-24 08:01:38 +00001218 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001219 int rc = -1;
1220
1221 /*
1222 * Some Opaque-LSA user may want to monitor every LSA installation
1223 * into the LSDB, regardless with target LSA type.
1224 */
paul09e4efd2003-01-18 00:12:02 +00001225 funclist = ospf_opaque_wildcard_funclist;
1226 if (new_lsa_callback (funclist, lsa) != 0)
1227 goto out;
1228
paul718e3742002-12-13 20:15:29 +00001229 funclist = ospf_opaque_type9_funclist;
1230 if (new_lsa_callback (funclist, lsa) != 0)
1231 goto out;
1232
1233 funclist = ospf_opaque_type10_funclist;
1234 if (new_lsa_callback (funclist, lsa) != 0)
1235 goto out;
1236
1237 funclist = ospf_opaque_type11_funclist;
1238 if (new_lsa_callback (funclist, lsa) != 0)
1239 goto out;
1240
1241 rc = 0;
1242out:
1243 return rc;
1244}
1245
1246static int
1247ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa)
1248{
paul87d6f872004-09-24 08:01:38 +00001249 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001250 int rc = -1;
1251
1252 /*
1253 * Some Opaque-LSA user may want to monitor every LSA deletion
1254 * from the LSDB, regardless with target LSA type.
1255 */
paul09e4efd2003-01-18 00:12:02 +00001256 funclist = ospf_opaque_wildcard_funclist;
1257 if (del_lsa_callback (funclist, lsa) != 0)
1258 goto out;
1259
paul718e3742002-12-13 20:15:29 +00001260 funclist = ospf_opaque_type9_funclist;
1261 if (del_lsa_callback (funclist, lsa) != 0)
1262 goto out;
1263
1264 funclist = ospf_opaque_type10_funclist;
1265 if (del_lsa_callback (funclist, lsa) != 0)
1266 goto out;
1267
1268 funclist = ospf_opaque_type11_funclist;
1269 if (del_lsa_callback (funclist, lsa) != 0)
1270 goto out;
1271
1272 rc = 0;
1273out:
1274 return rc;
1275}
1276
1277/*------------------------------------------------------------------------*
1278 * Followings are Opaque-LSA origination/refresh management functions.
1279 *------------------------------------------------------------------------*/
1280
1281static int ospf_opaque_type9_lsa_originate (struct thread *t);
1282static int ospf_opaque_type10_lsa_originate (struct thread *t);
1283static int ospf_opaque_type11_lsa_originate (struct thread *t);
paul87d6f872004-09-24 08:01:38 +00001284static void ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg);
paul718e3742002-12-13 20:15:29 +00001285
1286void
1287ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0)
1288{
1289 struct ospf *top;
1290 struct ospf_area *area;
paul87d6f872004-09-24 08:01:38 +00001291 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001292 struct opaque_info_per_type *oipt;
1293 int delay = 0;
1294
1295 if ((top = oi_to_top (oi)) == NULL || (area = oi->area) == NULL)
1296 {
1297 zlog_warn ("ospf_opaque_lsa_originate_schedule: Invalid argument?");
1298 goto out;
1299 }
1300
1301 /* It may not a right time to schedule origination now. */
1302 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1303 {
1304 if (IS_DEBUG_OSPF_EVENT)
1305 zlog_info ("ospf_opaque_lsa_originate_schedule: Not operational.");
1306 goto out; /* This is not an error. */
1307 }
1308 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
1309 {
1310 if (IS_DEBUG_OSPF_EVENT)
1311 zlog_info ("ospf_opaque_lsa_originate_schedule: Under blockade.");
1312 goto out; /* This is not an error, too. */
1313 }
1314
1315 if (delay0 != NULL)
1316 delay = *delay0;
1317
1318 /*
1319 * There might be some entries that have been waiting for triggering
1320 * of per opaque-type re-origination get resumed.
1321 */
1322 ospf_opaque_lsa_reoriginate_resume ( oi->opaque_lsa_self, (void *) oi);
1323 ospf_opaque_lsa_reoriginate_resume (area->opaque_lsa_self, (void *) area);
1324 ospf_opaque_lsa_reoriginate_resume ( top->opaque_lsa_self, (void *) top);
1325
1326 /*
1327 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1328 */
1329 if (! list_isempty (ospf_opaque_type9_funclist)
1330 && list_isempty (oi->opaque_lsa_self)
1331 && oi->t_opaque_lsa_self == NULL)
1332 {
1333 if (IS_DEBUG_OSPF_EVENT)
1334 zlog_info ("Schedule Type-9 Opaque-LSA origination in %d sec later.", delay);
1335 oi->t_opaque_lsa_self =
1336 thread_add_timer (master, ospf_opaque_type9_lsa_originate, oi, delay);
1337 delay += OSPF_MIN_LS_INTERVAL;
1338 }
1339
1340 if (! list_isempty (ospf_opaque_type10_funclist)
1341 && list_isempty (area->opaque_lsa_self)
1342 && area->t_opaque_lsa_self == NULL)
1343 {
1344 /*
1345 * One AREA may contain multiple OIs, but above 2nd and 3rd
1346 * conditions prevent from scheduling the originate function
1347 * again and again.
1348 */
1349 if (IS_DEBUG_OSPF_EVENT)
1350 zlog_info ("Schedule Type-10 Opaque-LSA origination in %d sec later.", delay);
1351 area->t_opaque_lsa_self =
1352 thread_add_timer (master, ospf_opaque_type10_lsa_originate,
1353 area, delay);
1354 delay += OSPF_MIN_LS_INTERVAL;
1355 }
1356
1357 if (! list_isempty (ospf_opaque_type11_funclist)
1358 && list_isempty (top->opaque_lsa_self)
1359 && top->t_opaque_lsa_self == NULL)
1360 {
1361 /*
1362 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1363 * conditions prevent from scheduling the originate function
1364 * again and again.
1365 */
1366 if (IS_DEBUG_OSPF_EVENT)
1367 zlog_info ("Schedule Type-11 Opaque-LSA origination in %d sec later.", delay);
1368 top->t_opaque_lsa_self =
1369 thread_add_timer (master, ospf_opaque_type11_lsa_originate,
1370 top, delay);
1371 delay += OSPF_MIN_LS_INTERVAL;
1372 }
1373
1374 /*
1375 * Following section treats a special situation that this node's
1376 * opaque capability has changed as "ON -> OFF -> ON".
1377 */
1378 if (! list_isempty (ospf_opaque_type9_funclist)
1379 && ! list_isempty (oi->opaque_lsa_self))
1380 {
1381 for (node = listhead (oi->opaque_lsa_self); node; nextnode (node))
1382 {
hasso0d85b992004-03-18 19:18:33 +00001383 /*
1384 * removed the test for
1385 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1386 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1387 * not being empty.
1388 */
paul718e3742002-12-13 20:15:29 +00001389 if ((oipt = getdata (node)) == NULL /* Something wrong? */
1390 || oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
hasso0d85b992004-03-18 19:18:33 +00001391 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001392 continue;
1393
1394 ospf_opaque_lsa_reoriginate_schedule ((void *) oi,
1395 OSPF_OPAQUE_LINK_LSA, oipt->opaque_type);
1396 }
1397 }
1398
1399 if (! list_isempty (ospf_opaque_type10_funclist)
1400 && ! list_isempty (area->opaque_lsa_self))
1401 {
1402 for (node = listhead (area->opaque_lsa_self); node; nextnode (node))
1403 {
hasso0d85b992004-03-18 19:18:33 +00001404 /*
1405 * removed the test for
1406 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1407 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1408 * not being empty.
1409 */
paul718e3742002-12-13 20:15:29 +00001410 if ((oipt = getdata (node)) == NULL /* Something wrong? */
1411 || oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
hasso0d85b992004-03-18 19:18:33 +00001412 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001413 continue;
1414
1415 ospf_opaque_lsa_reoriginate_schedule ((void *) area,
1416 OSPF_OPAQUE_AREA_LSA, oipt->opaque_type);
1417 }
1418 }
1419
1420 if (! list_isempty (ospf_opaque_type11_funclist)
1421 && ! list_isempty (top->opaque_lsa_self))
1422 {
1423 for (node = listhead (top->opaque_lsa_self); node; nextnode (node))
1424 {
hasso0d85b992004-03-18 19:18:33 +00001425 /*
1426 * removed the test for
1427 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1428 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1429 * not being empty.
1430 */
paul718e3742002-12-13 20:15:29 +00001431 if ((oipt = getdata (node)) == NULL /* Something wrong? */
1432 || oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
hasso0d85b992004-03-18 19:18:33 +00001433 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001434 continue;
1435
1436 ospf_opaque_lsa_reoriginate_schedule ((void *) top,
1437 OSPF_OPAQUE_AS_LSA, oipt->opaque_type);
1438 }
1439 }
1440
1441 if (delay0 != NULL)
1442 *delay0 = delay;
1443
1444out:
1445 return;
1446}
1447
1448static int
1449ospf_opaque_type9_lsa_originate (struct thread *t)
1450{
1451 struct ospf_interface *oi;
1452 int rc;
1453
1454 oi = THREAD_ARG (t);
1455 oi->t_opaque_lsa_self = NULL;
1456
1457 if (IS_DEBUG_OSPF_EVENT)
1458 zlog_info ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
1459 IF_NAME (oi));
1460
1461 rc = opaque_lsa_originate_callback (ospf_opaque_type9_funclist, oi);
1462
1463 return rc;
1464}
1465
1466static int
1467ospf_opaque_type10_lsa_originate (struct thread *t)
1468{
1469 struct ospf_area *area;
1470 int rc;
1471
1472 area = THREAD_ARG (t);
1473 area->t_opaque_lsa_self = NULL;
1474
1475 if (IS_DEBUG_OSPF_EVENT)
1476 zlog_info ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
1477 inet_ntoa (area->area_id));
1478
1479 rc = opaque_lsa_originate_callback (ospf_opaque_type10_funclist, area);
1480
1481 return rc;
1482}
1483
1484static int
1485ospf_opaque_type11_lsa_originate (struct thread *t)
1486{
1487 struct ospf *top;
1488 int rc;
1489
1490 top = THREAD_ARG (t);
1491 top->t_opaque_lsa_self = NULL;
1492
1493 if (IS_DEBUG_OSPF_EVENT)
1494 zlog_info ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
1495
1496 rc = opaque_lsa_originate_callback (ospf_opaque_type11_funclist, top);
1497
1498 return rc;
1499}
1500
1501static void
paul87d6f872004-09-24 08:01:38 +00001502ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg)
paul718e3742002-12-13 20:15:29 +00001503{
paul87d6f872004-09-24 08:01:38 +00001504 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001505 struct opaque_info_per_type *oipt;
1506 struct ospf_opaque_functab *functab;
1507
1508 if (listtop == NULL)
1509 goto out;
1510
1511 /*
1512 * Pickup oipt entries those which in SUSPEND status, and give
1513 * them a chance to start re-origination now.
1514 */
paul87d6f872004-09-24 08:01:38 +00001515 LIST_LOOP (listtop, oipt, node)
paul718e3742002-12-13 20:15:29 +00001516 {
paul87d6f872004-09-24 08:01:38 +00001517 if (oipt->status != PROC_SUSPEND)
paul718e3742002-12-13 20:15:29 +00001518 continue;
1519
1520 oipt->status = PROC_NORMAL;
1521
1522 if ((functab = oipt->functab) == NULL
paul87d6f872004-09-24 08:01:38 +00001523 || functab->lsa_originator == NULL)
paul718e3742002-12-13 20:15:29 +00001524 continue;
1525
1526 if ((* functab->lsa_originator)(arg) != 0)
1527 {
1528 zlog_warn ("ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", oipt->opaque_type);
1529 continue;
1530 }
1531 }
1532
1533out:
1534 return;
1535}
1536
1537struct ospf_lsa *
1538ospf_opaque_lsa_install (struct ospf_lsa *lsa, int rt_recalc)
1539{
1540 struct ospf_lsa *new = NULL;
1541 struct opaque_info_per_type *oipt;
1542 struct opaque_info_per_id *oipi;
1543 struct ospf *top;
1544
1545 /* Don't take "rt_recalc" into consideration for now. *//* XXX */
1546
1547 if (! IS_LSA_SELF (lsa))
1548 {
1549 new = lsa; /* Don't touch this LSA. */
1550 goto out;
1551 }
1552
1553 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
1554 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)));
1555
1556 /* Replace the existing lsa with the new one. */
1557 if ((oipt = lookup_opaque_info_by_type (lsa)) != NULL
paul87d6f872004-09-24 08:01:38 +00001558 && (oipi = lookup_opaque_info_by_id (oipt, lsa)) != NULL)
paul718e3742002-12-13 20:15:29 +00001559 {
1560 ospf_lsa_unlock (oipi->lsa);
1561 oipi->lsa = ospf_lsa_lock (lsa);
1562 }
1563 /* Register the new lsa entry and get its control info. */
1564 else
1565 if ((oipi = register_opaque_lsa (lsa)) == NULL)
1566 {
1567 zlog_warn ("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1568 goto out;
1569 }
1570
1571 /*
1572 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1573 * for periodic refresh of self-originated Opaque-LSAs.
1574 */
1575 switch (lsa->data->type)
1576 {
1577 case OSPF_OPAQUE_LINK_LSA:
paul09e4efd2003-01-18 00:12:02 +00001578 if ((top = oi_to_top (lsa->oi)) == NULL)
1579 {
1580 /* Above conditions must have passed. */
1581 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1582 goto out;
1583 }
1584 break;
paul718e3742002-12-13 20:15:29 +00001585 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00001586 if (lsa->area == NULL || (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001587 {
1588 /* Above conditions must have passed. */
1589 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1590 goto out;
1591 }
1592 break;
1593 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +00001594 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001595 if (lsa->area != NULL && (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001596 {
1597 /* Above conditions must have passed. */
1598 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1599 goto out;
1600 }
1601 break;
1602 default:
1603 zlog_warn ("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", lsa->data->type);
1604 goto out;
1605 }
1606
1607 ospf_refresher_register_lsa (top, lsa);
1608 new = lsa;
1609
1610out:
1611 return new;
1612}
1613
1614void
1615ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
1616{
paul020709f2003-04-04 02:44:16 +00001617 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001618 struct ospf_opaque_functab *functab;
1619
paul020709f2003-04-04 02:44:16 +00001620 ospf = ospf_lookup ();
1621
paul718e3742002-12-13 20:15:29 +00001622 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL
paul87d6f872004-09-24 08:01:38 +00001623 || functab->lsa_refresher == NULL)
paul718e3742002-12-13 20:15:29 +00001624 {
1625 /*
1626 * Though this LSA seems to have originated on this node, the
1627 * handling module for this "lsa-type and opaque-type" was
1628 * already deleted sometime ago.
1629 * Anyway, this node still has a responsibility to flush this
1630 * LSA from the routing domain.
1631 */
1632 if (IS_DEBUG_OSPF_EVENT)
1633 zlog_info ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id));
1634
1635 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
paul68980082003-03-25 05:07:42 +00001636 ospf_lsa_maxage (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00001637 }
1638 else
1639 (* functab->lsa_refresher)(lsa);
1640
1641 return;
1642}
1643
1644/*------------------------------------------------------------------------*
1645 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1646 * triggered by external interventions (vty session, signaling, etc).
1647 *------------------------------------------------------------------------*/
1648
1649#define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
1650 if (!(T)) \
1651 (T) = thread_add_timer (master, (F), (L), (V))
1652
1653static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type);
1654static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t);
1655static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t);
1656static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t);
1657static int ospf_opaque_lsa_refresh_timer (struct thread *t);
1658
1659void
1660ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
1661 u_char lsa_type, u_char opaque_type)
1662{
1663 struct ospf *top;
1664 struct ospf_area dummy, *area = NULL;
1665 struct ospf_interface *oi = NULL;
1666
1667 struct ospf_lsa *lsa;
1668 struct opaque_info_per_type *oipt;
paul87d6f872004-09-24 08:01:38 +00001669 int (*func) (struct thread * t) = NULL;
paul718e3742002-12-13 20:15:29 +00001670 int delay;
1671
1672 switch (lsa_type)
1673 {
1674 case OSPF_OPAQUE_LINK_LSA:
1675 if ((oi = (struct ospf_interface *) lsa_type_dependent) == NULL)
1676 {
paul87d6f872004-09-24 08:01:38 +00001677 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1678 " Type-9 Opaque-LSA: Invalid parameter?");
1679 goto out;
paul718e3742002-12-13 20:15:29 +00001680 }
1681 if ((top = oi_to_top (oi)) == NULL)
1682 {
paul87d6f872004-09-24 08:01:38 +00001683 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1684 IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001685 goto out;
1686 }
paul87d6f872004-09-24 08:01:38 +00001687 if (!list_isempty (ospf_opaque_type9_funclist)
1688 && list_isempty (oi->opaque_lsa_self)
1689 && oi->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001690 {
paul87d6f872004-09-24 08:01:38 +00001691 zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u):"
1692 " Common origination for OI(%s) has already started",
1693 opaque_type, IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001694 goto out;
1695 }
1696 func = ospf_opaque_type9_lsa_reoriginate_timer;
1697 break;
1698 case OSPF_OPAQUE_AREA_LSA:
1699 if ((area = (struct ospf_area *) lsa_type_dependent) == NULL)
1700 {
paul87d6f872004-09-24 08:01:38 +00001701 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1702 " Type-10 Opaque-LSA: Invalid parameter?");
paul718e3742002-12-13 20:15:29 +00001703 goto out;
1704 }
paul68980082003-03-25 05:07:42 +00001705 if ((top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001706 {
paul87d6f872004-09-24 08:01:38 +00001707 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1708 " AREA(%s) -> TOP?", inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001709 goto out;
1710 }
paul87d6f872004-09-24 08:01:38 +00001711 if (!list_isempty (ospf_opaque_type10_funclist)
1712 && list_isempty (area->opaque_lsa_self)
1713 && area->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001714 {
paul87d6f872004-09-24 08:01:38 +00001715 zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u):"
1716 " Common origination for AREA(%s) has already started",
1717 opaque_type, inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001718 goto out;
1719 }
1720 func = ospf_opaque_type10_lsa_reoriginate_timer;
1721 break;
1722 case OSPF_OPAQUE_AS_LSA:
1723 if ((top = (struct ospf *) lsa_type_dependent) == NULL)
1724 {
paul87d6f872004-09-24 08:01:38 +00001725 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1726 " Type-11 Opaque-LSA: Invalid parameter?");
1727 goto out;
paul718e3742002-12-13 20:15:29 +00001728 }
paul87d6f872004-09-24 08:01:38 +00001729 if (!list_isempty (ospf_opaque_type11_funclist)
1730 && list_isempty (top->opaque_lsa_self)
1731 && top->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001732 {
paul87d6f872004-09-24 08:01:38 +00001733 zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u):"
1734 " Common origination has already started", opaque_type);
paul718e3742002-12-13 20:15:29 +00001735 goto out;
1736 }
1737
1738 /* Fake "area" to pass "ospf" to a lookup function later. */
paul68980082003-03-25 05:07:42 +00001739 dummy.ospf = top;
paul718e3742002-12-13 20:15:29 +00001740 area = &dummy;
1741
1742 func = ospf_opaque_type11_lsa_reoriginate_timer;
1743 break;
1744 default:
paul87d6f872004-09-24 08:01:38 +00001745 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1746 " Unexpected LSA-type(%u)",
1747 lsa_type);
paul718e3742002-12-13 20:15:29 +00001748 goto out;
1749 }
1750
1751 /* It may not a right time to schedule reorigination now. */
paul87d6f872004-09-24 08:01:38 +00001752 if (!CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
paul718e3742002-12-13 20:15:29 +00001753 {
1754 if (IS_DEBUG_OSPF_EVENT)
1755 zlog_info ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
paul87d6f872004-09-24 08:01:38 +00001756 goto out; /* This is not an error. */
paul718e3742002-12-13 20:15:29 +00001757 }
1758 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
1759 {
1760 if (IS_DEBUG_OSPF_EVENT)
1761 zlog_info ("ospf_opaque_lsa_reoriginate_schedule: Under blockade.");
paul87d6f872004-09-24 08:01:38 +00001762 goto out; /* This is not an error, too. */
paul718e3742002-12-13 20:15:29 +00001763 }
1764
1765 /* Generate a dummy lsa to be passed for a lookup function. */
1766 lsa = pseudo_lsa (oi, area, lsa_type, opaque_type);
1767
1768 if ((oipt = lookup_opaque_info_by_type (lsa)) == NULL)
1769 {
1770 struct ospf_opaque_functab *functab;
1771 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL)
1772 {
paul87d6f872004-09-24 08:01:38 +00001773 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1774 " No associated function?: lsa_type(%u),"
1775 " opaque_type(%u)",
1776 lsa_type, opaque_type);
paul718e3742002-12-13 20:15:29 +00001777 goto out;
1778 }
1779 if ((oipt = register_opaque_info_per_type (functab, lsa)) == NULL)
1780 {
paul87d6f872004-09-24 08:01:38 +00001781 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1782 " Cannot get a control info?: lsa_type(%u),"
1783 " opaque_type(%u)",
1784 lsa_type, opaque_type);
paul718e3742002-12-13 20:15:29 +00001785 goto out;
1786 }
1787 }
1788
1789 if (oipt->t_opaque_lsa_self != NULL)
1790 {
1791 if (IS_DEBUG_OSPF_EVENT)
paul87d6f872004-09-24 08:01:38 +00001792 zlog_info ("Type-%u Opaque-LSA has already scheduled to"
1793 " RE-ORIGINATE: [opaque-type=%u]",
1794 lsa_type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
paul718e3742002-12-13 20:15:29 +00001795 goto out;
1796 }
1797
1798 /*
1799 * Different from initial origination time, in which various conditions
1800 * (opaque capability, neighbor status etc) are assured by caller of
1801 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1802 * it is highly possible that these conditions might not be satisfied
1803 * at the time of re-origination function is to be called.
1804 */
1805 delay = OSPF_MIN_LS_INTERVAL; /* XXX */
1806
1807 if (IS_DEBUG_OSPF_EVENT)
paul87d6f872004-09-24 08:01:38 +00001808 zlog_info ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
1809 " sec later: [opaque-type=%u]",
1810 lsa_type, delay,
1811 GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
paul718e3742002-12-13 20:15:29 +00001812
1813 OSPF_OPAQUE_TIMER_ON (oipt->t_opaque_lsa_self, func, oipt, delay);
1814
1815out:
1816 return;
1817}
1818
1819static struct ospf_lsa *
1820pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area,
1821 u_char lsa_type, u_char opaque_type)
1822{
1823 static struct ospf_lsa lsa = { 0 };
1824 static struct lsa_header lsah = { 0 };
1825 u_int32_t tmp;
1826
1827 lsa.oi = oi;
1828 lsa.area = area;
1829 lsa.data = &lsah;
1830
1831 lsah.type = lsa_type;
1832 tmp = SET_OPAQUE_LSID (opaque_type, 0); /* Opaque-ID is unused here. */
1833 lsah.id.s_addr = htonl (tmp);
1834
1835 return &lsa;
1836}
1837
1838static int
1839ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t)
1840{
1841 struct opaque_info_per_type *oipt;
1842 struct ospf_opaque_functab *functab;
1843 struct ospf *top;
1844 struct ospf_interface *oi;
1845 int rc = -1;
1846
1847 oipt = THREAD_ARG (t);
1848 oipt->t_opaque_lsa_self = NULL;
1849
1850 if ((functab = oipt->functab) == NULL
1851 || functab->lsa_originator == NULL)
1852 {
1853 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1854 goto out;
1855 }
1856
1857 oi = (struct ospf_interface *) oipt->owner;
1858 if ((top = oi_to_top (oi)) == NULL)
1859 {
1860 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1861 goto out;
1862 }
1863
1864 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)
1865 || ! ospf_if_is_enable (oi)
paul68980082003-03-25 05:07:42 +00001866 || ospf_nbr_count_opaque_capable (oi) == 0)
paul718e3742002-12-13 20:15:29 +00001867 {
1868 if (IS_DEBUG_OSPF_EVENT)
1869 zlog_info ("Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
1870
1871 oipt->status = PROC_SUSPEND;
1872 rc = 0;
1873 goto out;
1874 }
1875
1876 if (IS_DEBUG_OSPF_EVENT)
1877 zlog_info ("Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)", oipt->opaque_type, IF_NAME (oi));
1878
1879 rc = (* functab->lsa_originator)(oi);
1880out:
1881 return rc;
1882}
1883
1884static int
1885ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t)
1886{
1887 struct opaque_info_per_type *oipt;
1888 struct ospf_opaque_functab *functab;
paul87d6f872004-09-24 08:01:38 +00001889 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001890 struct ospf *top;
1891 struct ospf_area *area;
1892 struct ospf_interface *oi;
1893 int n, rc = -1;
1894
1895 oipt = THREAD_ARG (t);
1896 oipt->t_opaque_lsa_self = NULL;
1897
1898 if ((functab = oipt->functab) == NULL
1899 || functab->lsa_originator == NULL)
1900 {
1901 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1902 goto out;
1903 }
1904
1905 area = (struct ospf_area *) oipt->owner;
paul68980082003-03-25 05:07:42 +00001906 if (area == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001907 {
1908 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1909 goto out;
1910 }
1911
1912 /* There must be at least one "opaque-capable, full-state" neighbor. */
1913 n = 0;
paul87d6f872004-09-24 08:01:38 +00001914 LIST_LOOP (area->oiflist, oi, node)
paul718e3742002-12-13 20:15:29 +00001915 {
paul68980082003-03-25 05:07:42 +00001916 if ((n = ospf_nbr_count_opaque_capable (oi)) > 0)
paul718e3742002-12-13 20:15:29 +00001917 break;
1918 }
1919
1920 if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1921 {
1922 if (IS_DEBUG_OSPF_EVENT)
paul87d6f872004-09-24 08:01:38 +00001923 zlog_info ("Suspend re-origination of Type-10 Opaque-LSAs"
1924 " (opaque-type=%u) for a while...",
1925 oipt->opaque_type);
paul718e3742002-12-13 20:15:29 +00001926
1927 oipt->status = PROC_SUSPEND;
1928 rc = 0;
1929 goto out;
1930 }
1931
1932 if (IS_DEBUG_OSPF_EVENT)
paul87d6f872004-09-24 08:01:38 +00001933 zlog_info ("Timer[Type10-LSA]: Re-originate Opaque-LSAs"
1934 " (opaque-type=%u) for Area %s",
1935 oipt->opaque_type, inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001936
1937 rc = (* functab->lsa_originator)(area);
1938out:
1939 return rc;
1940}
1941
1942static int
1943ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t)
1944{
1945 struct opaque_info_per_type *oipt;
1946 struct ospf_opaque_functab *functab;
1947 struct ospf *top;
1948 int rc = -1;
1949
1950 oipt = THREAD_ARG (t);
1951 oipt->t_opaque_lsa_self = NULL;
1952
1953 if ((functab = oipt->functab) == NULL
paul87d6f872004-09-24 08:01:38 +00001954 || functab->lsa_originator == NULL)
paul718e3742002-12-13 20:15:29 +00001955 {
paul87d6f872004-09-24 08:01:38 +00001956 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer:"
1957 " No associated function?");
paul718e3742002-12-13 20:15:29 +00001958 goto out;
1959 }
1960
1961 if ((top = (struct ospf *) oipt->owner) == NULL)
1962 {
1963 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1964 goto out;
1965 }
1966
1967 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1968 {
1969 if (IS_DEBUG_OSPF_EVENT)
1970 zlog_info ("Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
1971
1972 oipt->status = PROC_SUSPEND;
1973 rc = 0;
1974 goto out;
1975 }
1976
1977 if (IS_DEBUG_OSPF_EVENT)
1978 zlog_info ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type);
1979
1980 rc = (* functab->lsa_originator)(top);
1981out:
1982 return rc;
1983}
1984
1985extern int ospf_lsa_refresh_delay (struct ospf_lsa *); /* ospf_lsa.c */
1986
1987void
1988ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
1989{
paul020709f2003-04-04 02:44:16 +00001990 struct ospf *ospf = ospf;
paul718e3742002-12-13 20:15:29 +00001991 struct opaque_info_per_type *oipt;
1992 struct opaque_info_per_id *oipi;
1993 struct ospf_lsa *lsa;
1994 int delay;
1995
paul020709f2003-04-04 02:44:16 +00001996 ospf = ospf_lookup ();
1997
paul718e3742002-12-13 20:15:29 +00001998 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
1999 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
2000 {
2001 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
2002 goto out;
2003 }
2004
2005 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2006 if ((lsa = oipi->lsa) == NULL)
2007 {
2008 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
2009 goto out;
2010 }
2011
2012 if (oipi->t_opaque_lsa_self != NULL)
2013 {
2014 if (IS_DEBUG_OSPF_EVENT)
2015 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)));
2016 goto out;
2017 }
2018
2019 /* Delete this lsa from neighbor retransmit-list. */
2020 switch (lsa->data->type)
2021 {
2022 case OSPF_OPAQUE_LINK_LSA:
2023 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002024 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002025 break;
2026 case OSPF_OPAQUE_AS_LSA:
paul68980082003-03-25 05:07:42 +00002027 ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002028 break;
2029 default:
2030 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2031 goto out;
2032 }
2033
2034 delay = ospf_lsa_refresh_delay (lsa);
2035
2036 if (IS_DEBUG_OSPF_EVENT)
2037 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)));
2038
2039 OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self,
2040 ospf_opaque_lsa_refresh_timer, oipi, delay);
2041out:
2042 return;
2043}
2044
2045static int
2046ospf_opaque_lsa_refresh_timer (struct thread *t)
2047{
2048 struct opaque_info_per_id *oipi;
2049 struct ospf_opaque_functab *functab;
2050 struct ospf_lsa *lsa;
2051
2052 if (IS_DEBUG_OSPF_EVENT)
2053 zlog_info ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
2054
2055 oipi = THREAD_ARG (t);
2056 oipi->t_opaque_lsa_self = NULL;
2057
2058 if ((lsa = oipi->lsa) != NULL)
2059 if ((functab = oipi->opqctl_type->functab) != NULL)
2060 if (functab->lsa_refresher != NULL)
2061 (* functab->lsa_refresher)(lsa);
2062
2063 return 0;
2064}
2065
2066void
2067ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
2068{
paul020709f2003-04-04 02:44:16 +00002069 struct ospf *ospf = ospf;
paul718e3742002-12-13 20:15:29 +00002070 struct opaque_info_per_type *oipt;
2071 struct opaque_info_per_id *oipi;
2072 struct ospf_lsa *lsa;
2073
paul020709f2003-04-04 02:44:16 +00002074 ospf = ospf_lookup ();
2075
paul718e3742002-12-13 20:15:29 +00002076 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
2077 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
2078 {
2079 zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2080 goto out;
2081 }
2082
2083 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2084 if ((lsa = oipi->lsa) == NULL)
2085 {
2086 zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
2087 goto out;
2088 }
2089
2090 /* Delete this lsa from neighbor retransmit-list. */
2091 switch (lsa->data->type)
2092 {
2093 case OSPF_OPAQUE_LINK_LSA:
2094 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002095 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002096 break;
2097 case OSPF_OPAQUE_AS_LSA:
paul68980082003-03-25 05:07:42 +00002098 ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002099 break;
2100 default:
2101 zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2102 goto out;
2103 }
2104
2105 /* Dequeue listnode entry from the list. */
2106 listnode_delete (oipt->id_list, oipi);
2107
2108 /* Avoid misjudgement in the next lookup. */
2109 if (listcount (oipt->id_list) == 0)
2110 oipt->id_list->head = oipt->id_list->tail = NULL;
2111
2112 /* Disassociate internal control information with the given lsa. */
paul718e3742002-12-13 20:15:29 +00002113 free_opaque_info_per_id ((void *) oipi);
2114
2115 /* Force given lsa's age to MaxAge. */
2116 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2117
2118 if (IS_DEBUG_OSPF_EVENT)
2119 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)));
2120
2121 /* This lsa will be flushed and removed eventually. */
paul68980082003-03-25 05:07:42 +00002122 ospf_lsa_maxage (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002123
2124out:
2125 return;
2126}
2127
2128/*------------------------------------------------------------------------*
2129 * Followings are control functions to block origination after restart.
2130 *------------------------------------------------------------------------*/
2131
2132static void ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs, struct ospf_neighbor *inbr, struct ospf_lsa *lsa);
2133static void ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi);
2134static void ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area);
2135static void ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top);
2136static unsigned long ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type);
2137
2138void
paul87d6f872004-09-24 08:01:38 +00002139ospf_opaque_adjust_lsreq (struct ospf_neighbor *nbr, struct list *lsas)
paul718e3742002-12-13 20:15:29 +00002140{
2141 struct ospf *top;
2142 struct ospf_area *area;
2143 struct ospf_interface *oi;
paul87d6f872004-09-24 08:01:38 +00002144 struct listnode *node1, *node2;
paul718e3742002-12-13 20:15:29 +00002145 struct ospf_lsa *lsa;
2146
2147 if ((top = oi_to_top (nbr->oi)) == NULL)
2148 goto out;
2149
2150 /*
2151 * If an instance of self-originated Opaque-LSA is found in the given
2152 * LSA list, and it is not installed to LSDB yet, exclude it from the
2153 * list "nbr->ls_req". In this way, it is assured that an LSReq message,
2154 * which might be sent in the process of flooding, will not request for
2155 * the LSA to be flushed immediately; otherwise, depending on timing,
2156 * an LSUpd message will carry instances of target LSAs with MaxAge,
2157 * while other LSUpd message might carry old LSA instances (non-MaxAge).
2158 * Obviously, the latter would trigger miserable situations that repeat
2159 * installation and removal of unwanted LSAs indefinitely.
2160 */
2161 for (node1 = listhead (lsas); node1; nextnode (node1))
2162 {
2163 if ((lsa = getdata (node1)) == NULL)
2164 continue;
2165
2166 /* Filter out unwanted LSAs. */
2167 if (! IS_OPAQUE_LSA (lsa->data->type))
2168 continue;
2169 if (! IPV4_ADDR_SAME (&lsa->data->adv_router, &top->router_id))
2170 continue;
2171
2172 /*
2173 * Don't touch an LSA which has MaxAge; two possible cases.
2174 *
2175 * 1) This LSA has originally flushed by myself (received LSUpd
2176 * message's router-id is equal to my router-id), and flooded
2177 * back by an opaque-capable router.
2178 *
2179 * 2) This LSA has expired in an opaque-capable router and thus
2180 * flushed by the router.
2181 */
2182 if (IS_LSA_MAXAGE (lsa))
2183 continue;
2184
2185 /* If the LSA has installed in the LSDB, nothing to do here. */
2186 if (ospf_lsa_lookup_by_header (nbr->oi->area, lsa->data) != NULL)
2187 continue;
2188
2189 /* Ok, here we go. */
2190 switch (lsa->data->type)
2191 {
2192 case OSPF_OPAQUE_LINK_LSA:
2193 oi = nbr->oi;
2194 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2195 break;
2196 case OSPF_OPAQUE_AREA_LSA:
2197 area = nbr->oi->area;
2198 for (node2 = listhead (area->oiflist); node2; nextnode (node2))
2199 {
2200 if ((oi = getdata (node2)) == NULL)
2201 continue;
2202 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2203 }
2204 break;
2205 case OSPF_OPAQUE_AS_LSA:
2206 for (node2 = listhead (top->oiflist); node2; nextnode (node2))
2207 {
2208 if ((oi = getdata (node2)) == NULL)
2209 continue;
2210 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2211 }
2212 break;
2213 default:
2214 break;
2215 }
2216 }
2217
2218out:
2219 return;
2220}
2221
2222static void
2223ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs,
2224 struct ospf_neighbor *inbr,
2225 struct ospf_lsa *lsa)
2226{
2227 struct route_node *rn;
2228 struct ospf_neighbor *onbr;
2229 struct ospf_lsa *ls_req;
2230
2231 for (rn = route_top (nbrs); rn; rn = route_next (rn))
2232 {
2233 if ((onbr = rn->info) == NULL)
2234 continue;
2235 if (onbr == inbr)
2236 continue;
2237 if ((ls_req = ospf_ls_request_lookup (onbr, lsa)) == NULL)
2238 continue;
2239
2240 if (IS_DEBUG_OSPF_EVENT)
2241 zlog_info ("LSA[%s]: Exclude this entry from LSReq to send.", dump_lsa_key (lsa));
2242
2243 ospf_ls_request_delete (onbr, ls_req);
2244/* ospf_check_nbr_loading (onbr);*//* XXX */
2245 }
2246
2247 return;
2248}
2249
2250void
paul87d6f872004-09-24 08:01:38 +00002251ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr,
2252 struct list *lsas)
paul718e3742002-12-13 20:15:29 +00002253{
2254 struct ospf *top;
paul87d6f872004-09-24 08:01:38 +00002255 struct listnode *node, *next;
paul718e3742002-12-13 20:15:29 +00002256 struct ospf_lsa *lsa;
2257 u_char before;
2258
2259 if ((top = oi_to_top (nbr->oi)) == NULL)
2260 goto out;
2261
2262 before = IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque);
2263
2264 for (node = listhead (lsas); node; node = next)
2265 {
2266 next = node->next;
2267
2268 if ((lsa = getdata (node)) == NULL)
2269 continue;
2270
2271 listnode_delete (lsas, lsa);
2272
2273 /*
2274 * Since these LSA entries are not yet installed into corresponding
2275 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2276 */
2277 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2278 switch (lsa->data->type)
2279 {
2280 case OSPF_OPAQUE_LINK_LSA:
2281 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
2282 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2283 break;
2284 case OSPF_OPAQUE_AREA_LSA:
2285 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
2286 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2287 break;
2288 case OSPF_OPAQUE_AS_LSA:
2289 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
paul68980082003-03-25 05:07:42 +00002290 ospf_flood_through_as (top, NULL/*inbr*/, lsa);
paul718e3742002-12-13 20:15:29 +00002291 break;
2292 default:
2293 zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
2294 goto out;
2295 }
2296
2297 ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */
2298 }
2299
2300 if (before == 0 && IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2301 {
2302 if (IS_DEBUG_OSPF_EVENT)
2303 zlog_info ("Block Opaque-LSA origination: OFF -> ON");
2304 }
2305
2306out:
2307 return;
2308}
2309
2310void
paul87d6f872004-09-24 08:01:38 +00002311ospf_opaque_ls_ack_received (struct ospf_neighbor *nbr, struct list *acks)
paul718e3742002-12-13 20:15:29 +00002312{
2313 struct ospf *top;
paul87d6f872004-09-24 08:01:38 +00002314 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002315 struct ospf_lsa *lsa;
2316 char type9_lsa_rcv = 0, type10_lsa_rcv = 0, type11_lsa_rcv = 0;
2317
2318 if ((top = oi_to_top (nbr->oi)) == NULL)
2319 goto out;
2320
paul87d6f872004-09-24 08:01:38 +00002321 LIST_LOOP (acks, lsa, node)
paul718e3742002-12-13 20:15:29 +00002322 {
paul718e3742002-12-13 20:15:29 +00002323 switch (lsa->data->type)
2324 {
2325 case OSPF_OPAQUE_LINK_LSA:
2326 type9_lsa_rcv = 1;
2327 /* Callback function... */
2328 break;
2329 case OSPF_OPAQUE_AREA_LSA:
2330 type10_lsa_rcv = 1;
2331 /* Callback function... */
2332 break;
2333 case OSPF_OPAQUE_AS_LSA:
2334 type11_lsa_rcv = 1;
2335 /* Callback function... */
2336 break;
2337 default:
2338 zlog_warn ("ospf_opaque_ls_ack_received: Unexpected LSA-type(%u)", lsa->data->type);
2339 goto out;
2340 }
2341 }
2342
2343 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2344 {
2345 int delay;
2346 struct ospf_interface *oi;
2347
2348 if (type9_lsa_rcv
2349 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT))
2350 ospf_opaque_type9_lsa_rxmt_nbr_check (nbr->oi);
2351
2352 if (type10_lsa_rcv
2353 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT))
2354 ospf_opaque_type10_lsa_rxmt_nbr_check (nbr->oi->area);
2355
2356 if (type11_lsa_rcv
2357 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT))
2358 ospf_opaque_type11_lsa_rxmt_nbr_check (top);
2359
2360 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2361 goto out; /* Blocking still in progress. */
2362
2363 if (IS_DEBUG_OSPF_EVENT)
2364 zlog_info ("Block Opaque-LSA origination: ON -> OFF");
2365
2366 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
2367 goto out; /* Opaque capability condition must have changed. */
2368
2369 /* Ok, let's start origination of Opaque-LSAs. */
2370 delay = OSPF_MIN_LS_INTERVAL;
paul718e3742002-12-13 20:15:29 +00002371
paul87d6f872004-09-24 08:01:38 +00002372 LIST_LOOP (top->oiflist, oi, node)
2373 {
paul718e3742002-12-13 20:15:29 +00002374 if (! ospf_if_is_enable (oi)
paul87d6f872004-09-24 08:01:38 +00002375 || ospf_nbr_count_opaque_capable (oi) == 0)
paul718e3742002-12-13 20:15:29 +00002376 continue;
2377
2378 ospf_opaque_lsa_originate_schedule (oi, &delay);
2379 }
2380 }
2381
2382out:
2383 return;
2384}
2385
2386static void
2387ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi)
2388{
2389 unsigned long n;
2390
2391 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_LINK_LSA);
2392 if (n == 0)
2393 {
2394 if (IS_DEBUG_OSPF_EVENT)
2395 zlog_info ("Self-originated type-9 Opaque-LSAs: OI(%s): Flush completed", IF_NAME (oi));
2396
paul68980082003-03-25 05:07:42 +00002397 UNSET_FLAG (oi->area->ospf->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
paul718e3742002-12-13 20:15:29 +00002398 }
2399 return;
2400}
2401
2402static void
2403ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area)
2404{
paul87d6f872004-09-24 08:01:38 +00002405 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002406 struct ospf_interface *oi;
2407 unsigned long n = 0;
2408
2409 for (node = listhead (area->oiflist); node; nextnode (node))
2410 {
2411 if ((oi = getdata (node)) == NULL)
2412 continue;
2413
2414 if (area->area_id.s_addr != OSPF_AREA_BACKBONE
2415 && oi->type == OSPF_IFTYPE_VIRTUALLINK)
2416 continue;
2417
2418 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AREA_LSA);
2419 if (n > 0)
2420 break;
2421 }
2422
2423 if (n == 0)
2424 {
2425 if (IS_DEBUG_OSPF_EVENT)
2426 zlog_info ("Self-originated type-10 Opaque-LSAs: AREA(%s): Flush completed", inet_ntoa (area->area_id));
2427
paul68980082003-03-25 05:07:42 +00002428 UNSET_FLAG (area->ospf->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
paul718e3742002-12-13 20:15:29 +00002429 }
2430
2431 return;
2432}
2433
2434static void
2435ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top)
2436{
paul87d6f872004-09-24 08:01:38 +00002437 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002438 struct ospf_interface *oi;
2439 unsigned long n = 0;
2440
2441 for (node = listhead (top->oiflist); node; nextnode (node))
2442 {
2443 if ((oi = getdata (node)) == NULL)
2444 continue;
2445
2446 switch (oi->type)
2447 {
2448 case OSPF_IFTYPE_VIRTUALLINK:
2449 continue;
2450 default:
2451 break;
2452 }
2453
2454 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AS_LSA);
2455 if (n > 0)
2456 goto out;
2457 }
2458
2459 if (n == 0)
2460 {
2461 if (IS_DEBUG_OSPF_EVENT)
2462 zlog_info ("Self-originated type-11 Opaque-LSAs: Flush completed");
2463
2464 UNSET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
2465 }
2466
2467out:
2468 return;
2469}
2470
2471static unsigned long
2472ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type)
2473{
2474 struct route_node *rn;
2475 struct ospf_neighbor *nbr;
2476 struct ospf *top;
2477 unsigned long n = 0;
2478
2479 for (rn = route_top (nbrs); rn; rn = route_next (rn))
2480 {
2481 if ((nbr = rn->info) == NULL)
2482 continue;
2483 if ((top = oi_to_top (nbr->oi)) == NULL)
2484 continue;
2485 if (IPV4_ADDR_SAME (&nbr->router_id, &top->router_id))
2486 continue;
2487 n += ospf_ls_retransmit_count_self (nbr, lsa_type);
2488 }
2489
2490 return n;
2491}
2492
2493/*------------------------------------------------------------------------*
2494 * Followings are util functions; probably be used by Opaque-LSAs only...
2495 *------------------------------------------------------------------------*/
2496
2497void
2498htonf (float *src, float *dst)
2499{
2500 u_int32_t lu1, lu2;
2501
2502 memcpy (&lu1, src, sizeof (u_int32_t));
2503 lu2 = htonl (lu1);
2504 memcpy (dst, &lu2, sizeof (u_int32_t));
2505 return;
2506}
2507
2508void
2509ntohf (float *src, float *dst)
2510{
2511 u_int32_t lu1, lu2;
2512
2513 memcpy (&lu1, src, sizeof (u_int32_t));
2514 lu2 = ntohl (lu1);
2515 memcpy (dst, &lu2, sizeof (u_int32_t));
2516 return;
2517}
2518
2519struct ospf *
2520oi_to_top (struct ospf_interface *oi)
2521{
2522 struct ospf *top = NULL;
2523 struct ospf_area *area;
2524
paul68980082003-03-25 05:07:42 +00002525 if (oi == NULL || (area = oi->area) == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00002526 zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");
2527
2528 return top;
2529}
2530
2531#endif /* HAVE_OPAQUE_LSA */