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