blob: 73e9639ca169829238d44c7cb3798ce9eac3d78d [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
paul09e4efd2003-01-18 00:12:02 +0000256static list ospf_opaque_wildcard_funclist; /* Handle LSA-9/10/11 altogether. */
paul718e3742002-12-13 20:15:29 +0000257static list ospf_opaque_type9_funclist;
258static list ospf_opaque_type10_funclist;
259static list ospf_opaque_type11_funclist;
260
261static void
262ospf_opaque_del_functab (void *val)
263{
264 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, val);
265 return;
266}
267
268static void
269ospf_opaque_funclist_init (void)
270{
271 list funclist;
272
paul09e4efd2003-01-18 00:12:02 +0000273 funclist = ospf_opaque_wildcard_funclist = list_new ();
274 funclist->del = ospf_opaque_del_functab;
275
paul718e3742002-12-13 20:15:29 +0000276 funclist = ospf_opaque_type9_funclist = list_new ();
277 funclist->del = ospf_opaque_del_functab;
278
279 funclist = ospf_opaque_type10_funclist = list_new ();
280 funclist->del = ospf_opaque_del_functab;
281
282 funclist = ospf_opaque_type11_funclist = list_new ();
283 funclist->del = ospf_opaque_del_functab;
284 return;
285}
286
287static void
288ospf_opaque_funclist_term (void)
289{
290 list funclist;
291
paul09e4efd2003-01-18 00:12:02 +0000292 funclist = ospf_opaque_wildcard_funclist;
293 list_delete (funclist);
294
paul718e3742002-12-13 20:15:29 +0000295 funclist = ospf_opaque_type9_funclist;
296 list_delete (funclist);
297
298 funclist = ospf_opaque_type10_funclist;
299 list_delete (funclist);
300
301 funclist = ospf_opaque_type11_funclist;
302 list_delete (funclist);
303 return;
304}
305
306static list
307ospf_get_opaque_funclist (u_char lsa_type)
308{
309 list funclist = NULL;
310
311 switch (lsa_type)
312 {
paul09e4efd2003-01-18 00:12:02 +0000313 case OPAQUE_TYPE_WILDCARD:
314 /* XXX
315 * This is an ugly trick to handle type-9/10/11 LSA altogether.
316 * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor
317 * an officially assigned opaque-type.
318 * Though it is possible that the value might be officially used
319 * in the future, we use it internally as a special label, for now.
320 */
321 funclist = ospf_opaque_wildcard_funclist;
322 break;
paul718e3742002-12-13 20:15:29 +0000323 case OSPF_OPAQUE_LINK_LSA:
324 funclist = ospf_opaque_type9_funclist;
325 break;
326 case OSPF_OPAQUE_AREA_LSA:
327 funclist = ospf_opaque_type10_funclist;
328 break;
329 case OSPF_OPAQUE_AS_LSA:
330 funclist = ospf_opaque_type11_funclist;
331 break;
332 default:
333 zlog_warn ("ospf_get_opaque_funclist: Unexpected LSA-type(%u)", lsa_type);
334 break;
335 }
336 return funclist;
337}
338
339int
340ospf_register_opaque_functab (
341 u_char lsa_type,
342 u_char opaque_type,
343 int (* new_if_hook)(struct interface *ifp),
344 int (* del_if_hook)(struct interface *ifp),
345 void (* ism_change_hook)(struct ospf_interface *oi, int old_status),
346 void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status),
347 void (* config_write_router)(struct vty *vty),
348 void (* config_write_if )(struct vty *vty, struct interface *ifp),
349 void (* config_write_debug )(struct vty *vty),
350 void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa),
351 int (* lsa_originator)(void *arg),
352 void (* lsa_refresher )(struct ospf_lsa *lsa),
353 int (* new_lsa_hook)(struct ospf_lsa *lsa),
354 int (* del_lsa_hook)(struct ospf_lsa *lsa))
355{
356 list funclist;
357 struct ospf_opaque_functab *new;
358 int rc = -1;
359
360 if ((funclist = ospf_get_opaque_funclist (lsa_type)) == NULL)
361 {
362 zlog_warn ("ospf_register_opaque_functab: Cannot get funclist for Type-%u LSAs?", lsa_type);
363 goto out;
364 }
365 else
366 {
367 listnode node;
368 struct ospf_opaque_functab *functab;
369
370 for (node = listhead (funclist); node; nextnode (node))
371 if ((functab = getdata (node)) != NULL)
372 if (functab->opaque_type == opaque_type)
373 {
374 zlog_warn ("ospf_register_opaque_functab: Duplicated entry?: lsa_type(%u), opaque_type(%u)", lsa_type, opaque_type);
375 goto out;
376 }
377 }
378
379 if ((new = XCALLOC (MTYPE_OSPF_OPAQUE_FUNCTAB,
380 sizeof (struct ospf_opaque_functab))) == NULL)
381 {
382 zlog_warn ("ospf_register_opaque_functab: XMALLOC: %s", strerror (errno));
383 goto out;
384 }
385
386 new->opaque_type = opaque_type;
387 new->oipt = NULL;
388 new->new_if_hook = new_if_hook;
389 new->del_if_hook = del_if_hook;
390 new->ism_change_hook = ism_change_hook;
391 new->nsm_change_hook = nsm_change_hook;
392 new->config_write_router = config_write_router;
393 new->config_write_if = config_write_if;
394 new->config_write_debug = config_write_debug;
395 new->show_opaque_info = show_opaque_info;
396 new->lsa_originator = lsa_originator;
397 new->lsa_refresher = lsa_refresher;
398 new->new_lsa_hook = new_lsa_hook;
399 new->del_lsa_hook = del_lsa_hook;
400
401 listnode_add (funclist, new);
402 rc = 0;
403
404out:
405 return rc;
406}
407
408void
409ospf_delete_opaque_functab (u_char lsa_type, u_char opaque_type)
410{
411 list funclist;
412 listnode node;
413 struct ospf_opaque_functab *functab;
414
415 if ((funclist = ospf_get_opaque_funclist (lsa_type)) != NULL)
416 for (node = listhead (funclist); node; nextnode (node))
417 {
418 if ((functab = getdata (node)) != NULL
419 && functab->opaque_type == opaque_type)
420 {
421 /* Cleanup internal control information, if it still remains. */
422 if (functab->oipt != NULL)
423 free_opaque_info_per_type (functab->oipt);
424
425 /* Dequeue listnode entry from the list. */
426 listnode_delete (funclist, functab);
427
428 /* Avoid misjudgement in the next lookup. */
429 if (listcount (funclist) == 0)
430 funclist->head = funclist->tail = NULL;
431
432 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, functab);
433 goto out;
434 }
435 }
436out:
437 return;
438}
439
440static struct ospf_opaque_functab *
441ospf_opaque_functab_lookup (struct ospf_lsa *lsa)
442{
443 list funclist;
444 listnode node;
445 struct ospf_opaque_functab *functab;
446 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
447
448 if ((funclist = ospf_get_opaque_funclist (lsa->data->type)) != NULL)
449 for (node = listhead (funclist); node; nextnode (node))
450 if ((functab = getdata (node)) != NULL)
451 if (functab->opaque_type == key)
452 return functab;
453
454 return NULL;
455}
456
457/*------------------------------------------------------------------------*
458 * Followings are management functions for self-originated LSA entries.
459 *------------------------------------------------------------------------*/
460
461/*
462 * Opaque-LSA control information per opaque-type.
463 * Single Opaque-Type may have multiple instances; each of them will be
464 * identified by their opaque-id.
465 */
466struct opaque_info_per_type
467{
paul09e4efd2003-01-18 00:12:02 +0000468 u_char lsa_type;
paul718e3742002-12-13 20:15:29 +0000469 u_char opaque_type;
470
471 enum { PROC_NORMAL, PROC_SUSPEND } status;
472
473 /*
474 * Thread for (re-)origination scheduling for this opaque-type.
475 *
476 * Initial origination of Opaque-LSAs is controlled by generic
477 * Opaque-LSA handling module so that same opaque-type entries are
478 * called all at once when certain conditions are met.
479 * However, there might be cases that some Opaque-LSA clients need
480 * to (re-)originate their own Opaque-LSAs out-of-sync with others.
481 * This thread is prepared for that specific purpose.
482 */
483 struct thread *t_opaque_lsa_self;
484
485 /*
paul09e4efd2003-01-18 00:12:02 +0000486 * Backpointer to an "owner" which is LSA-type dependent.
paul718e3742002-12-13 20:15:29 +0000487 * type-9: struct ospf_interface
488 * type-10: struct ospf_area
489 * type-11: struct ospf
490 */
491 void *owner;
492
493 /* Collection of callback functions for this opaque-type. */
494 struct ospf_opaque_functab *functab;
495
496 /* List of Opaque-LSA control informations per opaque-id. */
497 list id_list;
498};
499
500/* Opaque-LSA control information per opaque-id. */
501struct opaque_info_per_id
502{
503 u_int32_t opaque_id;
504
505 /* Thread for refresh/flush scheduling for this opaque-type/id. */
506 struct thread *t_opaque_lsa_self;
507
508 /* Backpointer to Opaque-LSA control information per opaque-type. */
509 struct opaque_info_per_type *opqctl_type;
510
511 /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
512 struct ospf_lsa *lsa;
513};
514
515static struct opaque_info_per_type *register_opaque_info_per_type (struct ospf_opaque_functab *functab, struct ospf_lsa *new);
516static struct opaque_info_per_type *lookup_opaque_info_by_type (struct ospf_lsa *lsa);
517static struct opaque_info_per_id *register_opaque_info_per_id (struct opaque_info_per_type *oipt, struct ospf_lsa *new);
518static struct opaque_info_per_id *lookup_opaque_info_by_id (struct opaque_info_per_type *oipt, struct ospf_lsa *lsa);
519static struct opaque_info_per_id *register_opaque_lsa (struct ospf_lsa *new);
520
521
522static struct opaque_info_per_type *
523register_opaque_info_per_type (struct ospf_opaque_functab *functab,
524 struct ospf_lsa *new)
525{
526 struct ospf *top;
527 struct opaque_info_per_type *oipt;
528
529 if ((oipt = XCALLOC (MTYPE_OPAQUE_INFO_PER_TYPE,
530 sizeof (struct opaque_info_per_type))) == NULL)
531 {
532 zlog_warn ("register_opaque_info_per_type: XMALLOC: %s", strerror (errno));
533 goto out;
534 }
535
536 switch (new->data->type)
537 {
538 case OSPF_OPAQUE_LINK_LSA:
539 oipt->owner = new->oi;
540 listnode_add (new->oi->opaque_lsa_self, oipt);
541 break;
542 case OSPF_OPAQUE_AREA_LSA:
543 oipt->owner = new->area;
544 listnode_add (new->area->opaque_lsa_self, oipt);
545 break;
546 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +0000547 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000548 if (new->area != NULL && (top = new->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +0000549 {
550 free_opaque_info_per_type ((void *) oipt);
551 oipt = NULL;
552 goto out; /* This case may not exist. */
553 }
554 oipt->owner = top;
555 listnode_add (top->opaque_lsa_self, oipt);
556 break;
557 default:
paul09e4efd2003-01-18 00:12:02 +0000558 zlog_warn ("register_opaque_info_per_type: Unexpected LSA-type(%u)", new->data->type);
paul718e3742002-12-13 20:15:29 +0000559 free_opaque_info_per_type ((void *) oipt);
560 oipt = NULL;
561 goto out; /* This case may not exist. */
562 }
563
paul09e4efd2003-01-18 00:12:02 +0000564 oipt->lsa_type = new->data->type;
paul718e3742002-12-13 20:15:29 +0000565 oipt->opaque_type = GET_OPAQUE_TYPE (ntohl (new->data->id.s_addr));
566 oipt->status = PROC_NORMAL;
567 oipt->t_opaque_lsa_self = NULL;
568 oipt->functab = functab;
569 functab->oipt = oipt;
570 oipt->id_list = list_new ();
571 oipt->id_list->del = free_opaque_info_per_id;
572
573out:
574 return oipt;
575}
576
577static void
578free_opaque_info_per_type (void *val)
579{
580 struct opaque_info_per_type *oipt = (struct opaque_info_per_type *) val;
581 struct opaque_info_per_id *oipi;
582 struct ospf_lsa *lsa;
583 listnode node;
584
585 /* Control information per opaque-id may still exist. */
586 for (node = listhead (oipt->id_list); node; nextnode (node))
587 {
588 if ((oipi = getdata (node)) == NULL)
589 continue;
590 if ((lsa = oipi->lsa) == NULL)
591 continue;
592 if (IS_LSA_MAXAGE (lsa))
593 continue;
594 ospf_opaque_lsa_flush_schedule (lsa);
595 }
596
paul09e4efd2003-01-18 00:12:02 +0000597 /* Remove "oipt" from its owner's self-originated LSA list. */
598 switch (oipt->lsa_type)
599 {
600 case OSPF_OPAQUE_LINK_LSA:
601 {
602 struct ospf_interface *oi = (struct ospf_interface *)(oipt->owner);
603 listnode_delete (oi->opaque_lsa_self, oipt);
604 break;
605 }
606 case OSPF_OPAQUE_AREA_LSA:
607 {
608 struct ospf_area *area = (struct ospf_area *)(oipt->owner);
609 listnode_delete (area->opaque_lsa_self, oipt);
610 break;
611 }
612 case OSPF_OPAQUE_AS_LSA:
613 {
614 struct ospf *top = (struct ospf *)(oipt->owner);
615 listnode_delete (top->opaque_lsa_self, oipt);
616 break;
617 }
618 default:
619 zlog_warn ("free_opaque_info_per_type: Unexpected LSA-type(%u)", oipt->lsa_type);
620 break; /* This case may not exist. */
621 }
622
paul718e3742002-12-13 20:15:29 +0000623 OSPF_TIMER_OFF (oipt->t_opaque_lsa_self);
624 list_delete (oipt->id_list);
625 XFREE (MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
626 return;
627}
628
629static struct opaque_info_per_type *
630lookup_opaque_info_by_type (struct ospf_lsa *lsa)
631{
632 struct ospf *top;
633 struct ospf_area *area;
634 struct ospf_interface *oi;
635 list listtop = NULL;
636 listnode node;
637 struct opaque_info_per_type *oipt = NULL;
638 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
639
640 switch (lsa->data->type)
641 {
642 case OSPF_OPAQUE_LINK_LSA:
643 if ((oi = lsa->oi) != NULL)
644 listtop = oi->opaque_lsa_self;
645 else
646 zlog_warn ("Type-9 Opaque-LSA: Reference to OI is missing?");
647 break;
648 case OSPF_OPAQUE_AREA_LSA:
649 if ((area = lsa->area) != NULL)
650 listtop = area->opaque_lsa_self;
651 else
652 zlog_warn ("Type-10 Opaque-LSA: Reference to AREA is missing?");
653 break;
654 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +0000655 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000656 if ((area = lsa->area) != NULL && (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +0000657 {
658 zlog_warn ("Type-11 Opaque-LSA: Reference to OSPF is missing?");
659 break; /* Unlikely to happen. */
660 }
661 listtop = top->opaque_lsa_self;
662 break;
663 default:
664 zlog_warn ("lookup_opaque_info_by_type: Unexpected LSA-type(%u)", lsa->data->type);
665 break;
666 }
667
668 if (listtop != NULL)
669 for (node = listhead (listtop); node; nextnode (node))
670 if ((oipt = getdata (node)) != NULL)
671 if (oipt->opaque_type == key)
672 return oipt;
673
674 return NULL;
675}
676
677static struct opaque_info_per_id *
678register_opaque_info_per_id (struct opaque_info_per_type *oipt,
679 struct ospf_lsa *new)
680{
681 struct opaque_info_per_id *oipi;
682
683 if ((oipi = XCALLOC (MTYPE_OPAQUE_INFO_PER_ID,
684 sizeof (struct opaque_info_per_id))) == NULL)
685 {
686 zlog_warn ("register_opaque_info_per_id: XMALLOC: %s", strerror (errno));
687 goto out;
688 }
689 oipi->opaque_id = GET_OPAQUE_ID (ntohl (new->data->id.s_addr));
690 oipi->t_opaque_lsa_self = NULL;
691 oipi->opqctl_type = oipt;
692 oipi->lsa = ospf_lsa_lock (new);
693
694 listnode_add (oipt->id_list, oipi);
695
696out:
697 return oipi;
698}
699
700static void
701free_opaque_info_per_id (void *val)
702{
703 struct opaque_info_per_id *oipi = (struct opaque_info_per_id *) val;
704
705 OSPF_TIMER_OFF (oipi->t_opaque_lsa_self);
706 if (oipi->lsa != NULL)
707 ospf_lsa_unlock (oipi->lsa);
708 XFREE (MTYPE_OPAQUE_INFO_PER_ID, oipi);
709 return;
710}
711
712static struct opaque_info_per_id *
713lookup_opaque_info_by_id (struct opaque_info_per_type *oipt,
714 struct ospf_lsa *lsa)
715{
716 listnode node;
717 struct opaque_info_per_id *oipi;
718 u_int32_t key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
719
720 for (node = listhead (oipt->id_list); node; nextnode (node))
721 if ((oipi = getdata (node)) != NULL)
722 if (oipi->opaque_id == key)
723 return oipi;
724
725 return NULL;
726}
727
728static struct opaque_info_per_id *
729register_opaque_lsa (struct ospf_lsa *new)
730{
731 struct ospf_opaque_functab *functab;
732 struct opaque_info_per_type *oipt;
733 struct opaque_info_per_id *oipi = NULL;
734
735 if ((functab = ospf_opaque_functab_lookup (new)) == NULL)
736 goto out;
737
738 if ((oipt = lookup_opaque_info_by_type (new)) == NULL
739 && (oipt = register_opaque_info_per_type (functab, new)) == NULL)
740 goto out;
741
742 if ((oipi = register_opaque_info_per_id (oipt, new)) == NULL)
743 goto out;
744
745out:
746 return oipi;
747}
748
749/*------------------------------------------------------------------------*
750 * Followings are (vty) configuration functions for Opaque-LSAs handling.
751 *------------------------------------------------------------------------*/
752
753DEFUN (capability_opaque,
754 capability_opaque_cmd,
755 "capability opaque",
756 "Enable specific OSPF feature\n"
757 "Opaque LSA\n")
758{
759 struct ospf *ospf = (struct ospf *) vty->index;
760
761 /* Turn on the "master switch" of opaque-lsa capability. */
762 if (!CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
763 {
764 if (IS_DEBUG_OSPF_EVENT)
765 zlog_info ("Opaque capability: OFF -> ON");
766
767 SET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
768 ospf_renegotiate_optional_capabilities (ospf);
769 }
770 return CMD_SUCCESS;
771}
772
773ALIAS (capability_opaque,
774 ospf_opaque_capable_cmd,
775 "ospf opaque-lsa",
776 "OSPF specific commands\n"
777 "Enable the Opaque-LSA capability (rfc2370)\n")
778
779DEFUN (no_capability_opaque,
780 no_capability_opaque_cmd,
781 "no capability opaque",
782 NO_STR
783 "Enable specific OSPF feature\n"
784 "Opaque LSA\n")
785{
786 struct ospf *ospf = (struct ospf *) vty->index;
787
788 /* Turn off the "master switch" of opaque-lsa capability. */
789 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
790 {
791 if (IS_DEBUG_OSPF_EVENT)
792 zlog_info ("Opaque capability: ON -> OFF");
793
794 UNSET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
795 ospf_renegotiate_optional_capabilities (ospf);
796 }
797 return CMD_SUCCESS;
798}
799
800ALIAS (no_capability_opaque,
801 no_ospf_opaque_capable_cmd,
802 "no ospf opaque-lsa",
803 NO_STR
804 "OSPF specific commands\n"
805 "Disable the Opaque-LSA capability (rfc2370)\n")
806
807static void
808ospf_opaque_register_vty (void)
809{
810 install_element (OSPF_NODE, &capability_opaque_cmd);
811 install_element (OSPF_NODE, &no_capability_opaque_cmd);
812 install_element (OSPF_NODE, &ospf_opaque_capable_cmd);
813 install_element (OSPF_NODE, &no_ospf_opaque_capable_cmd);
814 return;
815}
816
817/*------------------------------------------------------------------------*
818 * Followings are collection of user-registered function callers.
819 *------------------------------------------------------------------------*/
820
821static int
822opaque_lsa_new_if_callback (list funclist, struct interface *ifp)
823{
824 listnode node;
825 struct ospf_opaque_functab *functab;
826 int rc = -1;
827
828 for (node = listhead (funclist); node; nextnode (node))
829 if ((functab = getdata (node)) != NULL)
830 if (functab->new_if_hook != NULL)
831 if ((* functab->new_if_hook)(ifp) != 0)
832 goto out;
833 rc = 0;
834out:
835 return rc;
836}
837
838static int
839opaque_lsa_del_if_callback (list funclist, struct interface *ifp)
840{
841 listnode node;
842 struct ospf_opaque_functab *functab;
843 int rc = -1;
844
845 for (node = listhead (funclist); node; nextnode (node))
846 if ((functab = getdata (node)) != NULL)
847 if (functab->del_if_hook != NULL)
848 if ((* functab->del_if_hook)(ifp) != 0)
849 goto out;
850 rc = 0;
851out:
852 return rc;
853}
854
855static void
856opaque_lsa_ism_change_callback (list funclist,
857 struct ospf_interface *oi, int old_status)
858{
859 listnode node;
860 struct ospf_opaque_functab *functab;
861
862 for (node = listhead (funclist); node; nextnode (node))
863 if ((functab = getdata (node)) != NULL)
864 if (functab->ism_change_hook != NULL)
865 (* functab->ism_change_hook)(oi, old_status);
866 return;
867}
868
869static void
870opaque_lsa_nsm_change_callback (list funclist,
871 struct ospf_neighbor *nbr, int old_status)
872{
873 listnode node;
874 struct ospf_opaque_functab *functab;
875
876 for (node = listhead (funclist); node; nextnode (node))
877 if ((functab = getdata (node)) != NULL)
878 if (functab->nsm_change_hook != NULL)
879 (* functab->nsm_change_hook)(nbr, old_status);
880 return;
881}
882
883static void
884opaque_lsa_config_write_router_callback (list funclist, struct vty *vty)
885{
886 listnode node;
887 struct ospf_opaque_functab *functab;
888
889 for (node = listhead (funclist); node; nextnode (node))
890 if ((functab = getdata (node)) != NULL)
891 if (functab->config_write_router != NULL)
892 (* functab->config_write_router)(vty);
893 return;
894}
895
896static void
897opaque_lsa_config_write_if_callback (list funclist,
898 struct vty *vty, struct interface *ifp)
899{
900 listnode node;
901 struct ospf_opaque_functab *functab;
902
903 for (node = listhead (funclist); node; nextnode (node))
904 if ((functab = getdata (node)) != NULL)
905 if (functab->config_write_if != NULL)
906 (* functab->config_write_if)(vty, ifp);
907 return;
908}
909
910static void
911opaque_lsa_config_write_debug_callback (list funclist, struct vty *vty)
912{
913 listnode node;
914 struct ospf_opaque_functab *functab;
915
916 for (node = listhead (funclist); node; nextnode (node))
917 if ((functab = getdata (node)) != NULL)
918 if (functab->config_write_debug != NULL)
919 (* functab->config_write_debug)(vty);
920 return;
921}
922
923static int
924opaque_lsa_originate_callback (list funclist, void *lsa_type_dependent)
925{
926 listnode node;
927 struct ospf_opaque_functab *functab;
928 int rc = -1;
929
930 for (node = listhead (funclist); node; nextnode (node))
931 if ((functab = getdata (node)) != NULL)
932 if (functab->lsa_originator != NULL)
933 if ((* functab->lsa_originator)(lsa_type_dependent) != 0)
934 goto out;
935 rc = 0;
936out:
937 return rc;
938}
939
940static int
941new_lsa_callback (list funclist, struct ospf_lsa *lsa)
942{
943 listnode node;
944 struct ospf_opaque_functab *functab;
945 int rc = -1;
946
947 /* This function handles ALL types of LSAs, not only opaque ones. */
948 for (node = listhead (funclist); node; nextnode (node))
949 if ((functab = getdata (node)) != NULL)
950 if (functab->new_lsa_hook != NULL)
951 if ((* functab->new_lsa_hook)(lsa) != 0)
952 goto out;
953 rc = 0;
954out:
955 return rc;
956}
957
958static int
959del_lsa_callback (list funclist, struct ospf_lsa *lsa)
960{
961 listnode node;
962 struct ospf_opaque_functab *functab;
963 int rc = -1;
964
965 /* This function handles ALL types of LSAs, not only opaque ones. */
966 for (node = listhead (funclist); node; nextnode (node))
967 if ((functab = getdata (node)) != NULL)
968 if (functab->del_lsa_hook != NULL)
969 if ((* functab->del_lsa_hook)(lsa) != 0)
970 goto out;
971 rc = 0;
972out:
973 return rc;
974}
975
976/*------------------------------------------------------------------------*
977 * Followings are glue functions to call Opaque-LSA specific processing.
978 *------------------------------------------------------------------------*/
979
980int
981ospf_opaque_new_if (struct interface *ifp)
982{
983 list funclist;
984 int rc = -1;
985
paul09e4efd2003-01-18 00:12:02 +0000986 funclist = ospf_opaque_wildcard_funclist;
987 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
988 goto out;
989
paul718e3742002-12-13 20:15:29 +0000990 funclist = ospf_opaque_type9_funclist;
991 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
992 goto out;
993
994 funclist = ospf_opaque_type10_funclist;
995 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
996 goto out;
997
998 funclist = ospf_opaque_type11_funclist;
999 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
1000 goto out;
1001
1002 rc = 0;
1003out:
1004 return rc;
1005}
1006
1007int
1008ospf_opaque_del_if (struct interface *ifp)
1009{
1010 list funclist;
1011 int rc = -1;
1012
paul09e4efd2003-01-18 00:12:02 +00001013 funclist = ospf_opaque_wildcard_funclist;
1014 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1015 goto out;
1016
paul718e3742002-12-13 20:15:29 +00001017 funclist = ospf_opaque_type9_funclist;
1018 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1019 goto out;
1020
1021 funclist = ospf_opaque_type10_funclist;
1022 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1023 goto out;
1024
1025 funclist = ospf_opaque_type11_funclist;
1026 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1027 goto out;
1028
1029 rc = 0;
1030out:
1031 return rc;
1032}
1033
1034void
1035ospf_opaque_ism_change (struct ospf_interface *oi, int old_status)
1036{
1037 list funclist;
1038
paul09e4efd2003-01-18 00:12:02 +00001039 funclist = ospf_opaque_wildcard_funclist;
1040 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1041
paul718e3742002-12-13 20:15:29 +00001042 funclist = ospf_opaque_type9_funclist;
1043 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1044
1045 funclist = ospf_opaque_type10_funclist;
1046 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1047
1048 funclist = ospf_opaque_type11_funclist;
1049 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1050
1051 return;
1052}
1053
1054void
1055ospf_opaque_nsm_change (struct ospf_neighbor *nbr, int old_state)
1056{
1057 struct ospf *top;
1058 list funclist;
1059
1060 if ((top = oi_to_top (nbr->oi)) == NULL)
1061 goto out;
1062
1063 if (old_state != NSM_Full && nbr->state == NSM_Full)
1064 {
1065 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
1066 {
1067 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1068 {
1069 if (IS_DEBUG_OSPF_EVENT)
1070 zlog_info ("Opaque-LSA: Now get operational!");
1071
1072 SET_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT);
1073 }
1074
1075 ospf_opaque_lsa_originate_schedule (nbr->oi, NULL);
1076 }
1077 }
1078 else
1079 if (old_state == NSM_Full && nbr->state != NSM_Full)
1080 {
1081#ifdef NOTYET
1082 /*
1083 * If no more opaque-capable full-state neighbor remains in the
1084 * flooding scope which corresponds to Opaque-LSA type, periodic
1085 * LS flooding should be stopped.
1086 */
1087#endif /* NOTYET */
1088 ;
1089 }
1090
paul09e4efd2003-01-18 00:12:02 +00001091 funclist = ospf_opaque_wildcard_funclist;
1092 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1093
paul718e3742002-12-13 20:15:29 +00001094 funclist = ospf_opaque_type9_funclist;
1095 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1096
1097 funclist = ospf_opaque_type10_funclist;
1098 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1099
1100 funclist = ospf_opaque_type11_funclist;
1101 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1102
1103out:
1104 return;
1105}
1106
1107void
1108ospf_opaque_config_write_router (struct vty *vty, struct ospf *ospf)
1109{
1110 list funclist;
1111
1112 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
1113 vty_out (vty, " capability opaque%s", VTY_NEWLINE);
1114
paul09e4efd2003-01-18 00:12:02 +00001115 funclist = ospf_opaque_wildcard_funclist;
1116 opaque_lsa_config_write_router_callback (funclist, vty);
1117
paul718e3742002-12-13 20:15:29 +00001118 funclist = ospf_opaque_type9_funclist;
1119 opaque_lsa_config_write_router_callback (funclist, vty);
1120
1121 funclist = ospf_opaque_type10_funclist;
1122 opaque_lsa_config_write_router_callback (funclist, vty);
1123
1124 funclist = ospf_opaque_type11_funclist;
1125 opaque_lsa_config_write_router_callback (funclist, vty);
1126
1127 return;
1128}
1129
1130void
1131ospf_opaque_config_write_if (struct vty *vty, struct interface *ifp)
1132{
1133 list funclist;
1134
paul09e4efd2003-01-18 00:12:02 +00001135 funclist = ospf_opaque_wildcard_funclist;
1136 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1137
paul718e3742002-12-13 20:15:29 +00001138 funclist = ospf_opaque_type9_funclist;
1139 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1140
1141 funclist = ospf_opaque_type10_funclist;
1142 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1143
1144 funclist = ospf_opaque_type11_funclist;
1145 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1146
1147 return;
1148}
1149
1150void
1151ospf_opaque_config_write_debug (struct vty *vty)
1152{
1153 list funclist;
1154
paul09e4efd2003-01-18 00:12:02 +00001155 funclist = ospf_opaque_wildcard_funclist;
1156 opaque_lsa_config_write_debug_callback (funclist, vty);
1157
paul718e3742002-12-13 20:15:29 +00001158 funclist = ospf_opaque_type9_funclist;
1159 opaque_lsa_config_write_debug_callback (funclist, vty);
1160
1161 funclist = ospf_opaque_type10_funclist;
1162 opaque_lsa_config_write_debug_callback (funclist, vty);
1163
1164 funclist = ospf_opaque_type11_funclist;
1165 opaque_lsa_config_write_debug_callback (funclist, vty);
1166
1167 return;
1168}
1169
1170void
1171show_opaque_info_detail (struct vty *vty, struct ospf_lsa *lsa)
1172{
1173 struct lsa_header *lsah = (struct lsa_header *) lsa->data;
1174 u_int32_t lsid = ntohl (lsah->id.s_addr);
1175 u_char opaque_type = GET_OPAQUE_TYPE (lsid);
1176 u_int32_t opaque_id = GET_OPAQUE_ID (lsid);
1177 struct ospf_opaque_functab *functab;
1178
1179 /* Switch output functionality by vty address. */
1180 if (vty != NULL)
1181 {
paul020709f2003-04-04 02:44:16 +00001182 vty_out (vty, " Opaque-Type %u (%s)%s", opaque_type,
1183 ospf_opaque_type_name (opaque_type), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001184 vty_out (vty, " Opaque-ID 0x%x%s", opaque_id, VTY_NEWLINE);
1185
1186 vty_out (vty, " Opaque-Info: %u octets of data%s%s",
1187 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1188 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)",
1189 VTY_NEWLINE);
1190 }
1191 else
1192 {
paul020709f2003-04-04 02:44:16 +00001193 zlog_info (" Opaque-Type %u (%s)", opaque_type,
1194 ospf_opaque_type_name (opaque_type));
paul718e3742002-12-13 20:15:29 +00001195 zlog_info (" Opaque-ID 0x%x", opaque_id);
1196
1197 zlog_info (" Opaque-Info: %u octets of data%s",
1198 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1199 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)");
1200 }
1201
1202 /* Call individual output functions. */
1203 if ((functab = ospf_opaque_functab_lookup (lsa)) != NULL)
1204 if (functab->show_opaque_info != NULL)
1205 (* functab->show_opaque_info)(vty, lsa);
1206
1207 return;
1208}
1209
1210void
1211ospf_opaque_lsa_dump (struct stream *s, u_int16_t length)
1212{
1213 struct ospf_lsa lsa;
1214
1215 lsa.data = (struct lsa_header *) STREAM_PNT (s);
1216 show_opaque_info_detail (NULL, &lsa);
1217 return;
1218}
1219
1220static int
1221ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa)
1222{
1223 list funclist;
1224 int rc = -1;
1225
1226 /*
1227 * Some Opaque-LSA user may want to monitor every LSA installation
1228 * into the LSDB, regardless with target LSA type.
1229 */
paul09e4efd2003-01-18 00:12:02 +00001230 funclist = ospf_opaque_wildcard_funclist;
1231 if (new_lsa_callback (funclist, lsa) != 0)
1232 goto out;
1233
paul718e3742002-12-13 20:15:29 +00001234 funclist = ospf_opaque_type9_funclist;
1235 if (new_lsa_callback (funclist, lsa) != 0)
1236 goto out;
1237
1238 funclist = ospf_opaque_type10_funclist;
1239 if (new_lsa_callback (funclist, lsa) != 0)
1240 goto out;
1241
1242 funclist = ospf_opaque_type11_funclist;
1243 if (new_lsa_callback (funclist, lsa) != 0)
1244 goto out;
1245
1246 rc = 0;
1247out:
1248 return rc;
1249}
1250
1251static int
1252ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa)
1253{
1254 list funclist;
1255 int rc = -1;
1256
1257 /*
1258 * Some Opaque-LSA user may want to monitor every LSA deletion
1259 * from the LSDB, regardless with target LSA type.
1260 */
paul09e4efd2003-01-18 00:12:02 +00001261 funclist = ospf_opaque_wildcard_funclist;
1262 if (del_lsa_callback (funclist, lsa) != 0)
1263 goto out;
1264
paul718e3742002-12-13 20:15:29 +00001265 funclist = ospf_opaque_type9_funclist;
1266 if (del_lsa_callback (funclist, lsa) != 0)
1267 goto out;
1268
1269 funclist = ospf_opaque_type10_funclist;
1270 if (del_lsa_callback (funclist, lsa) != 0)
1271 goto out;
1272
1273 funclist = ospf_opaque_type11_funclist;
1274 if (del_lsa_callback (funclist, lsa) != 0)
1275 goto out;
1276
1277 rc = 0;
1278out:
1279 return rc;
1280}
1281
1282/*------------------------------------------------------------------------*
1283 * Followings are Opaque-LSA origination/refresh management functions.
1284 *------------------------------------------------------------------------*/
1285
1286static int ospf_opaque_type9_lsa_originate (struct thread *t);
1287static int ospf_opaque_type10_lsa_originate (struct thread *t);
1288static int ospf_opaque_type11_lsa_originate (struct thread *t);
1289static void ospf_opaque_lsa_reoriginate_resume (list listtop, void *arg);
1290
1291void
1292ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0)
1293{
1294 struct ospf *top;
1295 struct ospf_area *area;
1296 listnode node;
1297 struct opaque_info_per_type *oipt;
1298 int delay = 0;
1299
1300 if ((top = oi_to_top (oi)) == NULL || (area = oi->area) == NULL)
1301 {
1302 zlog_warn ("ospf_opaque_lsa_originate_schedule: Invalid argument?");
1303 goto out;
1304 }
1305
1306 /* It may not a right time to schedule origination now. */
1307 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1308 {
1309 if (IS_DEBUG_OSPF_EVENT)
1310 zlog_info ("ospf_opaque_lsa_originate_schedule: Not operational.");
1311 goto out; /* This is not an error. */
1312 }
1313 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
1314 {
1315 if (IS_DEBUG_OSPF_EVENT)
1316 zlog_info ("ospf_opaque_lsa_originate_schedule: Under blockade.");
1317 goto out; /* This is not an error, too. */
1318 }
1319
1320 if (delay0 != NULL)
1321 delay = *delay0;
1322
1323 /*
1324 * There might be some entries that have been waiting for triggering
1325 * of per opaque-type re-origination get resumed.
1326 */
1327 ospf_opaque_lsa_reoriginate_resume ( oi->opaque_lsa_self, (void *) oi);
1328 ospf_opaque_lsa_reoriginate_resume (area->opaque_lsa_self, (void *) area);
1329 ospf_opaque_lsa_reoriginate_resume ( top->opaque_lsa_self, (void *) top);
1330
1331 /*
1332 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1333 */
1334 if (! list_isempty (ospf_opaque_type9_funclist)
1335 && list_isempty (oi->opaque_lsa_self)
1336 && oi->t_opaque_lsa_self == NULL)
1337 {
1338 if (IS_DEBUG_OSPF_EVENT)
1339 zlog_info ("Schedule Type-9 Opaque-LSA origination in %d sec later.", delay);
1340 oi->t_opaque_lsa_self =
1341 thread_add_timer (master, ospf_opaque_type9_lsa_originate, oi, delay);
1342 delay += OSPF_MIN_LS_INTERVAL;
1343 }
1344
1345 if (! list_isempty (ospf_opaque_type10_funclist)
1346 && list_isempty (area->opaque_lsa_self)
1347 && area->t_opaque_lsa_self == NULL)
1348 {
1349 /*
1350 * One AREA may contain multiple OIs, but above 2nd and 3rd
1351 * conditions prevent from scheduling the originate function
1352 * again and again.
1353 */
1354 if (IS_DEBUG_OSPF_EVENT)
1355 zlog_info ("Schedule Type-10 Opaque-LSA origination in %d sec later.", delay);
1356 area->t_opaque_lsa_self =
1357 thread_add_timer (master, ospf_opaque_type10_lsa_originate,
1358 area, delay);
1359 delay += OSPF_MIN_LS_INTERVAL;
1360 }
1361
1362 if (! list_isempty (ospf_opaque_type11_funclist)
1363 && list_isempty (top->opaque_lsa_self)
1364 && top->t_opaque_lsa_self == NULL)
1365 {
1366 /*
1367 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1368 * conditions prevent from scheduling the originate function
1369 * again and again.
1370 */
1371 if (IS_DEBUG_OSPF_EVENT)
1372 zlog_info ("Schedule Type-11 Opaque-LSA origination in %d sec later.", delay);
1373 top->t_opaque_lsa_self =
1374 thread_add_timer (master, ospf_opaque_type11_lsa_originate,
1375 top, delay);
1376 delay += OSPF_MIN_LS_INTERVAL;
1377 }
1378
1379 /*
1380 * Following section treats a special situation that this node's
1381 * opaque capability has changed as "ON -> OFF -> ON".
1382 */
1383 if (! list_isempty (ospf_opaque_type9_funclist)
1384 && ! list_isempty (oi->opaque_lsa_self))
1385 {
1386 for (node = listhead (oi->opaque_lsa_self); node; nextnode (node))
1387 {
hasso0d85b992004-03-18 19:18:33 +00001388 /*
1389 * removed the test for
1390 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1391 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1392 * not being empty.
1393 */
paul718e3742002-12-13 20:15:29 +00001394 if ((oipt = getdata (node)) == NULL /* Something wrong? */
1395 || oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
hasso0d85b992004-03-18 19:18:33 +00001396 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001397 continue;
1398
1399 ospf_opaque_lsa_reoriginate_schedule ((void *) oi,
1400 OSPF_OPAQUE_LINK_LSA, oipt->opaque_type);
1401 }
1402 }
1403
1404 if (! list_isempty (ospf_opaque_type10_funclist)
1405 && ! list_isempty (area->opaque_lsa_self))
1406 {
1407 for (node = listhead (area->opaque_lsa_self); node; nextnode (node))
1408 {
hasso0d85b992004-03-18 19:18:33 +00001409 /*
1410 * removed the test for
1411 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1412 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1413 * not being empty.
1414 */
paul718e3742002-12-13 20:15:29 +00001415 if ((oipt = getdata (node)) == NULL /* Something wrong? */
1416 || oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
hasso0d85b992004-03-18 19:18:33 +00001417 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001418 continue;
1419
1420 ospf_opaque_lsa_reoriginate_schedule ((void *) area,
1421 OSPF_OPAQUE_AREA_LSA, oipt->opaque_type);
1422 }
1423 }
1424
1425 if (! list_isempty (ospf_opaque_type11_funclist)
1426 && ! list_isempty (top->opaque_lsa_self))
1427 {
1428 for (node = listhead (top->opaque_lsa_self); node; nextnode (node))
1429 {
hasso0d85b992004-03-18 19:18:33 +00001430 /*
1431 * removed the test for
1432 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1433 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1434 * not being empty.
1435 */
paul718e3742002-12-13 20:15:29 +00001436 if ((oipt = getdata (node)) == NULL /* Something wrong? */
1437 || oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
hasso0d85b992004-03-18 19:18:33 +00001438 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001439 continue;
1440
1441 ospf_opaque_lsa_reoriginate_schedule ((void *) top,
1442 OSPF_OPAQUE_AS_LSA, oipt->opaque_type);
1443 }
1444 }
1445
1446 if (delay0 != NULL)
1447 *delay0 = delay;
1448
1449out:
1450 return;
1451}
1452
1453static int
1454ospf_opaque_type9_lsa_originate (struct thread *t)
1455{
1456 struct ospf_interface *oi;
1457 int rc;
1458
1459 oi = THREAD_ARG (t);
1460 oi->t_opaque_lsa_self = NULL;
1461
1462 if (IS_DEBUG_OSPF_EVENT)
1463 zlog_info ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
1464 IF_NAME (oi));
1465
1466 rc = opaque_lsa_originate_callback (ospf_opaque_type9_funclist, oi);
1467
1468 return rc;
1469}
1470
1471static int
1472ospf_opaque_type10_lsa_originate (struct thread *t)
1473{
1474 struct ospf_area *area;
1475 int rc;
1476
1477 area = THREAD_ARG (t);
1478 area->t_opaque_lsa_self = NULL;
1479
1480 if (IS_DEBUG_OSPF_EVENT)
1481 zlog_info ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
1482 inet_ntoa (area->area_id));
1483
1484 rc = opaque_lsa_originate_callback (ospf_opaque_type10_funclist, area);
1485
1486 return rc;
1487}
1488
1489static int
1490ospf_opaque_type11_lsa_originate (struct thread *t)
1491{
1492 struct ospf *top;
1493 int rc;
1494
1495 top = THREAD_ARG (t);
1496 top->t_opaque_lsa_self = NULL;
1497
1498 if (IS_DEBUG_OSPF_EVENT)
1499 zlog_info ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
1500
1501 rc = opaque_lsa_originate_callback (ospf_opaque_type11_funclist, top);
1502
1503 return rc;
1504}
1505
1506static void
1507ospf_opaque_lsa_reoriginate_resume (list listtop, void *arg)
1508{
1509 listnode node;
1510 struct opaque_info_per_type *oipt;
1511 struct ospf_opaque_functab *functab;
1512
1513 if (listtop == NULL)
1514 goto out;
1515
1516 /*
1517 * Pickup oipt entries those which in SUSPEND status, and give
1518 * them a chance to start re-origination now.
1519 */
1520 for (node = listhead (listtop); node; nextnode (node))
1521 {
1522 if ((oipt = getdata (node)) == NULL
1523 || oipt->status != PROC_SUSPEND)
1524 continue;
1525
1526 oipt->status = PROC_NORMAL;
1527
1528 if ((functab = oipt->functab) == NULL
1529 || functab->lsa_originator == NULL)
1530 continue;
1531
1532 if ((* functab->lsa_originator)(arg) != 0)
1533 {
1534 zlog_warn ("ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", oipt->opaque_type);
1535 continue;
1536 }
1537 }
1538
1539out:
1540 return;
1541}
1542
1543struct ospf_lsa *
1544ospf_opaque_lsa_install (struct ospf_lsa *lsa, int rt_recalc)
1545{
1546 struct ospf_lsa *new = NULL;
1547 struct opaque_info_per_type *oipt;
1548 struct opaque_info_per_id *oipi;
1549 struct ospf *top;
1550
1551 /* Don't take "rt_recalc" into consideration for now. *//* XXX */
1552
1553 if (! IS_LSA_SELF (lsa))
1554 {
1555 new = lsa; /* Don't touch this LSA. */
1556 goto out;
1557 }
1558
1559 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
1560 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)));
1561
1562 /* Replace the existing lsa with the new one. */
1563 if ((oipt = lookup_opaque_info_by_type (lsa)) != NULL
1564 && (oipi = lookup_opaque_info_by_id (oipt, lsa)) != NULL)
1565 {
1566 ospf_lsa_unlock (oipi->lsa);
1567 oipi->lsa = ospf_lsa_lock (lsa);
1568 }
1569 /* Register the new lsa entry and get its control info. */
1570 else
1571 if ((oipi = register_opaque_lsa (lsa)) == NULL)
1572 {
1573 zlog_warn ("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1574 goto out;
1575 }
1576
1577 /*
1578 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1579 * for periodic refresh of self-originated Opaque-LSAs.
1580 */
1581 switch (lsa->data->type)
1582 {
1583 case OSPF_OPAQUE_LINK_LSA:
paul09e4efd2003-01-18 00:12:02 +00001584 if ((top = oi_to_top (lsa->oi)) == NULL)
1585 {
1586 /* Above conditions must have passed. */
1587 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1588 goto out;
1589 }
1590 break;
paul718e3742002-12-13 20:15:29 +00001591 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00001592 if (lsa->area == NULL || (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001593 {
1594 /* Above conditions must have passed. */
1595 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1596 goto out;
1597 }
1598 break;
1599 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +00001600 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001601 if (lsa->area != NULL && (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001602 {
1603 /* Above conditions must have passed. */
1604 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1605 goto out;
1606 }
1607 break;
1608 default:
1609 zlog_warn ("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", lsa->data->type);
1610 goto out;
1611 }
1612
1613 ospf_refresher_register_lsa (top, lsa);
1614 new = lsa;
1615
1616out:
1617 return new;
1618}
1619
1620void
1621ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
1622{
paul020709f2003-04-04 02:44:16 +00001623 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001624 struct ospf_opaque_functab *functab;
1625
paul020709f2003-04-04 02:44:16 +00001626 ospf = ospf_lookup ();
1627
paul718e3742002-12-13 20:15:29 +00001628 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL
1629 || functab->lsa_refresher == NULL)
1630 {
1631 /*
1632 * Though this LSA seems to have originated on this node, the
1633 * handling module for this "lsa-type and opaque-type" was
1634 * already deleted sometime ago.
1635 * Anyway, this node still has a responsibility to flush this
1636 * LSA from the routing domain.
1637 */
1638 if (IS_DEBUG_OSPF_EVENT)
1639 zlog_info ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id));
1640
1641 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
paul68980082003-03-25 05:07:42 +00001642 ospf_lsa_maxage (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00001643 }
1644 else
1645 (* functab->lsa_refresher)(lsa);
1646
1647 return;
1648}
1649
1650/*------------------------------------------------------------------------*
1651 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1652 * triggered by external interventions (vty session, signaling, etc).
1653 *------------------------------------------------------------------------*/
1654
1655#define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
1656 if (!(T)) \
1657 (T) = thread_add_timer (master, (F), (L), (V))
1658
1659static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type);
1660static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t);
1661static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t);
1662static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t);
1663static int ospf_opaque_lsa_refresh_timer (struct thread *t);
1664
1665void
1666ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
1667 u_char lsa_type, u_char opaque_type)
1668{
1669 struct ospf *top;
1670 struct ospf_area dummy, *area = NULL;
1671 struct ospf_interface *oi = NULL;
1672
1673 struct ospf_lsa *lsa;
1674 struct opaque_info_per_type *oipt;
1675 int (* func)(struct thread *t) = NULL;
1676 int delay;
1677
1678 switch (lsa_type)
1679 {
1680 case OSPF_OPAQUE_LINK_LSA:
1681 if ((oi = (struct ospf_interface *) lsa_type_dependent) == NULL)
1682 {
1683 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Type-9 Opaque-LSA: Invalid parameter?");
1684 goto out;
1685 }
1686 if ((top = oi_to_top (oi)) == NULL)
1687 {
1688 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?", IF_NAME (oi));
1689 goto out;
1690 }
1691 if (! list_isempty (ospf_opaque_type9_funclist)
1692 && list_isempty (oi->opaque_lsa_self)
1693 && oi->t_opaque_lsa_self != NULL)
1694 {
1695 zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u): Common origination for OI(%s) has already started", opaque_type, IF_NAME (oi));
1696 goto out;
1697 }
1698 func = ospf_opaque_type9_lsa_reoriginate_timer;
1699 break;
1700 case OSPF_OPAQUE_AREA_LSA:
1701 if ((area = (struct ospf_area *) lsa_type_dependent) == NULL)
1702 {
1703 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Type-10 Opaque-LSA: Invalid parameter?");
1704 goto out;
1705 }
paul68980082003-03-25 05:07:42 +00001706 if ((top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001707 {
1708 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: AREA(%s) -> TOP?", inet_ntoa (area->area_id));
1709 goto out;
1710 }
1711 if (! list_isempty (ospf_opaque_type10_funclist)
1712 && list_isempty (area->opaque_lsa_self)
1713 && area->t_opaque_lsa_self != NULL)
1714 {
1715 zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u): Common origination for AREA(%s) has already started", opaque_type, inet_ntoa (area->area_id));
1716 goto out;
1717 }
1718 func = ospf_opaque_type10_lsa_reoriginate_timer;
1719 break;
1720 case OSPF_OPAQUE_AS_LSA:
1721 if ((top = (struct ospf *) lsa_type_dependent) == NULL)
1722 {
1723 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Type-11 Opaque-LSA: Invalid parameter?");
1724 goto out;
1725 }
1726 if (! list_isempty (ospf_opaque_type11_funclist)
1727 && list_isempty (top->opaque_lsa_self)
1728 && top->t_opaque_lsa_self != NULL)
1729 {
1730 zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u): Common origination has already started", opaque_type);
1731 goto out;
1732 }
1733
1734 /* Fake "area" to pass "ospf" to a lookup function later. */
paul68980082003-03-25 05:07:42 +00001735 dummy.ospf = top;
paul718e3742002-12-13 20:15:29 +00001736 area = &dummy;
1737
1738 func = ospf_opaque_type11_lsa_reoriginate_timer;
1739 break;
1740 default:
1741 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Unexpected LSA-type(%u)", lsa_type);
1742 goto out;
1743 }
1744
1745 /* It may not a right time to schedule reorigination now. */
1746 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1747 {
1748 if (IS_DEBUG_OSPF_EVENT)
1749 zlog_info ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
1750 goto out; /* This is not an error. */
1751 }
1752 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
1753 {
1754 if (IS_DEBUG_OSPF_EVENT)
1755 zlog_info ("ospf_opaque_lsa_reoriginate_schedule: Under blockade.");
1756 goto out; /* This is not an error, too. */
1757 }
1758
1759 /* Generate a dummy lsa to be passed for a lookup function. */
1760 lsa = pseudo_lsa (oi, area, lsa_type, opaque_type);
1761
1762 if ((oipt = lookup_opaque_info_by_type (lsa)) == NULL)
1763 {
1764 struct ospf_opaque_functab *functab;
1765 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL)
1766 {
1767 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: No associated function?: lsa_type(%u), opaque_type(%u)", lsa_type, opaque_type);
1768 goto out;
1769 }
1770 if ((oipt = register_opaque_info_per_type (functab, lsa)) == NULL)
1771 {
1772 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Cannot get a control info?: lsa_type(%u), opaque_type(%u)", lsa_type, opaque_type);
1773 goto out;
1774 }
1775 }
1776
1777 if (oipt->t_opaque_lsa_self != NULL)
1778 {
1779 if (IS_DEBUG_OSPF_EVENT)
1780 zlog_info ("Type-%u Opaque-LSA has already scheduled to RE-ORIGINATE: [opaque-type=%u]", lsa_type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
1781 goto out;
1782 }
1783
1784 /*
1785 * Different from initial origination time, in which various conditions
1786 * (opaque capability, neighbor status etc) are assured by caller of
1787 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1788 * it is highly possible that these conditions might not be satisfied
1789 * at the time of re-origination function is to be called.
1790 */
1791 delay = OSPF_MIN_LS_INTERVAL; /* XXX */
1792
1793 if (IS_DEBUG_OSPF_EVENT)
1794 zlog_info ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d sec later: [opaque-type=%u]", lsa_type, delay, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
1795
1796 OSPF_OPAQUE_TIMER_ON (oipt->t_opaque_lsa_self, func, oipt, delay);
1797
1798out:
1799 return;
1800}
1801
1802static struct ospf_lsa *
1803pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area,
1804 u_char lsa_type, u_char opaque_type)
1805{
1806 static struct ospf_lsa lsa = { 0 };
1807 static struct lsa_header lsah = { 0 };
1808 u_int32_t tmp;
1809
1810 lsa.oi = oi;
1811 lsa.area = area;
1812 lsa.data = &lsah;
1813
1814 lsah.type = lsa_type;
1815 tmp = SET_OPAQUE_LSID (opaque_type, 0); /* Opaque-ID is unused here. */
1816 lsah.id.s_addr = htonl (tmp);
1817
1818 return &lsa;
1819}
1820
1821static int
1822ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t)
1823{
1824 struct opaque_info_per_type *oipt;
1825 struct ospf_opaque_functab *functab;
1826 struct ospf *top;
1827 struct ospf_interface *oi;
1828 int rc = -1;
1829
1830 oipt = THREAD_ARG (t);
1831 oipt->t_opaque_lsa_self = NULL;
1832
1833 if ((functab = oipt->functab) == NULL
1834 || functab->lsa_originator == NULL)
1835 {
1836 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1837 goto out;
1838 }
1839
1840 oi = (struct ospf_interface *) oipt->owner;
1841 if ((top = oi_to_top (oi)) == NULL)
1842 {
1843 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1844 goto out;
1845 }
1846
1847 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)
1848 || ! ospf_if_is_enable (oi)
paul68980082003-03-25 05:07:42 +00001849 || ospf_nbr_count_opaque_capable (oi) == 0)
paul718e3742002-12-13 20:15:29 +00001850 {
1851 if (IS_DEBUG_OSPF_EVENT)
1852 zlog_info ("Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
1853
1854 oipt->status = PROC_SUSPEND;
1855 rc = 0;
1856 goto out;
1857 }
1858
1859 if (IS_DEBUG_OSPF_EVENT)
1860 zlog_info ("Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)", oipt->opaque_type, IF_NAME (oi));
1861
1862 rc = (* functab->lsa_originator)(oi);
1863out:
1864 return rc;
1865}
1866
1867static int
1868ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t)
1869{
1870 struct opaque_info_per_type *oipt;
1871 struct ospf_opaque_functab *functab;
1872 listnode node;
1873 struct ospf *top;
1874 struct ospf_area *area;
1875 struct ospf_interface *oi;
1876 int n, rc = -1;
1877
1878 oipt = THREAD_ARG (t);
1879 oipt->t_opaque_lsa_self = NULL;
1880
1881 if ((functab = oipt->functab) == NULL
1882 || functab->lsa_originator == NULL)
1883 {
1884 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1885 goto out;
1886 }
1887
1888 area = (struct ospf_area *) oipt->owner;
paul68980082003-03-25 05:07:42 +00001889 if (area == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001890 {
1891 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1892 goto out;
1893 }
1894
1895 /* There must be at least one "opaque-capable, full-state" neighbor. */
1896 n = 0;
1897 for (node = listhead (area->oiflist); node; nextnode (node))
1898 {
1899 if ((oi = getdata (node)) == NULL)
1900 continue;
paul68980082003-03-25 05:07:42 +00001901 if ((n = ospf_nbr_count_opaque_capable (oi)) > 0)
paul718e3742002-12-13 20:15:29 +00001902 break;
1903 }
1904
1905 if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1906 {
1907 if (IS_DEBUG_OSPF_EVENT)
1908 zlog_info ("Suspend re-origination of Type-10 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
1909
1910 oipt->status = PROC_SUSPEND;
1911 rc = 0;
1912 goto out;
1913 }
1914
1915 if (IS_DEBUG_OSPF_EVENT)
1916 zlog_info ("Timer[Type10-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for Area %s", oipt->opaque_type, inet_ntoa (area->area_id));
1917
1918 rc = (* functab->lsa_originator)(area);
1919out:
1920 return rc;
1921}
1922
1923static int
1924ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t)
1925{
1926 struct opaque_info_per_type *oipt;
1927 struct ospf_opaque_functab *functab;
1928 struct ospf *top;
1929 int rc = -1;
1930
1931 oipt = THREAD_ARG (t);
1932 oipt->t_opaque_lsa_self = NULL;
1933
1934 if ((functab = oipt->functab) == NULL
1935 || functab->lsa_originator == NULL)
1936 {
1937 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: No associated function?");
1938 goto out;
1939 }
1940
1941 if ((top = (struct ospf *) oipt->owner) == NULL)
1942 {
1943 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1944 goto out;
1945 }
1946
1947 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1948 {
1949 if (IS_DEBUG_OSPF_EVENT)
1950 zlog_info ("Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
1951
1952 oipt->status = PROC_SUSPEND;
1953 rc = 0;
1954 goto out;
1955 }
1956
1957 if (IS_DEBUG_OSPF_EVENT)
1958 zlog_info ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type);
1959
1960 rc = (* functab->lsa_originator)(top);
1961out:
1962 return rc;
1963}
1964
1965extern int ospf_lsa_refresh_delay (struct ospf_lsa *); /* ospf_lsa.c */
1966
1967void
1968ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
1969{
paul020709f2003-04-04 02:44:16 +00001970 struct ospf *ospf = ospf;
paul718e3742002-12-13 20:15:29 +00001971 struct opaque_info_per_type *oipt;
1972 struct opaque_info_per_id *oipi;
1973 struct ospf_lsa *lsa;
1974 int delay;
1975
paul020709f2003-04-04 02:44:16 +00001976 ospf = ospf_lookup ();
1977
paul718e3742002-12-13 20:15:29 +00001978 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
1979 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
1980 {
1981 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
1982 goto out;
1983 }
1984
1985 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
1986 if ((lsa = oipi->lsa) == NULL)
1987 {
1988 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
1989 goto out;
1990 }
1991
1992 if (oipi->t_opaque_lsa_self != NULL)
1993 {
1994 if (IS_DEBUG_OSPF_EVENT)
1995 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)));
1996 goto out;
1997 }
1998
1999 /* Delete this lsa from neighbor retransmit-list. */
2000 switch (lsa->data->type)
2001 {
2002 case OSPF_OPAQUE_LINK_LSA:
2003 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002004 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002005 break;
2006 case OSPF_OPAQUE_AS_LSA:
paul68980082003-03-25 05:07:42 +00002007 ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002008 break;
2009 default:
2010 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2011 goto out;
2012 }
2013
2014 delay = ospf_lsa_refresh_delay (lsa);
2015
2016 if (IS_DEBUG_OSPF_EVENT)
2017 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)));
2018
2019 OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self,
2020 ospf_opaque_lsa_refresh_timer, oipi, delay);
2021out:
2022 return;
2023}
2024
2025static int
2026ospf_opaque_lsa_refresh_timer (struct thread *t)
2027{
2028 struct opaque_info_per_id *oipi;
2029 struct ospf_opaque_functab *functab;
2030 struct ospf_lsa *lsa;
2031
2032 if (IS_DEBUG_OSPF_EVENT)
2033 zlog_info ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
2034
2035 oipi = THREAD_ARG (t);
2036 oipi->t_opaque_lsa_self = NULL;
2037
2038 if ((lsa = oipi->lsa) != NULL)
2039 if ((functab = oipi->opqctl_type->functab) != NULL)
2040 if (functab->lsa_refresher != NULL)
2041 (* functab->lsa_refresher)(lsa);
2042
2043 return 0;
2044}
2045
2046void
2047ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
2048{
paul020709f2003-04-04 02:44:16 +00002049 struct ospf *ospf = ospf;
paul718e3742002-12-13 20:15:29 +00002050 struct opaque_info_per_type *oipt;
2051 struct opaque_info_per_id *oipi;
2052 struct ospf_lsa *lsa;
2053
paul020709f2003-04-04 02:44:16 +00002054 ospf = ospf_lookup ();
2055
paul718e3742002-12-13 20:15:29 +00002056 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
2057 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
2058 {
2059 zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2060 goto out;
2061 }
2062
2063 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2064 if ((lsa = oipi->lsa) == NULL)
2065 {
2066 zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
2067 goto out;
2068 }
2069
2070 /* Delete this lsa from neighbor retransmit-list. */
2071 switch (lsa->data->type)
2072 {
2073 case OSPF_OPAQUE_LINK_LSA:
2074 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002075 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002076 break;
2077 case OSPF_OPAQUE_AS_LSA:
paul68980082003-03-25 05:07:42 +00002078 ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002079 break;
2080 default:
2081 zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2082 goto out;
2083 }
2084
2085 /* Dequeue listnode entry from the list. */
2086 listnode_delete (oipt->id_list, oipi);
2087
2088 /* Avoid misjudgement in the next lookup. */
2089 if (listcount (oipt->id_list) == 0)
2090 oipt->id_list->head = oipt->id_list->tail = NULL;
2091
2092 /* Disassociate internal control information with the given lsa. */
paul718e3742002-12-13 20:15:29 +00002093 free_opaque_info_per_id ((void *) oipi);
2094
2095 /* Force given lsa's age to MaxAge. */
2096 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2097
2098 if (IS_DEBUG_OSPF_EVENT)
2099 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)));
2100
2101 /* This lsa will be flushed and removed eventually. */
paul68980082003-03-25 05:07:42 +00002102 ospf_lsa_maxage (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002103
2104out:
2105 return;
2106}
2107
2108/*------------------------------------------------------------------------*
2109 * Followings are control functions to block origination after restart.
2110 *------------------------------------------------------------------------*/
2111
2112static void ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs, struct ospf_neighbor *inbr, struct ospf_lsa *lsa);
2113static void ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi);
2114static void ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area);
2115static void ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top);
2116static unsigned long ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type);
2117
2118void
2119ospf_opaque_adjust_lsreq (struct ospf_neighbor *nbr, list lsas)
2120{
2121 struct ospf *top;
2122 struct ospf_area *area;
2123 struct ospf_interface *oi;
2124 listnode node1, node2;
2125 struct ospf_lsa *lsa;
2126
2127 if ((top = oi_to_top (nbr->oi)) == NULL)
2128 goto out;
2129
2130 /*
2131 * If an instance of self-originated Opaque-LSA is found in the given
2132 * LSA list, and it is not installed to LSDB yet, exclude it from the
2133 * list "nbr->ls_req". In this way, it is assured that an LSReq message,
2134 * which might be sent in the process of flooding, will not request for
2135 * the LSA to be flushed immediately; otherwise, depending on timing,
2136 * an LSUpd message will carry instances of target LSAs with MaxAge,
2137 * while other LSUpd message might carry old LSA instances (non-MaxAge).
2138 * Obviously, the latter would trigger miserable situations that repeat
2139 * installation and removal of unwanted LSAs indefinitely.
2140 */
2141 for (node1 = listhead (lsas); node1; nextnode (node1))
2142 {
2143 if ((lsa = getdata (node1)) == NULL)
2144 continue;
2145
2146 /* Filter out unwanted LSAs. */
2147 if (! IS_OPAQUE_LSA (lsa->data->type))
2148 continue;
2149 if (! IPV4_ADDR_SAME (&lsa->data->adv_router, &top->router_id))
2150 continue;
2151
2152 /*
2153 * Don't touch an LSA which has MaxAge; two possible cases.
2154 *
2155 * 1) This LSA has originally flushed by myself (received LSUpd
2156 * message's router-id is equal to my router-id), and flooded
2157 * back by an opaque-capable router.
2158 *
2159 * 2) This LSA has expired in an opaque-capable router and thus
2160 * flushed by the router.
2161 */
2162 if (IS_LSA_MAXAGE (lsa))
2163 continue;
2164
2165 /* If the LSA has installed in the LSDB, nothing to do here. */
2166 if (ospf_lsa_lookup_by_header (nbr->oi->area, lsa->data) != NULL)
2167 continue;
2168
2169 /* Ok, here we go. */
2170 switch (lsa->data->type)
2171 {
2172 case OSPF_OPAQUE_LINK_LSA:
2173 oi = nbr->oi;
2174 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2175 break;
2176 case OSPF_OPAQUE_AREA_LSA:
2177 area = nbr->oi->area;
2178 for (node2 = listhead (area->oiflist); node2; nextnode (node2))
2179 {
2180 if ((oi = getdata (node2)) == NULL)
2181 continue;
2182 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2183 }
2184 break;
2185 case OSPF_OPAQUE_AS_LSA:
2186 for (node2 = listhead (top->oiflist); node2; nextnode (node2))
2187 {
2188 if ((oi = getdata (node2)) == NULL)
2189 continue;
2190 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2191 }
2192 break;
2193 default:
2194 break;
2195 }
2196 }
2197
2198out:
2199 return;
2200}
2201
2202static void
2203ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs,
2204 struct ospf_neighbor *inbr,
2205 struct ospf_lsa *lsa)
2206{
2207 struct route_node *rn;
2208 struct ospf_neighbor *onbr;
2209 struct ospf_lsa *ls_req;
2210
2211 for (rn = route_top (nbrs); rn; rn = route_next (rn))
2212 {
2213 if ((onbr = rn->info) == NULL)
2214 continue;
2215 if (onbr == inbr)
2216 continue;
2217 if ((ls_req = ospf_ls_request_lookup (onbr, lsa)) == NULL)
2218 continue;
2219
2220 if (IS_DEBUG_OSPF_EVENT)
2221 zlog_info ("LSA[%s]: Exclude this entry from LSReq to send.", dump_lsa_key (lsa));
2222
2223 ospf_ls_request_delete (onbr, ls_req);
2224/* ospf_check_nbr_loading (onbr);*//* XXX */
2225 }
2226
2227 return;
2228}
2229
2230void
2231ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr, list lsas)
2232{
2233 struct ospf *top;
2234 listnode node, next;
2235 struct ospf_lsa *lsa;
2236 u_char before;
2237
2238 if ((top = oi_to_top (nbr->oi)) == NULL)
2239 goto out;
2240
2241 before = IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque);
2242
2243 for (node = listhead (lsas); node; node = next)
2244 {
2245 next = node->next;
2246
2247 if ((lsa = getdata (node)) == NULL)
2248 continue;
2249
2250 listnode_delete (lsas, lsa);
2251
2252 /*
2253 * Since these LSA entries are not yet installed into corresponding
2254 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2255 */
2256 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2257 switch (lsa->data->type)
2258 {
2259 case OSPF_OPAQUE_LINK_LSA:
2260 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
2261 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2262 break;
2263 case OSPF_OPAQUE_AREA_LSA:
2264 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
2265 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2266 break;
2267 case OSPF_OPAQUE_AS_LSA:
2268 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
paul68980082003-03-25 05:07:42 +00002269 ospf_flood_through_as (top, NULL/*inbr*/, lsa);
paul718e3742002-12-13 20:15:29 +00002270 break;
2271 default:
2272 zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
2273 goto out;
2274 }
2275
2276 ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */
2277 }
2278
2279 if (before == 0 && IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2280 {
2281 if (IS_DEBUG_OSPF_EVENT)
2282 zlog_info ("Block Opaque-LSA origination: OFF -> ON");
2283 }
2284
2285out:
2286 return;
2287}
2288
2289void
2290ospf_opaque_ls_ack_received (struct ospf_neighbor *nbr, list acks)
2291{
2292 struct ospf *top;
2293 listnode node;
2294 struct ospf_lsa *lsa;
2295 char type9_lsa_rcv = 0, type10_lsa_rcv = 0, type11_lsa_rcv = 0;
2296
2297 if ((top = oi_to_top (nbr->oi)) == NULL)
2298 goto out;
2299
2300 for (node = listhead (acks); node; nextnode (node))
2301 {
2302 if ((lsa = getdata (node)) == NULL)
2303 continue;
2304
2305 switch (lsa->data->type)
2306 {
2307 case OSPF_OPAQUE_LINK_LSA:
2308 type9_lsa_rcv = 1;
2309 /* Callback function... */
2310 break;
2311 case OSPF_OPAQUE_AREA_LSA:
2312 type10_lsa_rcv = 1;
2313 /* Callback function... */
2314 break;
2315 case OSPF_OPAQUE_AS_LSA:
2316 type11_lsa_rcv = 1;
2317 /* Callback function... */
2318 break;
2319 default:
2320 zlog_warn ("ospf_opaque_ls_ack_received: Unexpected LSA-type(%u)", lsa->data->type);
2321 goto out;
2322 }
2323 }
2324
2325 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2326 {
2327 int delay;
2328 struct ospf_interface *oi;
2329
2330 if (type9_lsa_rcv
2331 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT))
2332 ospf_opaque_type9_lsa_rxmt_nbr_check (nbr->oi);
2333
2334 if (type10_lsa_rcv
2335 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT))
2336 ospf_opaque_type10_lsa_rxmt_nbr_check (nbr->oi->area);
2337
2338 if (type11_lsa_rcv
2339 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT))
2340 ospf_opaque_type11_lsa_rxmt_nbr_check (top);
2341
2342 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2343 goto out; /* Blocking still in progress. */
2344
2345 if (IS_DEBUG_OSPF_EVENT)
2346 zlog_info ("Block Opaque-LSA origination: ON -> OFF");
2347
2348 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
2349 goto out; /* Opaque capability condition must have changed. */
2350
2351 /* Ok, let's start origination of Opaque-LSAs. */
2352 delay = OSPF_MIN_LS_INTERVAL;
2353 for (node = listhead (top->oiflist); node; nextnode (node))
2354 {
2355 if ((oi = getdata (node)) == NULL)
2356 continue;
2357
2358 if (! ospf_if_is_enable (oi)
paul68980082003-03-25 05:07:42 +00002359 || ospf_nbr_count_opaque_capable (oi) == 0)
paul718e3742002-12-13 20:15:29 +00002360 continue;
2361
2362 ospf_opaque_lsa_originate_schedule (oi, &delay);
2363 }
2364 }
2365
2366out:
2367 return;
2368}
2369
2370static void
2371ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi)
2372{
2373 unsigned long n;
2374
2375 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_LINK_LSA);
2376 if (n == 0)
2377 {
2378 if (IS_DEBUG_OSPF_EVENT)
2379 zlog_info ("Self-originated type-9 Opaque-LSAs: OI(%s): Flush completed", IF_NAME (oi));
2380
paul68980082003-03-25 05:07:42 +00002381 UNSET_FLAG (oi->area->ospf->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
paul718e3742002-12-13 20:15:29 +00002382 }
2383 return;
2384}
2385
2386static void
2387ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area)
2388{
2389 listnode node;
2390 struct ospf_interface *oi;
2391 unsigned long n = 0;
2392
2393 for (node = listhead (area->oiflist); node; nextnode (node))
2394 {
2395 if ((oi = getdata (node)) == NULL)
2396 continue;
2397
2398 if (area->area_id.s_addr != OSPF_AREA_BACKBONE
2399 && oi->type == OSPF_IFTYPE_VIRTUALLINK)
2400 continue;
2401
2402 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AREA_LSA);
2403 if (n > 0)
2404 break;
2405 }
2406
2407 if (n == 0)
2408 {
2409 if (IS_DEBUG_OSPF_EVENT)
2410 zlog_info ("Self-originated type-10 Opaque-LSAs: AREA(%s): Flush completed", inet_ntoa (area->area_id));
2411
paul68980082003-03-25 05:07:42 +00002412 UNSET_FLAG (area->ospf->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
paul718e3742002-12-13 20:15:29 +00002413 }
2414
2415 return;
2416}
2417
2418static void
2419ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top)
2420{
2421 listnode node;
2422 struct ospf_interface *oi;
2423 unsigned long n = 0;
2424
2425 for (node = listhead (top->oiflist); node; nextnode (node))
2426 {
2427 if ((oi = getdata (node)) == NULL)
2428 continue;
2429
2430 switch (oi->type)
2431 {
2432 case OSPF_IFTYPE_VIRTUALLINK:
2433 continue;
2434 default:
2435 break;
2436 }
2437
2438 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AS_LSA);
2439 if (n > 0)
2440 goto out;
2441 }
2442
2443 if (n == 0)
2444 {
2445 if (IS_DEBUG_OSPF_EVENT)
2446 zlog_info ("Self-originated type-11 Opaque-LSAs: Flush completed");
2447
2448 UNSET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
2449 }
2450
2451out:
2452 return;
2453}
2454
2455static unsigned long
2456ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type)
2457{
2458 struct route_node *rn;
2459 struct ospf_neighbor *nbr;
2460 struct ospf *top;
2461 unsigned long n = 0;
2462
2463 for (rn = route_top (nbrs); rn; rn = route_next (rn))
2464 {
2465 if ((nbr = rn->info) == NULL)
2466 continue;
2467 if ((top = oi_to_top (nbr->oi)) == NULL)
2468 continue;
2469 if (IPV4_ADDR_SAME (&nbr->router_id, &top->router_id))
2470 continue;
2471 n += ospf_ls_retransmit_count_self (nbr, lsa_type);
2472 }
2473
2474 return n;
2475}
2476
2477/*------------------------------------------------------------------------*
2478 * Followings are util functions; probably be used by Opaque-LSAs only...
2479 *------------------------------------------------------------------------*/
2480
2481void
2482htonf (float *src, float *dst)
2483{
2484 u_int32_t lu1, lu2;
2485
2486 memcpy (&lu1, src, sizeof (u_int32_t));
2487 lu2 = htonl (lu1);
2488 memcpy (dst, &lu2, sizeof (u_int32_t));
2489 return;
2490}
2491
2492void
2493ntohf (float *src, float *dst)
2494{
2495 u_int32_t lu1, lu2;
2496
2497 memcpy (&lu1, src, sizeof (u_int32_t));
2498 lu2 = ntohl (lu1);
2499 memcpy (dst, &lu2, sizeof (u_int32_t));
2500 return;
2501}
2502
2503struct ospf *
2504oi_to_top (struct ospf_interface *oi)
2505{
2506 struct ospf *top = NULL;
2507 struct ospf_area *area;
2508
paul68980082003-03-25 05:07:42 +00002509 if (oi == NULL || (area = oi->area) == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00002510 zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");
2511
2512 return top;
2513}
2514
2515#endif /* HAVE_OPAQUE_LSA */