blob: fa9c4dba5c8453788a3d387a1dbb9a47b3935d7b [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;
548 if (new->area != NULL && (top = new->area->top) == NULL)
549 {
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;
656 if ((area = lsa->area) != NULL && (top = area->top) == NULL)
657 {
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:
1575 if (lsa->area == NULL || (top = lsa->area->top) == NULL)
1576 {
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;
1584 if (lsa->area != NULL && (top = lsa->area->top) == NULL)
1585 {
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{
1606 struct ospf_opaque_functab *functab;
1607
1608 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL
1609 || functab->lsa_refresher == NULL)
1610 {
1611 /*
1612 * Though this LSA seems to have originated on this node, the
1613 * handling module for this "lsa-type and opaque-type" was
1614 * already deleted sometime ago.
1615 * Anyway, this node still has a responsibility to flush this
1616 * LSA from the routing domain.
1617 */
1618 if (IS_DEBUG_OSPF_EVENT)
1619 zlog_info ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id));
1620
1621 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
1622 ospf_lsa_maxage (lsa);
1623 }
1624 else
1625 (* functab->lsa_refresher)(lsa);
1626
1627 return;
1628}
1629
1630/*------------------------------------------------------------------------*
1631 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1632 * triggered by external interventions (vty session, signaling, etc).
1633 *------------------------------------------------------------------------*/
1634
1635#define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
1636 if (!(T)) \
1637 (T) = thread_add_timer (master, (F), (L), (V))
1638
1639static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type);
1640static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t);
1641static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t);
1642static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t);
1643static int ospf_opaque_lsa_refresh_timer (struct thread *t);
1644
1645void
1646ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
1647 u_char lsa_type, u_char opaque_type)
1648{
1649 struct ospf *top;
1650 struct ospf_area dummy, *area = NULL;
1651 struct ospf_interface *oi = NULL;
1652
1653 struct ospf_lsa *lsa;
1654 struct opaque_info_per_type *oipt;
1655 int (* func)(struct thread *t) = NULL;
1656 int delay;
1657
1658 switch (lsa_type)
1659 {
1660 case OSPF_OPAQUE_LINK_LSA:
1661 if ((oi = (struct ospf_interface *) lsa_type_dependent) == NULL)
1662 {
1663 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Type-9 Opaque-LSA: Invalid parameter?");
1664 goto out;
1665 }
1666 if ((top = oi_to_top (oi)) == NULL)
1667 {
1668 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?", IF_NAME (oi));
1669 goto out;
1670 }
1671 if (! list_isempty (ospf_opaque_type9_funclist)
1672 && list_isempty (oi->opaque_lsa_self)
1673 && oi->t_opaque_lsa_self != NULL)
1674 {
1675 zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u): Common origination for OI(%s) has already started", opaque_type, IF_NAME (oi));
1676 goto out;
1677 }
1678 func = ospf_opaque_type9_lsa_reoriginate_timer;
1679 break;
1680 case OSPF_OPAQUE_AREA_LSA:
1681 if ((area = (struct ospf_area *) lsa_type_dependent) == NULL)
1682 {
1683 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Type-10 Opaque-LSA: Invalid parameter?");
1684 goto out;
1685 }
1686 if ((top = area->top) == NULL)
1687 {
1688 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: AREA(%s) -> TOP?", inet_ntoa (area->area_id));
1689 goto out;
1690 }
1691 if (! list_isempty (ospf_opaque_type10_funclist)
1692 && list_isempty (area->opaque_lsa_self)
1693 && area->t_opaque_lsa_self != NULL)
1694 {
1695 zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u): Common origination for AREA(%s) has already started", opaque_type, inet_ntoa (area->area_id));
1696 goto out;
1697 }
1698 func = ospf_opaque_type10_lsa_reoriginate_timer;
1699 break;
1700 case OSPF_OPAQUE_AS_LSA:
1701 if ((top = (struct ospf *) lsa_type_dependent) == NULL)
1702 {
1703 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Type-11 Opaque-LSA: Invalid parameter?");
1704 goto out;
1705 }
1706 if (! list_isempty (ospf_opaque_type11_funclist)
1707 && list_isempty (top->opaque_lsa_self)
1708 && top->t_opaque_lsa_self != NULL)
1709 {
1710 zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u): Common origination has already started", opaque_type);
1711 goto out;
1712 }
1713
1714 /* Fake "area" to pass "ospf" to a lookup function later. */
1715 dummy.top = top;
1716 area = &dummy;
1717
1718 func = ospf_opaque_type11_lsa_reoriginate_timer;
1719 break;
1720 default:
1721 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Unexpected LSA-type(%u)", lsa_type);
1722 goto out;
1723 }
1724
1725 /* It may not a right time to schedule reorigination now. */
1726 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1727 {
1728 if (IS_DEBUG_OSPF_EVENT)
1729 zlog_info ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
1730 goto out; /* This is not an error. */
1731 }
1732 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
1733 {
1734 if (IS_DEBUG_OSPF_EVENT)
1735 zlog_info ("ospf_opaque_lsa_reoriginate_schedule: Under blockade.");
1736 goto out; /* This is not an error, too. */
1737 }
1738
1739 /* Generate a dummy lsa to be passed for a lookup function. */
1740 lsa = pseudo_lsa (oi, area, lsa_type, opaque_type);
1741
1742 if ((oipt = lookup_opaque_info_by_type (lsa)) == NULL)
1743 {
1744 struct ospf_opaque_functab *functab;
1745 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL)
1746 {
1747 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: No associated function?: lsa_type(%u), opaque_type(%u)", lsa_type, opaque_type);
1748 goto out;
1749 }
1750 if ((oipt = register_opaque_info_per_type (functab, lsa)) == NULL)
1751 {
1752 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Cannot get a control info?: lsa_type(%u), opaque_type(%u)", lsa_type, opaque_type);
1753 goto out;
1754 }
1755 }
1756
1757 if (oipt->t_opaque_lsa_self != NULL)
1758 {
1759 if (IS_DEBUG_OSPF_EVENT)
1760 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)));
1761 goto out;
1762 }
1763
1764 /*
1765 * Different from initial origination time, in which various conditions
1766 * (opaque capability, neighbor status etc) are assured by caller of
1767 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1768 * it is highly possible that these conditions might not be satisfied
1769 * at the time of re-origination function is to be called.
1770 */
1771 delay = OSPF_MIN_LS_INTERVAL; /* XXX */
1772
1773 if (IS_DEBUG_OSPF_EVENT)
1774 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)));
1775
1776 OSPF_OPAQUE_TIMER_ON (oipt->t_opaque_lsa_self, func, oipt, delay);
1777
1778out:
1779 return;
1780}
1781
1782static struct ospf_lsa *
1783pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area,
1784 u_char lsa_type, u_char opaque_type)
1785{
1786 static struct ospf_lsa lsa = { 0 };
1787 static struct lsa_header lsah = { 0 };
1788 u_int32_t tmp;
1789
1790 lsa.oi = oi;
1791 lsa.area = area;
1792 lsa.data = &lsah;
1793
1794 lsah.type = lsa_type;
1795 tmp = SET_OPAQUE_LSID (opaque_type, 0); /* Opaque-ID is unused here. */
1796 lsah.id.s_addr = htonl (tmp);
1797
1798 return &lsa;
1799}
1800
1801static int
1802ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t)
1803{
1804 struct opaque_info_per_type *oipt;
1805 struct ospf_opaque_functab *functab;
1806 struct ospf *top;
1807 struct ospf_interface *oi;
1808 int rc = -1;
1809
1810 oipt = THREAD_ARG (t);
1811 oipt->t_opaque_lsa_self = NULL;
1812
1813 if ((functab = oipt->functab) == NULL
1814 || functab->lsa_originator == NULL)
1815 {
1816 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1817 goto out;
1818 }
1819
1820 oi = (struct ospf_interface *) oipt->owner;
1821 if ((top = oi_to_top (oi)) == NULL)
1822 {
1823 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1824 goto out;
1825 }
1826
1827 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)
1828 || ! ospf_if_is_enable (oi)
1829 || ospf_opaque_capable_nbr_count (oi->nbrs, NSM_Full) == 0)
1830 {
1831 if (IS_DEBUG_OSPF_EVENT)
1832 zlog_info ("Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
1833
1834 oipt->status = PROC_SUSPEND;
1835 rc = 0;
1836 goto out;
1837 }
1838
1839 if (IS_DEBUG_OSPF_EVENT)
1840 zlog_info ("Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)", oipt->opaque_type, IF_NAME (oi));
1841
1842 rc = (* functab->lsa_originator)(oi);
1843out:
1844 return rc;
1845}
1846
1847static int
1848ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t)
1849{
1850 struct opaque_info_per_type *oipt;
1851 struct ospf_opaque_functab *functab;
1852 listnode node;
1853 struct ospf *top;
1854 struct ospf_area *area;
1855 struct ospf_interface *oi;
1856 int n, rc = -1;
1857
1858 oipt = THREAD_ARG (t);
1859 oipt->t_opaque_lsa_self = NULL;
1860
1861 if ((functab = oipt->functab) == NULL
1862 || functab->lsa_originator == NULL)
1863 {
1864 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1865 goto out;
1866 }
1867
1868 area = (struct ospf_area *) oipt->owner;
1869 if (area == NULL || (top = area->top) == NULL)
1870 {
1871 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1872 goto out;
1873 }
1874
1875 /* There must be at least one "opaque-capable, full-state" neighbor. */
1876 n = 0;
1877 for (node = listhead (area->oiflist); node; nextnode (node))
1878 {
1879 if ((oi = getdata (node)) == NULL)
1880 continue;
1881 if ((n = ospf_opaque_capable_nbr_count (oi->nbrs, NSM_Full)) > 0)
1882 break;
1883 }
1884
1885 if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1886 {
1887 if (IS_DEBUG_OSPF_EVENT)
1888 zlog_info ("Suspend re-origination of Type-10 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
1889
1890 oipt->status = PROC_SUSPEND;
1891 rc = 0;
1892 goto out;
1893 }
1894
1895 if (IS_DEBUG_OSPF_EVENT)
1896 zlog_info ("Timer[Type10-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for Area %s", oipt->opaque_type, inet_ntoa (area->area_id));
1897
1898 rc = (* functab->lsa_originator)(area);
1899out:
1900 return rc;
1901}
1902
1903static int
1904ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t)
1905{
1906 struct opaque_info_per_type *oipt;
1907 struct ospf_opaque_functab *functab;
1908 struct ospf *top;
1909 int rc = -1;
1910
1911 oipt = THREAD_ARG (t);
1912 oipt->t_opaque_lsa_self = NULL;
1913
1914 if ((functab = oipt->functab) == NULL
1915 || functab->lsa_originator == NULL)
1916 {
1917 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: No associated function?");
1918 goto out;
1919 }
1920
1921 if ((top = (struct ospf *) oipt->owner) == NULL)
1922 {
1923 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1924 goto out;
1925 }
1926
1927 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1928 {
1929 if (IS_DEBUG_OSPF_EVENT)
1930 zlog_info ("Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
1931
1932 oipt->status = PROC_SUSPEND;
1933 rc = 0;
1934 goto out;
1935 }
1936
1937 if (IS_DEBUG_OSPF_EVENT)
1938 zlog_info ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type);
1939
1940 rc = (* functab->lsa_originator)(top);
1941out:
1942 return rc;
1943}
1944
1945extern int ospf_lsa_refresh_delay (struct ospf_lsa *); /* ospf_lsa.c */
1946
1947void
1948ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
1949{
1950 struct opaque_info_per_type *oipt;
1951 struct opaque_info_per_id *oipi;
1952 struct ospf_lsa *lsa;
1953 int delay;
1954
1955 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
1956 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
1957 {
1958 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
1959 goto out;
1960 }
1961
1962 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
1963 if ((lsa = oipi->lsa) == NULL)
1964 {
1965 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
1966 goto out;
1967 }
1968
1969 if (oipi->t_opaque_lsa_self != NULL)
1970 {
1971 if (IS_DEBUG_OSPF_EVENT)
1972 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)));
1973 goto out;
1974 }
1975
1976 /* Delete this lsa from neighbor retransmit-list. */
1977 switch (lsa->data->type)
1978 {
1979 case OSPF_OPAQUE_LINK_LSA:
1980 case OSPF_OPAQUE_AREA_LSA:
1981 ospf_ls_retransmit_delete_nbr_all (lsa->area, lsa);
1982 break;
1983 case OSPF_OPAQUE_AS_LSA:
1984 ospf_ls_retransmit_delete_nbr_all (NULL, lsa);
1985 break;
1986 default:
1987 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type);
1988 goto out;
1989 }
1990
1991 delay = ospf_lsa_refresh_delay (lsa);
1992
1993 if (IS_DEBUG_OSPF_EVENT)
1994 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)));
1995
1996 OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self,
1997 ospf_opaque_lsa_refresh_timer, oipi, delay);
1998out:
1999 return;
2000}
2001
2002static int
2003ospf_opaque_lsa_refresh_timer (struct thread *t)
2004{
2005 struct opaque_info_per_id *oipi;
2006 struct ospf_opaque_functab *functab;
2007 struct ospf_lsa *lsa;
2008
2009 if (IS_DEBUG_OSPF_EVENT)
2010 zlog_info ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
2011
2012 oipi = THREAD_ARG (t);
2013 oipi->t_opaque_lsa_self = NULL;
2014
2015 if ((lsa = oipi->lsa) != NULL)
2016 if ((functab = oipi->opqctl_type->functab) != NULL)
2017 if (functab->lsa_refresher != NULL)
2018 (* functab->lsa_refresher)(lsa);
2019
2020 return 0;
2021}
2022
2023void
2024ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
2025{
2026 struct opaque_info_per_type *oipt;
2027 struct opaque_info_per_id *oipi;
2028 struct ospf_lsa *lsa;
2029
2030 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
2031 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
2032 {
2033 zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2034 goto out;
2035 }
2036
2037 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2038 if ((lsa = oipi->lsa) == NULL)
2039 {
2040 zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
2041 goto out;
2042 }
2043
2044 /* Delete this lsa from neighbor retransmit-list. */
2045 switch (lsa->data->type)
2046 {
2047 case OSPF_OPAQUE_LINK_LSA:
2048 case OSPF_OPAQUE_AREA_LSA:
2049 ospf_ls_retransmit_delete_nbr_all (lsa->area, lsa);
2050 break;
2051 case OSPF_OPAQUE_AS_LSA:
2052 ospf_ls_retransmit_delete_nbr_all (NULL, lsa);
2053 break;
2054 default:
2055 zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2056 goto out;
2057 }
2058
2059 /* Dequeue listnode entry from the list. */
2060 listnode_delete (oipt->id_list, oipi);
2061
2062 /* Avoid misjudgement in the next lookup. */
2063 if (listcount (oipt->id_list) == 0)
2064 oipt->id_list->head = oipt->id_list->tail = NULL;
2065
2066 /* Disassociate internal control information with the given lsa. */
2067 oipi->lsa = NULL;
2068 free_opaque_info_per_id ((void *) oipi);
2069
2070 /* Force given lsa's age to MaxAge. */
2071 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2072
2073 if (IS_DEBUG_OSPF_EVENT)
2074 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)));
2075
2076 /* This lsa will be flushed and removed eventually. */
2077 ospf_lsa_maxage (lsa);
2078
2079out:
2080 return;
2081}
2082
2083/*------------------------------------------------------------------------*
2084 * Followings are control functions to block origination after restart.
2085 *------------------------------------------------------------------------*/
2086
2087static void ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs, struct ospf_neighbor *inbr, struct ospf_lsa *lsa);
2088static void ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi);
2089static void ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area);
2090static void ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top);
2091static unsigned long ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type);
2092
2093void
2094ospf_opaque_adjust_lsreq (struct ospf_neighbor *nbr, list lsas)
2095{
2096 struct ospf *top;
2097 struct ospf_area *area;
2098 struct ospf_interface *oi;
2099 listnode node1, node2;
2100 struct ospf_lsa *lsa;
2101
2102 if ((top = oi_to_top (nbr->oi)) == NULL)
2103 goto out;
2104
2105 /*
2106 * If an instance of self-originated Opaque-LSA is found in the given
2107 * LSA list, and it is not installed to LSDB yet, exclude it from the
2108 * list "nbr->ls_req". In this way, it is assured that an LSReq message,
2109 * which might be sent in the process of flooding, will not request for
2110 * the LSA to be flushed immediately; otherwise, depending on timing,
2111 * an LSUpd message will carry instances of target LSAs with MaxAge,
2112 * while other LSUpd message might carry old LSA instances (non-MaxAge).
2113 * Obviously, the latter would trigger miserable situations that repeat
2114 * installation and removal of unwanted LSAs indefinitely.
2115 */
2116 for (node1 = listhead (lsas); node1; nextnode (node1))
2117 {
2118 if ((lsa = getdata (node1)) == NULL)
2119 continue;
2120
2121 /* Filter out unwanted LSAs. */
2122 if (! IS_OPAQUE_LSA (lsa->data->type))
2123 continue;
2124 if (! IPV4_ADDR_SAME (&lsa->data->adv_router, &top->router_id))
2125 continue;
2126
2127 /*
2128 * Don't touch an LSA which has MaxAge; two possible cases.
2129 *
2130 * 1) This LSA has originally flushed by myself (received LSUpd
2131 * message's router-id is equal to my router-id), and flooded
2132 * back by an opaque-capable router.
2133 *
2134 * 2) This LSA has expired in an opaque-capable router and thus
2135 * flushed by the router.
2136 */
2137 if (IS_LSA_MAXAGE (lsa))
2138 continue;
2139
2140 /* If the LSA has installed in the LSDB, nothing to do here. */
2141 if (ospf_lsa_lookup_by_header (nbr->oi->area, lsa->data) != NULL)
2142 continue;
2143
2144 /* Ok, here we go. */
2145 switch (lsa->data->type)
2146 {
2147 case OSPF_OPAQUE_LINK_LSA:
2148 oi = nbr->oi;
2149 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2150 break;
2151 case OSPF_OPAQUE_AREA_LSA:
2152 area = nbr->oi->area;
2153 for (node2 = listhead (area->oiflist); node2; nextnode (node2))
2154 {
2155 if ((oi = getdata (node2)) == NULL)
2156 continue;
2157 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2158 }
2159 break;
2160 case OSPF_OPAQUE_AS_LSA:
2161 for (node2 = listhead (top->oiflist); node2; nextnode (node2))
2162 {
2163 if ((oi = getdata (node2)) == NULL)
2164 continue;
2165 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2166 }
2167 break;
2168 default:
2169 break;
2170 }
2171 }
2172
2173out:
2174 return;
2175}
2176
2177static void
2178ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs,
2179 struct ospf_neighbor *inbr,
2180 struct ospf_lsa *lsa)
2181{
2182 struct route_node *rn;
2183 struct ospf_neighbor *onbr;
2184 struct ospf_lsa *ls_req;
2185
2186 for (rn = route_top (nbrs); rn; rn = route_next (rn))
2187 {
2188 if ((onbr = rn->info) == NULL)
2189 continue;
2190 if (onbr == inbr)
2191 continue;
2192 if ((ls_req = ospf_ls_request_lookup (onbr, lsa)) == NULL)
2193 continue;
2194
2195 if (IS_DEBUG_OSPF_EVENT)
2196 zlog_info ("LSA[%s]: Exclude this entry from LSReq to send.", dump_lsa_key (lsa));
2197
2198 ospf_ls_request_delete (onbr, ls_req);
2199/* ospf_check_nbr_loading (onbr);*//* XXX */
2200 }
2201
2202 return;
2203}
2204
2205void
2206ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr, list lsas)
2207{
2208 struct ospf *top;
2209 listnode node, next;
2210 struct ospf_lsa *lsa;
2211 u_char before;
2212
2213 if ((top = oi_to_top (nbr->oi)) == NULL)
2214 goto out;
2215
2216 before = IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque);
2217
2218 for (node = listhead (lsas); node; node = next)
2219 {
2220 next = node->next;
2221
2222 if ((lsa = getdata (node)) == NULL)
2223 continue;
2224
2225 listnode_delete (lsas, lsa);
2226
2227 /*
2228 * Since these LSA entries are not yet installed into corresponding
2229 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2230 */
2231 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2232 switch (lsa->data->type)
2233 {
2234 case OSPF_OPAQUE_LINK_LSA:
2235 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
2236 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2237 break;
2238 case OSPF_OPAQUE_AREA_LSA:
2239 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
2240 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2241 break;
2242 case OSPF_OPAQUE_AS_LSA:
2243 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
2244 ospf_flood_through_as (NULL/*inbr*/, lsa);
2245 break;
2246 default:
2247 zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
2248 goto out;
2249 }
2250
2251 ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */
2252 }
2253
2254 if (before == 0 && IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2255 {
2256 if (IS_DEBUG_OSPF_EVENT)
2257 zlog_info ("Block Opaque-LSA origination: OFF -> ON");
2258 }
2259
2260out:
2261 return;
2262}
2263
2264void
2265ospf_opaque_ls_ack_received (struct ospf_neighbor *nbr, list acks)
2266{
2267 struct ospf *top;
2268 listnode node;
2269 struct ospf_lsa *lsa;
2270 char type9_lsa_rcv = 0, type10_lsa_rcv = 0, type11_lsa_rcv = 0;
2271
2272 if ((top = oi_to_top (nbr->oi)) == NULL)
2273 goto out;
2274
2275 for (node = listhead (acks); node; nextnode (node))
2276 {
2277 if ((lsa = getdata (node)) == NULL)
2278 continue;
2279
2280 switch (lsa->data->type)
2281 {
2282 case OSPF_OPAQUE_LINK_LSA:
2283 type9_lsa_rcv = 1;
2284 /* Callback function... */
2285 break;
2286 case OSPF_OPAQUE_AREA_LSA:
2287 type10_lsa_rcv = 1;
2288 /* Callback function... */
2289 break;
2290 case OSPF_OPAQUE_AS_LSA:
2291 type11_lsa_rcv = 1;
2292 /* Callback function... */
2293 break;
2294 default:
2295 zlog_warn ("ospf_opaque_ls_ack_received: Unexpected LSA-type(%u)", lsa->data->type);
2296 goto out;
2297 }
2298 }
2299
2300 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2301 {
2302 int delay;
2303 struct ospf_interface *oi;
2304
2305 if (type9_lsa_rcv
2306 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT))
2307 ospf_opaque_type9_lsa_rxmt_nbr_check (nbr->oi);
2308
2309 if (type10_lsa_rcv
2310 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT))
2311 ospf_opaque_type10_lsa_rxmt_nbr_check (nbr->oi->area);
2312
2313 if (type11_lsa_rcv
2314 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT))
2315 ospf_opaque_type11_lsa_rxmt_nbr_check (top);
2316
2317 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2318 goto out; /* Blocking still in progress. */
2319
2320 if (IS_DEBUG_OSPF_EVENT)
2321 zlog_info ("Block Opaque-LSA origination: ON -> OFF");
2322
2323 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
2324 goto out; /* Opaque capability condition must have changed. */
2325
2326 /* Ok, let's start origination of Opaque-LSAs. */
2327 delay = OSPF_MIN_LS_INTERVAL;
2328 for (node = listhead (top->oiflist); node; nextnode (node))
2329 {
2330 if ((oi = getdata (node)) == NULL)
2331 continue;
2332
2333 if (! ospf_if_is_enable (oi)
2334 || ospf_opaque_capable_nbr_count (oi->nbrs, NSM_Full) == 0)
2335 continue;
2336
2337 ospf_opaque_lsa_originate_schedule (oi, &delay);
2338 }
2339 }
2340
2341out:
2342 return;
2343}
2344
2345static void
2346ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi)
2347{
2348 unsigned long n;
2349
2350 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_LINK_LSA);
2351 if (n == 0)
2352 {
2353 if (IS_DEBUG_OSPF_EVENT)
2354 zlog_info ("Self-originated type-9 Opaque-LSAs: OI(%s): Flush completed", IF_NAME (oi));
2355
2356 UNSET_FLAG (oi->area->top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
2357 }
2358 return;
2359}
2360
2361static void
2362ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area)
2363{
2364 listnode node;
2365 struct ospf_interface *oi;
2366 unsigned long n = 0;
2367
2368 for (node = listhead (area->oiflist); node; nextnode (node))
2369 {
2370 if ((oi = getdata (node)) == NULL)
2371 continue;
2372
2373 if (area->area_id.s_addr != OSPF_AREA_BACKBONE
2374 && oi->type == OSPF_IFTYPE_VIRTUALLINK)
2375 continue;
2376
2377 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AREA_LSA);
2378 if (n > 0)
2379 break;
2380 }
2381
2382 if (n == 0)
2383 {
2384 if (IS_DEBUG_OSPF_EVENT)
2385 zlog_info ("Self-originated type-10 Opaque-LSAs: AREA(%s): Flush completed", inet_ntoa (area->area_id));
2386
2387 UNSET_FLAG (area->top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
2388 }
2389
2390 return;
2391}
2392
2393static void
2394ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top)
2395{
2396 listnode node;
2397 struct ospf_interface *oi;
2398 unsigned long n = 0;
2399
2400 for (node = listhead (top->oiflist); node; nextnode (node))
2401 {
2402 if ((oi = getdata (node)) == NULL)
2403 continue;
2404
2405 switch (oi->type)
2406 {
2407 case OSPF_IFTYPE_VIRTUALLINK:
2408 continue;
2409 default:
2410 break;
2411 }
2412
2413 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AS_LSA);
2414 if (n > 0)
2415 goto out;
2416 }
2417
2418 if (n == 0)
2419 {
2420 if (IS_DEBUG_OSPF_EVENT)
2421 zlog_info ("Self-originated type-11 Opaque-LSAs: Flush completed");
2422
2423 UNSET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
2424 }
2425
2426out:
2427 return;
2428}
2429
2430static unsigned long
2431ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type)
2432{
2433 struct route_node *rn;
2434 struct ospf_neighbor *nbr;
2435 struct ospf *top;
2436 unsigned long n = 0;
2437
2438 for (rn = route_top (nbrs); rn; rn = route_next (rn))
2439 {
2440 if ((nbr = rn->info) == NULL)
2441 continue;
2442 if ((top = oi_to_top (nbr->oi)) == NULL)
2443 continue;
2444 if (IPV4_ADDR_SAME (&nbr->router_id, &top->router_id))
2445 continue;
2446 n += ospf_ls_retransmit_count_self (nbr, lsa_type);
2447 }
2448
2449 return n;
2450}
2451
2452/*------------------------------------------------------------------------*
2453 * Followings are util functions; probably be used by Opaque-LSAs only...
2454 *------------------------------------------------------------------------*/
2455
2456void
2457htonf (float *src, float *dst)
2458{
2459 u_int32_t lu1, lu2;
2460
2461 memcpy (&lu1, src, sizeof (u_int32_t));
2462 lu2 = htonl (lu1);
2463 memcpy (dst, &lu2, sizeof (u_int32_t));
2464 return;
2465}
2466
2467void
2468ntohf (float *src, float *dst)
2469{
2470 u_int32_t lu1, lu2;
2471
2472 memcpy (&lu1, src, sizeof (u_int32_t));
2473 lu2 = ntohl (lu1);
2474 memcpy (dst, &lu2, sizeof (u_int32_t));
2475 return;
2476}
2477
2478struct ospf *
2479oi_to_top (struct ospf_interface *oi)
2480{
2481 struct ospf *top = NULL;
2482 struct ospf_area *area;
2483
2484 if (oi == NULL || (area = oi->area) == NULL || (top = area->top) == NULL)
2485 zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");
2486
2487 return top;
2488}
2489
2490#endif /* HAVE_OPAQUE_LSA */