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