blob: b8ba51843a6041fe15777c5433148ed8ef1db75f [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:
547 top = ospf_top;
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:
655 top = ospf_top;
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 {
1182 vty_out (vty, " Opaque-Type %u (%s)%s", opaque_type, ospf_opaque_type_name (opaque_type), VTY_NEWLINE);
1183 vty_out (vty, " Opaque-ID 0x%x%s", opaque_id, VTY_NEWLINE);
1184
1185 vty_out (vty, " Opaque-Info: %u octets of data%s%s",
1186 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1187 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)",
1188 VTY_NEWLINE);
1189 }
1190 else
1191 {
1192 zlog_info (" Opaque-Type %u (%s)", opaque_type, ospf_opaque_type_name (opaque_type));
1193 zlog_info (" Opaque-ID 0x%x", opaque_id);
1194
1195 zlog_info (" Opaque-Info: %u octets of data%s",
1196 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1197 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)");
1198 }
1199
1200 /* Call individual output functions. */
1201 if ((functab = ospf_opaque_functab_lookup (lsa)) != NULL)
1202 if (functab->show_opaque_info != NULL)
1203 (* functab->show_opaque_info)(vty, lsa);
1204
1205 return;
1206}
1207
1208void
1209ospf_opaque_lsa_dump (struct stream *s, u_int16_t length)
1210{
1211 struct ospf_lsa lsa;
1212
1213 lsa.data = (struct lsa_header *) STREAM_PNT (s);
1214 show_opaque_info_detail (NULL, &lsa);
1215 return;
1216}
1217
1218static int
1219ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa)
1220{
1221 list funclist;
1222 int rc = -1;
1223
1224 /*
1225 * Some Opaque-LSA user may want to monitor every LSA installation
1226 * into the LSDB, regardless with target LSA type.
1227 */
paul09e4efd2003-01-18 00:12:02 +00001228 funclist = ospf_opaque_wildcard_funclist;
1229 if (new_lsa_callback (funclist, lsa) != 0)
1230 goto out;
1231
paul718e3742002-12-13 20:15:29 +00001232 funclist = ospf_opaque_type9_funclist;
1233 if (new_lsa_callback (funclist, lsa) != 0)
1234 goto out;
1235
1236 funclist = ospf_opaque_type10_funclist;
1237 if (new_lsa_callback (funclist, lsa) != 0)
1238 goto out;
1239
1240 funclist = ospf_opaque_type11_funclist;
1241 if (new_lsa_callback (funclist, lsa) != 0)
1242 goto out;
1243
1244 rc = 0;
1245out:
1246 return rc;
1247}
1248
1249static int
1250ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa)
1251{
1252 list funclist;
1253 int rc = -1;
1254
1255 /*
1256 * Some Opaque-LSA user may want to monitor every LSA deletion
1257 * from the LSDB, regardless with target LSA type.
1258 */
paul09e4efd2003-01-18 00:12:02 +00001259 funclist = ospf_opaque_wildcard_funclist;
1260 if (del_lsa_callback (funclist, lsa) != 0)
1261 goto out;
1262
paul718e3742002-12-13 20:15:29 +00001263 funclist = ospf_opaque_type9_funclist;
1264 if (del_lsa_callback (funclist, lsa) != 0)
1265 goto out;
1266
1267 funclist = ospf_opaque_type10_funclist;
1268 if (del_lsa_callback (funclist, lsa) != 0)
1269 goto out;
1270
1271 funclist = ospf_opaque_type11_funclist;
1272 if (del_lsa_callback (funclist, lsa) != 0)
1273 goto out;
1274
1275 rc = 0;
1276out:
1277 return rc;
1278}
1279
1280/*------------------------------------------------------------------------*
1281 * Followings are Opaque-LSA origination/refresh management functions.
1282 *------------------------------------------------------------------------*/
1283
1284static int ospf_opaque_type9_lsa_originate (struct thread *t);
1285static int ospf_opaque_type10_lsa_originate (struct thread *t);
1286static int ospf_opaque_type11_lsa_originate (struct thread *t);
1287static void ospf_opaque_lsa_reoriginate_resume (list listtop, void *arg);
1288
1289void
1290ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0)
1291{
1292 struct ospf *top;
1293 struct ospf_area *area;
1294 listnode node;
1295 struct opaque_info_per_type *oipt;
1296 int delay = 0;
1297
1298 if ((top = oi_to_top (oi)) == NULL || (area = oi->area) == NULL)
1299 {
1300 zlog_warn ("ospf_opaque_lsa_originate_schedule: Invalid argument?");
1301 goto out;
1302 }
1303
1304 /* It may not a right time to schedule origination now. */
1305 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1306 {
1307 if (IS_DEBUG_OSPF_EVENT)
1308 zlog_info ("ospf_opaque_lsa_originate_schedule: Not operational.");
1309 goto out; /* This is not an error. */
1310 }
1311 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
1312 {
1313 if (IS_DEBUG_OSPF_EVENT)
1314 zlog_info ("ospf_opaque_lsa_originate_schedule: Under blockade.");
1315 goto out; /* This is not an error, too. */
1316 }
1317
1318 if (delay0 != NULL)
1319 delay = *delay0;
1320
1321 /*
1322 * There might be some entries that have been waiting for triggering
1323 * of per opaque-type re-origination get resumed.
1324 */
1325 ospf_opaque_lsa_reoriginate_resume ( oi->opaque_lsa_self, (void *) oi);
1326 ospf_opaque_lsa_reoriginate_resume (area->opaque_lsa_self, (void *) area);
1327 ospf_opaque_lsa_reoriginate_resume ( top->opaque_lsa_self, (void *) top);
1328
1329 /*
1330 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1331 */
1332 if (! list_isempty (ospf_opaque_type9_funclist)
1333 && list_isempty (oi->opaque_lsa_self)
1334 && oi->t_opaque_lsa_self == NULL)
1335 {
1336 if (IS_DEBUG_OSPF_EVENT)
1337 zlog_info ("Schedule Type-9 Opaque-LSA origination in %d sec later.", delay);
1338 oi->t_opaque_lsa_self =
1339 thread_add_timer (master, ospf_opaque_type9_lsa_originate, oi, delay);
1340 delay += OSPF_MIN_LS_INTERVAL;
1341 }
1342
1343 if (! list_isempty (ospf_opaque_type10_funclist)
1344 && list_isempty (area->opaque_lsa_self)
1345 && area->t_opaque_lsa_self == NULL)
1346 {
1347 /*
1348 * One AREA may contain multiple OIs, but above 2nd and 3rd
1349 * conditions prevent from scheduling the originate function
1350 * again and again.
1351 */
1352 if (IS_DEBUG_OSPF_EVENT)
1353 zlog_info ("Schedule Type-10 Opaque-LSA origination in %d sec later.", delay);
1354 area->t_opaque_lsa_self =
1355 thread_add_timer (master, ospf_opaque_type10_lsa_originate,
1356 area, delay);
1357 delay += OSPF_MIN_LS_INTERVAL;
1358 }
1359
1360 if (! list_isempty (ospf_opaque_type11_funclist)
1361 && list_isempty (top->opaque_lsa_self)
1362 && top->t_opaque_lsa_self == NULL)
1363 {
1364 /*
1365 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1366 * conditions prevent from scheduling the originate function
1367 * again and again.
1368 */
1369 if (IS_DEBUG_OSPF_EVENT)
1370 zlog_info ("Schedule Type-11 Opaque-LSA origination in %d sec later.", delay);
1371 top->t_opaque_lsa_self =
1372 thread_add_timer (master, ospf_opaque_type11_lsa_originate,
1373 top, delay);
1374 delay += OSPF_MIN_LS_INTERVAL;
1375 }
1376
1377 /*
1378 * Following section treats a special situation that this node's
1379 * opaque capability has changed as "ON -> OFF -> ON".
1380 */
1381 if (! list_isempty (ospf_opaque_type9_funclist)
1382 && ! list_isempty (oi->opaque_lsa_self))
1383 {
1384 for (node = listhead (oi->opaque_lsa_self); node; nextnode (node))
1385 {
1386 if ((oipt = getdata (node)) == NULL /* Something wrong? */
1387 || oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1388 || oipt->status == PROC_SUSPEND /* Cannot originate now. */
1389 || ! list_isempty (oipt->id_list)) /* Handler is already active. */
1390 continue;
1391
1392 ospf_opaque_lsa_reoriginate_schedule ((void *) oi,
1393 OSPF_OPAQUE_LINK_LSA, oipt->opaque_type);
1394 }
1395 }
1396
1397 if (! list_isempty (ospf_opaque_type10_funclist)
1398 && ! list_isempty (area->opaque_lsa_self))
1399 {
1400 for (node = listhead (area->opaque_lsa_self); node; nextnode (node))
1401 {
1402 if ((oipt = getdata (node)) == NULL /* Something wrong? */
1403 || oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1404 || oipt->status == PROC_SUSPEND /* Cannot originate now. */
1405 || ! list_isempty (oipt->id_list)) /* Handler is already active. */
1406 continue;
1407
1408 ospf_opaque_lsa_reoriginate_schedule ((void *) area,
1409 OSPF_OPAQUE_AREA_LSA, oipt->opaque_type);
1410 }
1411 }
1412
1413 if (! list_isempty (ospf_opaque_type11_funclist)
1414 && ! list_isempty (top->opaque_lsa_self))
1415 {
1416 for (node = listhead (top->opaque_lsa_self); node; nextnode (node))
1417 {
1418 if ((oipt = getdata (node)) == NULL /* Something wrong? */
1419 || oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1420 || oipt->status == PROC_SUSPEND /* Cannot originate now. */
1421 || ! list_isempty (oipt->id_list)) /* Handler is already active. */
1422 continue;
1423
1424 ospf_opaque_lsa_reoriginate_schedule ((void *) top,
1425 OSPF_OPAQUE_AS_LSA, oipt->opaque_type);
1426 }
1427 }
1428
1429 if (delay0 != NULL)
1430 *delay0 = delay;
1431
1432out:
1433 return;
1434}
1435
1436static int
1437ospf_opaque_type9_lsa_originate (struct thread *t)
1438{
1439 struct ospf_interface *oi;
1440 int rc;
1441
1442 oi = THREAD_ARG (t);
1443 oi->t_opaque_lsa_self = NULL;
1444
1445 if (IS_DEBUG_OSPF_EVENT)
1446 zlog_info ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
1447 IF_NAME (oi));
1448
1449 rc = opaque_lsa_originate_callback (ospf_opaque_type9_funclist, oi);
1450
1451 return rc;
1452}
1453
1454static int
1455ospf_opaque_type10_lsa_originate (struct thread *t)
1456{
1457 struct ospf_area *area;
1458 int rc;
1459
1460 area = THREAD_ARG (t);
1461 area->t_opaque_lsa_self = NULL;
1462
1463 if (IS_DEBUG_OSPF_EVENT)
1464 zlog_info ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
1465 inet_ntoa (area->area_id));
1466
1467 rc = opaque_lsa_originate_callback (ospf_opaque_type10_funclist, area);
1468
1469 return rc;
1470}
1471
1472static int
1473ospf_opaque_type11_lsa_originate (struct thread *t)
1474{
1475 struct ospf *top;
1476 int rc;
1477
1478 top = THREAD_ARG (t);
1479 top->t_opaque_lsa_self = NULL;
1480
1481 if (IS_DEBUG_OSPF_EVENT)
1482 zlog_info ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
1483
1484 rc = opaque_lsa_originate_callback (ospf_opaque_type11_funclist, top);
1485
1486 return rc;
1487}
1488
1489static void
1490ospf_opaque_lsa_reoriginate_resume (list listtop, void *arg)
1491{
1492 listnode node;
1493 struct opaque_info_per_type *oipt;
1494 struct ospf_opaque_functab *functab;
1495
1496 if (listtop == NULL)
1497 goto out;
1498
1499 /*
1500 * Pickup oipt entries those which in SUSPEND status, and give
1501 * them a chance to start re-origination now.
1502 */
1503 for (node = listhead (listtop); node; nextnode (node))
1504 {
1505 if ((oipt = getdata (node)) == NULL
1506 || oipt->status != PROC_SUSPEND)
1507 continue;
1508
1509 oipt->status = PROC_NORMAL;
1510
1511 if ((functab = oipt->functab) == NULL
1512 || functab->lsa_originator == NULL)
1513 continue;
1514
1515 if ((* functab->lsa_originator)(arg) != 0)
1516 {
1517 zlog_warn ("ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", oipt->opaque_type);
1518 continue;
1519 }
1520 }
1521
1522out:
1523 return;
1524}
1525
1526struct ospf_lsa *
1527ospf_opaque_lsa_install (struct ospf_lsa *lsa, int rt_recalc)
1528{
1529 struct ospf_lsa *new = NULL;
1530 struct opaque_info_per_type *oipt;
1531 struct opaque_info_per_id *oipi;
1532 struct ospf *top;
1533
1534 /* Don't take "rt_recalc" into consideration for now. *//* XXX */
1535
1536 if (! IS_LSA_SELF (lsa))
1537 {
1538 new = lsa; /* Don't touch this LSA. */
1539 goto out;
1540 }
1541
1542 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
1543 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)));
1544
1545 /* Replace the existing lsa with the new one. */
1546 if ((oipt = lookup_opaque_info_by_type (lsa)) != NULL
1547 && (oipi = lookup_opaque_info_by_id (oipt, lsa)) != NULL)
1548 {
1549 ospf_lsa_unlock (oipi->lsa);
1550 oipi->lsa = ospf_lsa_lock (lsa);
1551 }
1552 /* Register the new lsa entry and get its control info. */
1553 else
1554 if ((oipi = register_opaque_lsa (lsa)) == NULL)
1555 {
1556 zlog_warn ("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1557 goto out;
1558 }
1559
1560 /*
1561 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1562 * for periodic refresh of self-originated Opaque-LSAs.
1563 */
1564 switch (lsa->data->type)
1565 {
1566 case OSPF_OPAQUE_LINK_LSA:
paul09e4efd2003-01-18 00:12:02 +00001567 if ((top = oi_to_top (lsa->oi)) == NULL)
1568 {
1569 /* Above conditions must have passed. */
1570 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1571 goto out;
1572 }
1573 break;
paul718e3742002-12-13 20:15:29 +00001574 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00001575 if (lsa->area == NULL || (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001576 {
1577 /* Above conditions must have passed. */
1578 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1579 goto out;
1580 }
1581 break;
1582 case OSPF_OPAQUE_AS_LSA:
1583 top = ospf_top;
paul68980082003-03-25 05:07:42 +00001584 if (lsa->area != NULL && (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001585 {
1586 /* Above conditions must have passed. */
1587 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1588 goto out;
1589 }
1590 break;
1591 default:
1592 zlog_warn ("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", lsa->data->type);
1593 goto out;
1594 }
1595
1596 ospf_refresher_register_lsa (top, lsa);
1597 new = lsa;
1598
1599out:
1600 return new;
1601}
1602
1603void
1604ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
1605{
paul68980082003-03-25 05:07:42 +00001606 struct ospf *ospf = ospf_top;
paul718e3742002-12-13 20:15:29 +00001607 struct ospf_opaque_functab *functab;
1608
1609 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL
1610 || functab->lsa_refresher == NULL)
1611 {
1612 /*
1613 * Though this LSA seems to have originated on this node, the
1614 * handling module for this "lsa-type and opaque-type" was
1615 * already deleted sometime ago.
1616 * Anyway, this node still has a responsibility to flush this
1617 * LSA from the routing domain.
1618 */
1619 if (IS_DEBUG_OSPF_EVENT)
1620 zlog_info ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id));
1621
1622 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
paul68980082003-03-25 05:07:42 +00001623 ospf_lsa_maxage (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00001624 }
1625 else
1626 (* functab->lsa_refresher)(lsa);
1627
1628 return;
1629}
1630
1631/*------------------------------------------------------------------------*
1632 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1633 * triggered by external interventions (vty session, signaling, etc).
1634 *------------------------------------------------------------------------*/
1635
1636#define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
1637 if (!(T)) \
1638 (T) = thread_add_timer (master, (F), (L), (V))
1639
1640static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type);
1641static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t);
1642static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t);
1643static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t);
1644static int ospf_opaque_lsa_refresh_timer (struct thread *t);
1645
1646void
1647ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
1648 u_char lsa_type, u_char opaque_type)
1649{
1650 struct ospf *top;
1651 struct ospf_area dummy, *area = NULL;
1652 struct ospf_interface *oi = NULL;
1653
1654 struct ospf_lsa *lsa;
1655 struct opaque_info_per_type *oipt;
1656 int (* func)(struct thread *t) = NULL;
1657 int delay;
1658
1659 switch (lsa_type)
1660 {
1661 case OSPF_OPAQUE_LINK_LSA:
1662 if ((oi = (struct ospf_interface *) lsa_type_dependent) == NULL)
1663 {
1664 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Type-9 Opaque-LSA: Invalid parameter?");
1665 goto out;
1666 }
1667 if ((top = oi_to_top (oi)) == NULL)
1668 {
1669 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?", IF_NAME (oi));
1670 goto out;
1671 }
1672 if (! list_isempty (ospf_opaque_type9_funclist)
1673 && list_isempty (oi->opaque_lsa_self)
1674 && oi->t_opaque_lsa_self != NULL)
1675 {
1676 zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u): Common origination for OI(%s) has already started", opaque_type, IF_NAME (oi));
1677 goto out;
1678 }
1679 func = ospf_opaque_type9_lsa_reoriginate_timer;
1680 break;
1681 case OSPF_OPAQUE_AREA_LSA:
1682 if ((area = (struct ospf_area *) lsa_type_dependent) == NULL)
1683 {
1684 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Type-10 Opaque-LSA: Invalid parameter?");
1685 goto out;
1686 }
paul68980082003-03-25 05:07:42 +00001687 if ((top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001688 {
1689 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: AREA(%s) -> TOP?", inet_ntoa (area->area_id));
1690 goto out;
1691 }
1692 if (! list_isempty (ospf_opaque_type10_funclist)
1693 && list_isempty (area->opaque_lsa_self)
1694 && area->t_opaque_lsa_self != NULL)
1695 {
1696 zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u): Common origination for AREA(%s) has already started", opaque_type, inet_ntoa (area->area_id));
1697 goto out;
1698 }
1699 func = ospf_opaque_type10_lsa_reoriginate_timer;
1700 break;
1701 case OSPF_OPAQUE_AS_LSA:
1702 if ((top = (struct ospf *) lsa_type_dependent) == NULL)
1703 {
1704 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Type-11 Opaque-LSA: Invalid parameter?");
1705 goto out;
1706 }
1707 if (! list_isempty (ospf_opaque_type11_funclist)
1708 && list_isempty (top->opaque_lsa_self)
1709 && top->t_opaque_lsa_self != NULL)
1710 {
1711 zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u): Common origination has already started", opaque_type);
1712 goto out;
1713 }
1714
1715 /* Fake "area" to pass "ospf" to a lookup function later. */
paul68980082003-03-25 05:07:42 +00001716 dummy.ospf = top;
paul718e3742002-12-13 20:15:29 +00001717 area = &dummy;
1718
1719 func = ospf_opaque_type11_lsa_reoriginate_timer;
1720 break;
1721 default:
1722 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Unexpected LSA-type(%u)", lsa_type);
1723 goto out;
1724 }
1725
1726 /* It may not a right time to schedule reorigination now. */
1727 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1728 {
1729 if (IS_DEBUG_OSPF_EVENT)
1730 zlog_info ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
1731 goto out; /* This is not an error. */
1732 }
1733 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
1734 {
1735 if (IS_DEBUG_OSPF_EVENT)
1736 zlog_info ("ospf_opaque_lsa_reoriginate_schedule: Under blockade.");
1737 goto out; /* This is not an error, too. */
1738 }
1739
1740 /* Generate a dummy lsa to be passed for a lookup function. */
1741 lsa = pseudo_lsa (oi, area, lsa_type, opaque_type);
1742
1743 if ((oipt = lookup_opaque_info_by_type (lsa)) == NULL)
1744 {
1745 struct ospf_opaque_functab *functab;
1746 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL)
1747 {
1748 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: No associated function?: lsa_type(%u), opaque_type(%u)", lsa_type, opaque_type);
1749 goto out;
1750 }
1751 if ((oipt = register_opaque_info_per_type (functab, lsa)) == NULL)
1752 {
1753 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Cannot get a control info?: lsa_type(%u), opaque_type(%u)", lsa_type, opaque_type);
1754 goto out;
1755 }
1756 }
1757
1758 if (oipt->t_opaque_lsa_self != NULL)
1759 {
1760 if (IS_DEBUG_OSPF_EVENT)
1761 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)));
1762 goto out;
1763 }
1764
1765 /*
1766 * Different from initial origination time, in which various conditions
1767 * (opaque capability, neighbor status etc) are assured by caller of
1768 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1769 * it is highly possible that these conditions might not be satisfied
1770 * at the time of re-origination function is to be called.
1771 */
1772 delay = OSPF_MIN_LS_INTERVAL; /* XXX */
1773
1774 if (IS_DEBUG_OSPF_EVENT)
1775 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)));
1776
1777 OSPF_OPAQUE_TIMER_ON (oipt->t_opaque_lsa_self, func, oipt, delay);
1778
1779out:
1780 return;
1781}
1782
1783static struct ospf_lsa *
1784pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area,
1785 u_char lsa_type, u_char opaque_type)
1786{
1787 static struct ospf_lsa lsa = { 0 };
1788 static struct lsa_header lsah = { 0 };
1789 u_int32_t tmp;
1790
1791 lsa.oi = oi;
1792 lsa.area = area;
1793 lsa.data = &lsah;
1794
1795 lsah.type = lsa_type;
1796 tmp = SET_OPAQUE_LSID (opaque_type, 0); /* Opaque-ID is unused here. */
1797 lsah.id.s_addr = htonl (tmp);
1798
1799 return &lsa;
1800}
1801
1802static int
1803ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t)
1804{
1805 struct opaque_info_per_type *oipt;
1806 struct ospf_opaque_functab *functab;
1807 struct ospf *top;
1808 struct ospf_interface *oi;
1809 int rc = -1;
1810
1811 oipt = THREAD_ARG (t);
1812 oipt->t_opaque_lsa_self = NULL;
1813
1814 if ((functab = oipt->functab) == NULL
1815 || functab->lsa_originator == NULL)
1816 {
1817 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1818 goto out;
1819 }
1820
1821 oi = (struct ospf_interface *) oipt->owner;
1822 if ((top = oi_to_top (oi)) == NULL)
1823 {
1824 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1825 goto out;
1826 }
1827
1828 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)
1829 || ! ospf_if_is_enable (oi)
paul68980082003-03-25 05:07:42 +00001830 || ospf_nbr_count_opaque_capable (oi) == 0)
paul718e3742002-12-13 20:15:29 +00001831 {
1832 if (IS_DEBUG_OSPF_EVENT)
1833 zlog_info ("Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
1834
1835 oipt->status = PROC_SUSPEND;
1836 rc = 0;
1837 goto out;
1838 }
1839
1840 if (IS_DEBUG_OSPF_EVENT)
1841 zlog_info ("Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)", oipt->opaque_type, IF_NAME (oi));
1842
1843 rc = (* functab->lsa_originator)(oi);
1844out:
1845 return rc;
1846}
1847
1848static int
1849ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t)
1850{
1851 struct opaque_info_per_type *oipt;
1852 struct ospf_opaque_functab *functab;
1853 listnode node;
1854 struct ospf *top;
1855 struct ospf_area *area;
1856 struct ospf_interface *oi;
1857 int n, rc = -1;
1858
1859 oipt = THREAD_ARG (t);
1860 oipt->t_opaque_lsa_self = NULL;
1861
1862 if ((functab = oipt->functab) == NULL
1863 || functab->lsa_originator == NULL)
1864 {
1865 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1866 goto out;
1867 }
1868
1869 area = (struct ospf_area *) oipt->owner;
paul68980082003-03-25 05:07:42 +00001870 if (area == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001871 {
1872 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1873 goto out;
1874 }
1875
1876 /* There must be at least one "opaque-capable, full-state" neighbor. */
1877 n = 0;
1878 for (node = listhead (area->oiflist); node; nextnode (node))
1879 {
1880 if ((oi = getdata (node)) == NULL)
1881 continue;
paul68980082003-03-25 05:07:42 +00001882 if ((n = ospf_nbr_count_opaque_capable (oi)) > 0)
paul718e3742002-12-13 20:15:29 +00001883 break;
1884 }
1885
1886 if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1887 {
1888 if (IS_DEBUG_OSPF_EVENT)
1889 zlog_info ("Suspend re-origination of Type-10 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
1890
1891 oipt->status = PROC_SUSPEND;
1892 rc = 0;
1893 goto out;
1894 }
1895
1896 if (IS_DEBUG_OSPF_EVENT)
1897 zlog_info ("Timer[Type10-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for Area %s", oipt->opaque_type, inet_ntoa (area->area_id));
1898
1899 rc = (* functab->lsa_originator)(area);
1900out:
1901 return rc;
1902}
1903
1904static int
1905ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t)
1906{
1907 struct opaque_info_per_type *oipt;
1908 struct ospf_opaque_functab *functab;
1909 struct ospf *top;
1910 int rc = -1;
1911
1912 oipt = THREAD_ARG (t);
1913 oipt->t_opaque_lsa_self = NULL;
1914
1915 if ((functab = oipt->functab) == NULL
1916 || functab->lsa_originator == NULL)
1917 {
1918 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: No associated function?");
1919 goto out;
1920 }
1921
1922 if ((top = (struct ospf *) oipt->owner) == NULL)
1923 {
1924 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1925 goto out;
1926 }
1927
1928 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1929 {
1930 if (IS_DEBUG_OSPF_EVENT)
1931 zlog_info ("Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
1932
1933 oipt->status = PROC_SUSPEND;
1934 rc = 0;
1935 goto out;
1936 }
1937
1938 if (IS_DEBUG_OSPF_EVENT)
1939 zlog_info ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type);
1940
1941 rc = (* functab->lsa_originator)(top);
1942out:
1943 return rc;
1944}
1945
1946extern int ospf_lsa_refresh_delay (struct ospf_lsa *); /* ospf_lsa.c */
1947
1948void
1949ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
1950{
paul68980082003-03-25 05:07:42 +00001951 struct ospf *ospf = ospf_top;
paul718e3742002-12-13 20:15:29 +00001952 struct opaque_info_per_type *oipt;
1953 struct opaque_info_per_id *oipi;
1954 struct ospf_lsa *lsa;
1955 int delay;
1956
1957 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
1958 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
1959 {
1960 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
1961 goto out;
1962 }
1963
1964 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
1965 if ((lsa = oipi->lsa) == NULL)
1966 {
1967 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
1968 goto out;
1969 }
1970
1971 if (oipi->t_opaque_lsa_self != NULL)
1972 {
1973 if (IS_DEBUG_OSPF_EVENT)
1974 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)));
1975 goto out;
1976 }
1977
1978 /* Delete this lsa from neighbor retransmit-list. */
1979 switch (lsa->data->type)
1980 {
1981 case OSPF_OPAQUE_LINK_LSA:
1982 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00001983 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00001984 break;
1985 case OSPF_OPAQUE_AS_LSA:
paul68980082003-03-25 05:07:42 +00001986 ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00001987 break;
1988 default:
1989 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type);
1990 goto out;
1991 }
1992
1993 delay = ospf_lsa_refresh_delay (lsa);
1994
1995 if (IS_DEBUG_OSPF_EVENT)
1996 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)));
1997
1998 OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self,
1999 ospf_opaque_lsa_refresh_timer, oipi, delay);
2000out:
2001 return;
2002}
2003
2004static int
2005ospf_opaque_lsa_refresh_timer (struct thread *t)
2006{
2007 struct opaque_info_per_id *oipi;
2008 struct ospf_opaque_functab *functab;
2009 struct ospf_lsa *lsa;
2010
2011 if (IS_DEBUG_OSPF_EVENT)
2012 zlog_info ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
2013
2014 oipi = THREAD_ARG (t);
2015 oipi->t_opaque_lsa_self = NULL;
2016
2017 if ((lsa = oipi->lsa) != NULL)
2018 if ((functab = oipi->opqctl_type->functab) != NULL)
2019 if (functab->lsa_refresher != NULL)
2020 (* functab->lsa_refresher)(lsa);
2021
2022 return 0;
2023}
2024
2025void
2026ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
2027{
paul68980082003-03-25 05:07:42 +00002028 struct ospf *ospf = ospf_top;
paul718e3742002-12-13 20:15:29 +00002029 struct opaque_info_per_type *oipt;
2030 struct opaque_info_per_id *oipi;
2031 struct ospf_lsa *lsa;
2032
2033 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
2034 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
2035 {
2036 zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2037 goto out;
2038 }
2039
2040 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2041 if ((lsa = oipi->lsa) == NULL)
2042 {
2043 zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
2044 goto out;
2045 }
2046
2047 /* Delete this lsa from neighbor retransmit-list. */
2048 switch (lsa->data->type)
2049 {
2050 case OSPF_OPAQUE_LINK_LSA:
2051 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002052 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002053 break;
2054 case OSPF_OPAQUE_AS_LSA:
paul68980082003-03-25 05:07:42 +00002055 ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002056 break;
2057 default:
2058 zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2059 goto out;
2060 }
2061
2062 /* Dequeue listnode entry from the list. */
2063 listnode_delete (oipt->id_list, oipi);
2064
2065 /* Avoid misjudgement in the next lookup. */
2066 if (listcount (oipt->id_list) == 0)
2067 oipt->id_list->head = oipt->id_list->tail = NULL;
2068
2069 /* Disassociate internal control information with the given lsa. */
2070 oipi->lsa = NULL;
2071 free_opaque_info_per_id ((void *) oipi);
2072
2073 /* Force given lsa's age to MaxAge. */
2074 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2075
2076 if (IS_DEBUG_OSPF_EVENT)
2077 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)));
2078
2079 /* This lsa will be flushed and removed eventually. */
paul68980082003-03-25 05:07:42 +00002080 ospf_lsa_maxage (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002081
2082out:
2083 return;
2084}
2085
2086/*------------------------------------------------------------------------*
2087 * Followings are control functions to block origination after restart.
2088 *------------------------------------------------------------------------*/
2089
2090static void ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs, struct ospf_neighbor *inbr, struct ospf_lsa *lsa);
2091static void ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi);
2092static void ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area);
2093static void ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top);
2094static unsigned long ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type);
2095
2096void
2097ospf_opaque_adjust_lsreq (struct ospf_neighbor *nbr, list lsas)
2098{
2099 struct ospf *top;
2100 struct ospf_area *area;
2101 struct ospf_interface *oi;
2102 listnode node1, node2;
2103 struct ospf_lsa *lsa;
2104
2105 if ((top = oi_to_top (nbr->oi)) == NULL)
2106 goto out;
2107
2108 /*
2109 * If an instance of self-originated Opaque-LSA is found in the given
2110 * LSA list, and it is not installed to LSDB yet, exclude it from the
2111 * list "nbr->ls_req". In this way, it is assured that an LSReq message,
2112 * which might be sent in the process of flooding, will not request for
2113 * the LSA to be flushed immediately; otherwise, depending on timing,
2114 * an LSUpd message will carry instances of target LSAs with MaxAge,
2115 * while other LSUpd message might carry old LSA instances (non-MaxAge).
2116 * Obviously, the latter would trigger miserable situations that repeat
2117 * installation and removal of unwanted LSAs indefinitely.
2118 */
2119 for (node1 = listhead (lsas); node1; nextnode (node1))
2120 {
2121 if ((lsa = getdata (node1)) == NULL)
2122 continue;
2123
2124 /* Filter out unwanted LSAs. */
2125 if (! IS_OPAQUE_LSA (lsa->data->type))
2126 continue;
2127 if (! IPV4_ADDR_SAME (&lsa->data->adv_router, &top->router_id))
2128 continue;
2129
2130 /*
2131 * Don't touch an LSA which has MaxAge; two possible cases.
2132 *
2133 * 1) This LSA has originally flushed by myself (received LSUpd
2134 * message's router-id is equal to my router-id), and flooded
2135 * back by an opaque-capable router.
2136 *
2137 * 2) This LSA has expired in an opaque-capable router and thus
2138 * flushed by the router.
2139 */
2140 if (IS_LSA_MAXAGE (lsa))
2141 continue;
2142
2143 /* If the LSA has installed in the LSDB, nothing to do here. */
2144 if (ospf_lsa_lookup_by_header (nbr->oi->area, lsa->data) != NULL)
2145 continue;
2146
2147 /* Ok, here we go. */
2148 switch (lsa->data->type)
2149 {
2150 case OSPF_OPAQUE_LINK_LSA:
2151 oi = nbr->oi;
2152 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2153 break;
2154 case OSPF_OPAQUE_AREA_LSA:
2155 area = nbr->oi->area;
2156 for (node2 = listhead (area->oiflist); node2; nextnode (node2))
2157 {
2158 if ((oi = getdata (node2)) == NULL)
2159 continue;
2160 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2161 }
2162 break;
2163 case OSPF_OPAQUE_AS_LSA:
2164 for (node2 = listhead (top->oiflist); node2; nextnode (node2))
2165 {
2166 if ((oi = getdata (node2)) == NULL)
2167 continue;
2168 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2169 }
2170 break;
2171 default:
2172 break;
2173 }
2174 }
2175
2176out:
2177 return;
2178}
2179
2180static void
2181ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs,
2182 struct ospf_neighbor *inbr,
2183 struct ospf_lsa *lsa)
2184{
2185 struct route_node *rn;
2186 struct ospf_neighbor *onbr;
2187 struct ospf_lsa *ls_req;
2188
2189 for (rn = route_top (nbrs); rn; rn = route_next (rn))
2190 {
2191 if ((onbr = rn->info) == NULL)
2192 continue;
2193 if (onbr == inbr)
2194 continue;
2195 if ((ls_req = ospf_ls_request_lookup (onbr, lsa)) == NULL)
2196 continue;
2197
2198 if (IS_DEBUG_OSPF_EVENT)
2199 zlog_info ("LSA[%s]: Exclude this entry from LSReq to send.", dump_lsa_key (lsa));
2200
2201 ospf_ls_request_delete (onbr, ls_req);
2202/* ospf_check_nbr_loading (onbr);*//* XXX */
2203 }
2204
2205 return;
2206}
2207
2208void
2209ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr, list lsas)
2210{
2211 struct ospf *top;
2212 listnode node, next;
2213 struct ospf_lsa *lsa;
2214 u_char before;
2215
2216 if ((top = oi_to_top (nbr->oi)) == NULL)
2217 goto out;
2218
2219 before = IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque);
2220
2221 for (node = listhead (lsas); node; node = next)
2222 {
2223 next = node->next;
2224
2225 if ((lsa = getdata (node)) == NULL)
2226 continue;
2227
2228 listnode_delete (lsas, lsa);
2229
2230 /*
2231 * Since these LSA entries are not yet installed into corresponding
2232 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2233 */
2234 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2235 switch (lsa->data->type)
2236 {
2237 case OSPF_OPAQUE_LINK_LSA:
2238 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
2239 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2240 break;
2241 case OSPF_OPAQUE_AREA_LSA:
2242 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
2243 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2244 break;
2245 case OSPF_OPAQUE_AS_LSA:
2246 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
paul68980082003-03-25 05:07:42 +00002247 ospf_flood_through_as (top, NULL/*inbr*/, lsa);
paul718e3742002-12-13 20:15:29 +00002248 break;
2249 default:
2250 zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
2251 goto out;
2252 }
2253
2254 ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */
2255 }
2256
2257 if (before == 0 && IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2258 {
2259 if (IS_DEBUG_OSPF_EVENT)
2260 zlog_info ("Block Opaque-LSA origination: OFF -> ON");
2261 }
2262
2263out:
2264 return;
2265}
2266
2267void
2268ospf_opaque_ls_ack_received (struct ospf_neighbor *nbr, list acks)
2269{
2270 struct ospf *top;
2271 listnode node;
2272 struct ospf_lsa *lsa;
2273 char type9_lsa_rcv = 0, type10_lsa_rcv = 0, type11_lsa_rcv = 0;
2274
2275 if ((top = oi_to_top (nbr->oi)) == NULL)
2276 goto out;
2277
2278 for (node = listhead (acks); node; nextnode (node))
2279 {
2280 if ((lsa = getdata (node)) == NULL)
2281 continue;
2282
2283 switch (lsa->data->type)
2284 {
2285 case OSPF_OPAQUE_LINK_LSA:
2286 type9_lsa_rcv = 1;
2287 /* Callback function... */
2288 break;
2289 case OSPF_OPAQUE_AREA_LSA:
2290 type10_lsa_rcv = 1;
2291 /* Callback function... */
2292 break;
2293 case OSPF_OPAQUE_AS_LSA:
2294 type11_lsa_rcv = 1;
2295 /* Callback function... */
2296 break;
2297 default:
2298 zlog_warn ("ospf_opaque_ls_ack_received: Unexpected LSA-type(%u)", lsa->data->type);
2299 goto out;
2300 }
2301 }
2302
2303 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2304 {
2305 int delay;
2306 struct ospf_interface *oi;
2307
2308 if (type9_lsa_rcv
2309 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT))
2310 ospf_opaque_type9_lsa_rxmt_nbr_check (nbr->oi);
2311
2312 if (type10_lsa_rcv
2313 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT))
2314 ospf_opaque_type10_lsa_rxmt_nbr_check (nbr->oi->area);
2315
2316 if (type11_lsa_rcv
2317 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT))
2318 ospf_opaque_type11_lsa_rxmt_nbr_check (top);
2319
2320 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2321 goto out; /* Blocking still in progress. */
2322
2323 if (IS_DEBUG_OSPF_EVENT)
2324 zlog_info ("Block Opaque-LSA origination: ON -> OFF");
2325
2326 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
2327 goto out; /* Opaque capability condition must have changed. */
2328
2329 /* Ok, let's start origination of Opaque-LSAs. */
2330 delay = OSPF_MIN_LS_INTERVAL;
2331 for (node = listhead (top->oiflist); node; nextnode (node))
2332 {
2333 if ((oi = getdata (node)) == NULL)
2334 continue;
2335
2336 if (! ospf_if_is_enable (oi)
paul68980082003-03-25 05:07:42 +00002337 || ospf_nbr_count_opaque_capable (oi) == 0)
paul718e3742002-12-13 20:15:29 +00002338 continue;
2339
2340 ospf_opaque_lsa_originate_schedule (oi, &delay);
2341 }
2342 }
2343
2344out:
2345 return;
2346}
2347
2348static void
2349ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi)
2350{
2351 unsigned long n;
2352
2353 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_LINK_LSA);
2354 if (n == 0)
2355 {
2356 if (IS_DEBUG_OSPF_EVENT)
2357 zlog_info ("Self-originated type-9 Opaque-LSAs: OI(%s): Flush completed", IF_NAME (oi));
2358
paul68980082003-03-25 05:07:42 +00002359 UNSET_FLAG (oi->area->ospf->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
paul718e3742002-12-13 20:15:29 +00002360 }
2361 return;
2362}
2363
2364static void
2365ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area)
2366{
2367 listnode node;
2368 struct ospf_interface *oi;
2369 unsigned long n = 0;
2370
2371 for (node = listhead (area->oiflist); node; nextnode (node))
2372 {
2373 if ((oi = getdata (node)) == NULL)
2374 continue;
2375
2376 if (area->area_id.s_addr != OSPF_AREA_BACKBONE
2377 && oi->type == OSPF_IFTYPE_VIRTUALLINK)
2378 continue;
2379
2380 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AREA_LSA);
2381 if (n > 0)
2382 break;
2383 }
2384
2385 if (n == 0)
2386 {
2387 if (IS_DEBUG_OSPF_EVENT)
2388 zlog_info ("Self-originated type-10 Opaque-LSAs: AREA(%s): Flush completed", inet_ntoa (area->area_id));
2389
paul68980082003-03-25 05:07:42 +00002390 UNSET_FLAG (area->ospf->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
paul718e3742002-12-13 20:15:29 +00002391 }
2392
2393 return;
2394}
2395
2396static void
2397ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top)
2398{
2399 listnode node;
2400 struct ospf_interface *oi;
2401 unsigned long n = 0;
2402
2403 for (node = listhead (top->oiflist); node; nextnode (node))
2404 {
2405 if ((oi = getdata (node)) == NULL)
2406 continue;
2407
2408 switch (oi->type)
2409 {
2410 case OSPF_IFTYPE_VIRTUALLINK:
2411 continue;
2412 default:
2413 break;
2414 }
2415
2416 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AS_LSA);
2417 if (n > 0)
2418 goto out;
2419 }
2420
2421 if (n == 0)
2422 {
2423 if (IS_DEBUG_OSPF_EVENT)
2424 zlog_info ("Self-originated type-11 Opaque-LSAs: Flush completed");
2425
2426 UNSET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
2427 }
2428
2429out:
2430 return;
2431}
2432
2433static unsigned long
2434ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type)
2435{
2436 struct route_node *rn;
2437 struct ospf_neighbor *nbr;
2438 struct ospf *top;
2439 unsigned long n = 0;
2440
2441 for (rn = route_top (nbrs); rn; rn = route_next (rn))
2442 {
2443 if ((nbr = rn->info) == NULL)
2444 continue;
2445 if ((top = oi_to_top (nbr->oi)) == NULL)
2446 continue;
2447 if (IPV4_ADDR_SAME (&nbr->router_id, &top->router_id))
2448 continue;
2449 n += ospf_ls_retransmit_count_self (nbr, lsa_type);
2450 }
2451
2452 return n;
2453}
2454
2455/*------------------------------------------------------------------------*
2456 * Followings are util functions; probably be used by Opaque-LSAs only...
2457 *------------------------------------------------------------------------*/
2458
2459void
2460htonf (float *src, float *dst)
2461{
2462 u_int32_t lu1, lu2;
2463
2464 memcpy (&lu1, src, sizeof (u_int32_t));
2465 lu2 = htonl (lu1);
2466 memcpy (dst, &lu2, sizeof (u_int32_t));
2467 return;
2468}
2469
2470void
2471ntohf (float *src, float *dst)
2472{
2473 u_int32_t lu1, lu2;
2474
2475 memcpy (&lu1, src, sizeof (u_int32_t));
2476 lu2 = ntohl (lu1);
2477 memcpy (dst, &lu2, sizeof (u_int32_t));
2478 return;
2479}
2480
2481struct ospf *
2482oi_to_top (struct ospf_interface *oi)
2483{
2484 struct ospf *top = NULL;
2485 struct ospf_area *area;
2486
paul68980082003-03-25 05:07:42 +00002487 if (oi == NULL || (area = oi->area) == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00002488 zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");
2489
2490 return top;
2491}
2492
2493#endif /* HAVE_OPAQUE_LSA */