blob: ecb28ffe3d8efd4703f20ee20848c6748904d0b0 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
2 * This is an implementation of rfc2370.
3 * Copyright (C) 2001 KDD R&D Laboratories, Inc.
4 * http://www.kddlabs.co.jp/
5 *
6 * This file is part of GNU Zebra.
7 *
8 * GNU Zebra is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
11 * later version.
12 *
13 * GNU Zebra is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with GNU Zebra; see the file COPYING. If not, write to the Free
20 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 * 02111-1307, USA.
22 */
23
24/***** MTYPE definitions are not reflected to "memory.h" yet. *****/
25#define MTYPE_OSPF_OPAQUE_FUNCTAB 0
26#define MTYPE_OPAQUE_INFO_PER_TYPE 0
27#define MTYPE_OPAQUE_INFO_PER_ID 0
28
29#include <zebra.h>
30#ifdef HAVE_OPAQUE_LSA
31
32#include "linklist.h"
33#include "prefix.h"
34#include "if.h"
35#include "table.h"
36#include "memory.h"
37#include "command.h"
38#include "vty.h"
39#include "stream.h"
40#include "log.h"
41#include "thread.h"
42#include "hash.h"
43#include "sockunion.h" /* for inet_aton() */
44
45#include "ospfd/ospfd.h"
46#include "ospfd/ospf_interface.h"
47#include "ospfd/ospf_ism.h"
48#include "ospfd/ospf_asbr.h"
49#include "ospfd/ospf_lsa.h"
50#include "ospfd/ospf_lsdb.h"
51#include "ospfd/ospf_neighbor.h"
52#include "ospfd/ospf_nsm.h"
53#include "ospfd/ospf_flood.h"
54#include "ospfd/ospf_packet.h"
55#include "ospfd/ospf_spf.h"
56#include "ospfd/ospf_dump.h"
57#include "ospfd/ospf_route.h"
58#include "ospfd/ospf_ase.h"
59#include "ospfd/ospf_zebra.h"
60
61/*------------------------------------------------------------------------*
62 * Followings are initialize/terminate functions for Opaque-LSAs handling.
63 *------------------------------------------------------------------------*/
64
65#ifdef HAVE_OSPF_TE
66#include "ospfd/ospf_te.h"
67#endif /* HAVE_OSPF_TE */
68
paul283ae332003-03-17 01:16:55 +000069#ifdef SUPPORT_OSPF_API
70int ospf_apiserver_init (void);
71void ospf_apiserver_term (void);
hassof4d58ce2004-10-12 06:13:54 +000072/* Init apiserver? It's disabled by default. */
73int ospf_apiserver_enable;
paul283ae332003-03-17 01:16:55 +000074#endif /* SUPPORT_OSPF_API */
75
paul718e3742002-12-13 20:15:29 +000076static void ospf_opaque_register_vty (void);
77static void ospf_opaque_funclist_init (void);
78static void ospf_opaque_funclist_term (void);
79static void free_opaque_info_per_type (void *val);
80static void free_opaque_info_per_id (void *val);
81static int ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa);
82static int ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa);
83
84void
85ospf_opaque_init (void)
86{
87 ospf_opaque_register_vty ();
88 ospf_opaque_funclist_init ();
89
90#ifdef HAVE_OSPF_TE
91 if (ospf_mpls_te_init () != 0)
92 exit (1);
93#endif /* HAVE_OSPF_TE */
94
paul283ae332003-03-17 01:16:55 +000095#ifdef SUPPORT_OSPF_API
hassoc3abdb72004-10-11 16:27:03 +000096 if ((ospf_apiserver_enable) && (ospf_apiserver_init () != 0))
paul283ae332003-03-17 01:16:55 +000097 exit (1);
98#endif /* SUPPORT_OSPF_API */
99
paul718e3742002-12-13 20:15:29 +0000100 return;
101}
102
103void
104ospf_opaque_term (void)
105{
106#ifdef HAVE_OSPF_TE
107 ospf_mpls_te_term ();
108#endif /* HAVE_OSPF_TE */
109
paul283ae332003-03-17 01:16:55 +0000110#ifdef SUPPORT_OSPF_API
111 ospf_apiserver_term ();
112#endif /* SUPPORT_OSPF_API */
113
paul718e3742002-12-13 20:15:29 +0000114 ospf_opaque_funclist_term ();
115 return;
116}
117
118int
119ospf_opaque_type9_lsa_init (struct ospf_interface *oi)
120{
121 if (oi->opaque_lsa_self != NULL)
122 list_delete (oi->opaque_lsa_self);
123
124 oi->opaque_lsa_self = list_new ();
125 oi->opaque_lsa_self->del = free_opaque_info_per_type;
126 oi->t_opaque_lsa_self = NULL;
127 return 0;
128}
129
130void
131ospf_opaque_type9_lsa_term (struct ospf_interface *oi)
132{
133 OSPF_TIMER_OFF (oi->t_opaque_lsa_self);
134 if (oi->opaque_lsa_self != NULL)
135 list_delete (oi->opaque_lsa_self);
136 oi->opaque_lsa_self = NULL;
137 return;
138}
139
140int
141ospf_opaque_type10_lsa_init (struct ospf_area *area)
142{
143 if (area->opaque_lsa_self != NULL)
144 list_delete (area->opaque_lsa_self);
145
146 area->opaque_lsa_self = list_new ();
147 area->opaque_lsa_self->del = free_opaque_info_per_type;
148 area->t_opaque_lsa_self = NULL;
149
150#ifdef MONITOR_LSDB_CHANGE
151 area->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
152 area->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
153#endif /* MONITOR_LSDB_CHANGE */
154 return 0;
155}
156
157void
158ospf_opaque_type10_lsa_term (struct ospf_area *area)
159{
160#ifdef MONITOR_LSDB_CHANGE
161 area->lsdb->new_lsa_hook =
162 area->lsdb->del_lsa_hook = NULL;
163#endif /* MONITOR_LSDB_CHANGE */
164
165 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
166 if (area->opaque_lsa_self != NULL)
167 list_delete (area->opaque_lsa_self);
168 area->opaque_lsa_self = NULL;
169 return;
170}
171
172int
173ospf_opaque_type11_lsa_init (struct ospf *top)
174{
175 if (top->opaque_lsa_self != NULL)
176 list_delete (top->opaque_lsa_self);
177
178 top->opaque_lsa_self = list_new ();
179 top->opaque_lsa_self->del = free_opaque_info_per_type;
180 top->t_opaque_lsa_self = NULL;
181
182#ifdef MONITOR_LSDB_CHANGE
183 top->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
184 top->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
185#endif /* MONITOR_LSDB_CHANGE */
186 return 0;
187}
188
189void
190ospf_opaque_type11_lsa_term (struct ospf *top)
191{
192#ifdef MONITOR_LSDB_CHANGE
193 top->lsdb->new_lsa_hook =
194 top->lsdb->del_lsa_hook = NULL;
195#endif /* MONITOR_LSDB_CHANGE */
196
197 OSPF_TIMER_OFF (top->t_opaque_lsa_self);
198 if (top->opaque_lsa_self != NULL)
199 list_delete (top->opaque_lsa_self);
200 top->opaque_lsa_self = NULL;
201 return;
202}
203
204static const char *
205ospf_opaque_type_name (u_char opaque_type)
206{
207 const char *name = "Unknown";
208
209 switch (opaque_type)
210 {
211 case OPAQUE_TYPE_WILDCARD: /* This is a special assignment! */
212 name = "Wildcard";
213 break;
214 case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA:
215 name = "Traffic Engineering LSA";
216 break;
217 case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC:
218 name = "Sycamore optical topology description";
219 break;
220 case OPAQUE_TYPE_GRACE_LSA:
221 name = "Grace-LSA";
222 break;
223 default:
224 if (OPAQUE_TYPE_RANGE_UNASSIGNED (opaque_type))
225 name = "Unassigned";
Andrew Certain0798cee2012-12-04 13:43:42 -0800226 else
227 {
228 u_int32_t bigger_range = opaque_type;
229 /*
230 * Get around type-limits warning: comparison is always true due to limited range of data type
231 */
232 if (OPAQUE_TYPE_RANGE_RESERVED (bigger_range))
233 name = "Private/Experimental";
234 }
paul718e3742002-12-13 20:15:29 +0000235 break;
236 }
237 return name;
238}
239
240/*------------------------------------------------------------------------*
241 * Followings are management functions to store user specified callbacks.
242 *------------------------------------------------------------------------*/
243
244struct opaque_info_per_type; /* Forward declaration. */
245
246struct ospf_opaque_functab
247{
248 u_char opaque_type;
249 struct opaque_info_per_type *oipt;
250
251 int (* new_if_hook)(struct interface *ifp);
252 int (* del_if_hook)(struct interface *ifp);
253 void (* ism_change_hook)(struct ospf_interface *oi, int old_status);
254 void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status);
255 void (* config_write_router)(struct vty *vty);
256 void (* config_write_if )(struct vty *vty, struct interface *ifp);
257 void (* config_write_debug )(struct vty *vty);
258 void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa);
259 int (* lsa_originator)(void *arg);
Paul Jakmad71ea652011-03-22 15:23:55 +0000260 struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa);
paul718e3742002-12-13 20:15:29 +0000261 int (* new_lsa_hook)(struct ospf_lsa *lsa);
262 int (* del_lsa_hook)(struct ospf_lsa *lsa);
263};
264
paul87d6f872004-09-24 08:01:38 +0000265/* Handle LSA-9/10/11 altogether. */
266static struct list *ospf_opaque_wildcard_funclist;
267static struct list *ospf_opaque_type9_funclist;
268static struct list *ospf_opaque_type10_funclist;
269static struct list *ospf_opaque_type11_funclist;
paul718e3742002-12-13 20:15:29 +0000270
271static void
272ospf_opaque_del_functab (void *val)
273{
274 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, val);
275 return;
276}
277
278static void
279ospf_opaque_funclist_init (void)
280{
paul87d6f872004-09-24 08:01:38 +0000281 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000282
paul09e4efd2003-01-18 00:12:02 +0000283 funclist = ospf_opaque_wildcard_funclist = list_new ();
284 funclist->del = ospf_opaque_del_functab;
285
paul718e3742002-12-13 20:15:29 +0000286 funclist = ospf_opaque_type9_funclist = list_new ();
287 funclist->del = ospf_opaque_del_functab;
288
289 funclist = ospf_opaque_type10_funclist = list_new ();
290 funclist->del = ospf_opaque_del_functab;
291
292 funclist = ospf_opaque_type11_funclist = list_new ();
293 funclist->del = ospf_opaque_del_functab;
294 return;
295}
296
297static void
298ospf_opaque_funclist_term (void)
299{
paul87d6f872004-09-24 08:01:38 +0000300 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000301
paul09e4efd2003-01-18 00:12:02 +0000302 funclist = ospf_opaque_wildcard_funclist;
303 list_delete (funclist);
304
paul718e3742002-12-13 20:15:29 +0000305 funclist = ospf_opaque_type9_funclist;
306 list_delete (funclist);
307
308 funclist = ospf_opaque_type10_funclist;
309 list_delete (funclist);
310
311 funclist = ospf_opaque_type11_funclist;
312 list_delete (funclist);
313 return;
314}
315
paul87d6f872004-09-24 08:01:38 +0000316static struct list *
paul718e3742002-12-13 20:15:29 +0000317ospf_get_opaque_funclist (u_char lsa_type)
318{
paul87d6f872004-09-24 08:01:38 +0000319 struct list *funclist = NULL;
paul718e3742002-12-13 20:15:29 +0000320
321 switch (lsa_type)
322 {
paul09e4efd2003-01-18 00:12:02 +0000323 case OPAQUE_TYPE_WILDCARD:
324 /* XXX
325 * This is an ugly trick to handle type-9/10/11 LSA altogether.
326 * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor
327 * an officially assigned opaque-type.
328 * Though it is possible that the value might be officially used
329 * in the future, we use it internally as a special label, for now.
330 */
331 funclist = ospf_opaque_wildcard_funclist;
332 break;
paul718e3742002-12-13 20:15:29 +0000333 case OSPF_OPAQUE_LINK_LSA:
334 funclist = ospf_opaque_type9_funclist;
335 break;
336 case OSPF_OPAQUE_AREA_LSA:
337 funclist = ospf_opaque_type10_funclist;
338 break;
339 case OSPF_OPAQUE_AS_LSA:
340 funclist = ospf_opaque_type11_funclist;
341 break;
342 default:
343 zlog_warn ("ospf_get_opaque_funclist: Unexpected LSA-type(%u)", lsa_type);
344 break;
345 }
346 return funclist;
347}
348
paul87d6f872004-09-24 08:01:38 +0000349/* XXX: such a huge argument list can /not/ be healthy... */
paul718e3742002-12-13 20:15:29 +0000350int
351ospf_register_opaque_functab (
352 u_char lsa_type,
353 u_char opaque_type,
354 int (* new_if_hook)(struct interface *ifp),
355 int (* del_if_hook)(struct interface *ifp),
356 void (* ism_change_hook)(struct ospf_interface *oi, int old_status),
357 void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status),
358 void (* config_write_router)(struct vty *vty),
359 void (* config_write_if )(struct vty *vty, struct interface *ifp),
360 void (* config_write_debug )(struct vty *vty),
361 void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa),
362 int (* lsa_originator)(void *arg),
Paul Jakmad71ea652011-03-22 15:23:55 +0000363 struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa),
paul718e3742002-12-13 20:15:29 +0000364 int (* new_lsa_hook)(struct ospf_lsa *lsa),
365 int (* del_lsa_hook)(struct ospf_lsa *lsa))
366{
paul87d6f872004-09-24 08:01:38 +0000367 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000368 struct ospf_opaque_functab *new;
369 int rc = -1;
370
371 if ((funclist = ospf_get_opaque_funclist (lsa_type)) == NULL)
372 {
paul87d6f872004-09-24 08:01:38 +0000373 zlog_warn ("ospf_register_opaque_functab: Cannot get funclist"
374 " for Type-%u LSAs?",
375 lsa_type);
paul718e3742002-12-13 20:15:29 +0000376 goto out;
377 }
378 else
379 {
paul1eb8ef22005-04-07 07:30:20 +0000380 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000381 struct ospf_opaque_functab *functab;
paul87d6f872004-09-24 08:01:38 +0000382
paul1eb8ef22005-04-07 07:30:20 +0000383 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000384 if (functab->opaque_type == opaque_type)
385 {
386 zlog_warn ("ospf_register_opaque_functab: Duplicated entry?:"
387 " lsa_type(%u), opaque_type(%u)",
388 lsa_type, opaque_type);
389 goto out;
390 }
paul718e3742002-12-13 20:15:29 +0000391 }
392
393 if ((new = XCALLOC (MTYPE_OSPF_OPAQUE_FUNCTAB,
394 sizeof (struct ospf_opaque_functab))) == NULL)
395 {
paul87d6f872004-09-24 08:01:38 +0000396 zlog_warn ("ospf_register_opaque_functab: XMALLOC: %s",
ajs6099b3b2004-11-20 02:06:59 +0000397 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000398 goto out;
399 }
400
401 new->opaque_type = opaque_type;
402 new->oipt = NULL;
403 new->new_if_hook = new_if_hook;
404 new->del_if_hook = del_if_hook;
405 new->ism_change_hook = ism_change_hook;
406 new->nsm_change_hook = nsm_change_hook;
407 new->config_write_router = config_write_router;
408 new->config_write_if = config_write_if;
409 new->config_write_debug = config_write_debug;
410 new->show_opaque_info = show_opaque_info;
411 new->lsa_originator = lsa_originator;
412 new->lsa_refresher = lsa_refresher;
413 new->new_lsa_hook = new_lsa_hook;
414 new->del_lsa_hook = del_lsa_hook;
415
416 listnode_add (funclist, new);
417 rc = 0;
418
419out:
420 return rc;
421}
422
423void
424ospf_delete_opaque_functab (u_char lsa_type, u_char opaque_type)
425{
paul87d6f872004-09-24 08:01:38 +0000426 struct list *funclist;
paul1eb8ef22005-04-07 07:30:20 +0000427 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000428 struct ospf_opaque_functab *functab;
429
430 if ((funclist = ospf_get_opaque_funclist (lsa_type)) != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000431 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul718e3742002-12-13 20:15:29 +0000432 {
paul1eb8ef22005-04-07 07:30:20 +0000433 if (functab->opaque_type == opaque_type)
paul718e3742002-12-13 20:15:29 +0000434 {
435 /* Cleanup internal control information, if it still remains. */
436 if (functab->oipt != NULL)
437 free_opaque_info_per_type (functab->oipt);
438
439 /* Dequeue listnode entry from the list. */
440 listnode_delete (funclist, functab);
441
442 /* Avoid misjudgement in the next lookup. */
443 if (listcount (funclist) == 0)
444 funclist->head = funclist->tail = NULL;
445
446 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, functab);
paul87d6f872004-09-24 08:01:38 +0000447 break;
paul718e3742002-12-13 20:15:29 +0000448 }
449 }
paul87d6f872004-09-24 08:01:38 +0000450
paul718e3742002-12-13 20:15:29 +0000451 return;
452}
453
454static struct ospf_opaque_functab *
455ospf_opaque_functab_lookup (struct ospf_lsa *lsa)
456{
paul87d6f872004-09-24 08:01:38 +0000457 struct list *funclist;
458 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000459 struct ospf_opaque_functab *functab;
460 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
461
462 if ((funclist = ospf_get_opaque_funclist (lsa->data->type)) != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000463 for (ALL_LIST_ELEMENTS_RO (funclist, node, functab))
paul87d6f872004-09-24 08:01:38 +0000464 if (functab->opaque_type == key)
465 return functab;
paul718e3742002-12-13 20:15:29 +0000466
467 return NULL;
468}
469
470/*------------------------------------------------------------------------*
471 * Followings are management functions for self-originated LSA entries.
472 *------------------------------------------------------------------------*/
473
474/*
475 * Opaque-LSA control information per opaque-type.
476 * Single Opaque-Type may have multiple instances; each of them will be
477 * identified by their opaque-id.
478 */
479struct opaque_info_per_type
480{
paul09e4efd2003-01-18 00:12:02 +0000481 u_char lsa_type;
paul718e3742002-12-13 20:15:29 +0000482 u_char opaque_type;
483
484 enum { PROC_NORMAL, PROC_SUSPEND } status;
485
486 /*
487 * Thread for (re-)origination scheduling for this opaque-type.
488 *
489 * Initial origination of Opaque-LSAs is controlled by generic
490 * Opaque-LSA handling module so that same opaque-type entries are
491 * called all at once when certain conditions are met.
492 * However, there might be cases that some Opaque-LSA clients need
493 * to (re-)originate their own Opaque-LSAs out-of-sync with others.
494 * This thread is prepared for that specific purpose.
495 */
496 struct thread *t_opaque_lsa_self;
497
498 /*
paul09e4efd2003-01-18 00:12:02 +0000499 * Backpointer to an "owner" which is LSA-type dependent.
paul718e3742002-12-13 20:15:29 +0000500 * type-9: struct ospf_interface
501 * type-10: struct ospf_area
502 * type-11: struct ospf
503 */
504 void *owner;
505
506 /* Collection of callback functions for this opaque-type. */
507 struct ospf_opaque_functab *functab;
508
509 /* List of Opaque-LSA control informations per opaque-id. */
paul87d6f872004-09-24 08:01:38 +0000510 struct list *id_list;
paul718e3742002-12-13 20:15:29 +0000511};
512
513/* Opaque-LSA control information per opaque-id. */
514struct opaque_info_per_id
515{
516 u_int32_t opaque_id;
517
518 /* Thread for refresh/flush scheduling for this opaque-type/id. */
519 struct thread *t_opaque_lsa_self;
520
521 /* Backpointer to Opaque-LSA control information per opaque-type. */
522 struct opaque_info_per_type *opqctl_type;
523
524 /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
525 struct ospf_lsa *lsa;
526};
527
528static struct opaque_info_per_type *register_opaque_info_per_type (struct ospf_opaque_functab *functab, struct ospf_lsa *new);
529static struct opaque_info_per_type *lookup_opaque_info_by_type (struct ospf_lsa *lsa);
530static struct opaque_info_per_id *register_opaque_info_per_id (struct opaque_info_per_type *oipt, struct ospf_lsa *new);
531static struct opaque_info_per_id *lookup_opaque_info_by_id (struct opaque_info_per_type *oipt, struct ospf_lsa *lsa);
532static struct opaque_info_per_id *register_opaque_lsa (struct ospf_lsa *new);
533
534
535static struct opaque_info_per_type *
536register_opaque_info_per_type (struct ospf_opaque_functab *functab,
537 struct ospf_lsa *new)
538{
539 struct ospf *top;
540 struct opaque_info_per_type *oipt;
541
542 if ((oipt = XCALLOC (MTYPE_OPAQUE_INFO_PER_TYPE,
543 sizeof (struct opaque_info_per_type))) == NULL)
544 {
ajs6099b3b2004-11-20 02:06:59 +0000545 zlog_warn ("register_opaque_info_per_type: XMALLOC: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000546 goto out;
547 }
548
549 switch (new->data->type)
550 {
551 case OSPF_OPAQUE_LINK_LSA:
552 oipt->owner = new->oi;
553 listnode_add (new->oi->opaque_lsa_self, oipt);
554 break;
555 case OSPF_OPAQUE_AREA_LSA:
556 oipt->owner = new->area;
557 listnode_add (new->area->opaque_lsa_self, oipt);
558 break;
559 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +0000560 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000561 if (new->area != NULL && (top = new->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +0000562 {
563 free_opaque_info_per_type ((void *) oipt);
564 oipt = NULL;
565 goto out; /* This case may not exist. */
566 }
567 oipt->owner = top;
568 listnode_add (top->opaque_lsa_self, oipt);
569 break;
570 default:
paul09e4efd2003-01-18 00:12:02 +0000571 zlog_warn ("register_opaque_info_per_type: Unexpected LSA-type(%u)", new->data->type);
paul718e3742002-12-13 20:15:29 +0000572 free_opaque_info_per_type ((void *) oipt);
573 oipt = NULL;
574 goto out; /* This case may not exist. */
575 }
576
paul09e4efd2003-01-18 00:12:02 +0000577 oipt->lsa_type = new->data->type;
paul718e3742002-12-13 20:15:29 +0000578 oipt->opaque_type = GET_OPAQUE_TYPE (ntohl (new->data->id.s_addr));
579 oipt->status = PROC_NORMAL;
580 oipt->t_opaque_lsa_self = NULL;
581 oipt->functab = functab;
582 functab->oipt = oipt;
583 oipt->id_list = list_new ();
584 oipt->id_list->del = free_opaque_info_per_id;
585
586out:
587 return oipt;
588}
589
590static void
591free_opaque_info_per_type (void *val)
592{
593 struct opaque_info_per_type *oipt = (struct opaque_info_per_type *) val;
594 struct opaque_info_per_id *oipi;
595 struct ospf_lsa *lsa;
paul1eb8ef22005-04-07 07:30:20 +0000596 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000597
598 /* Control information per opaque-id may still exist. */
paul1eb8ef22005-04-07 07:30:20 +0000599 for (ALL_LIST_ELEMENTS (oipt->id_list, node, nnode, oipi))
paul718e3742002-12-13 20:15:29 +0000600 {
paul718e3742002-12-13 20:15:29 +0000601 if ((lsa = oipi->lsa) == NULL)
602 continue;
603 if (IS_LSA_MAXAGE (lsa))
604 continue;
605 ospf_opaque_lsa_flush_schedule (lsa);
606 }
607
paul09e4efd2003-01-18 00:12:02 +0000608 /* Remove "oipt" from its owner's self-originated LSA list. */
609 switch (oipt->lsa_type)
610 {
611 case OSPF_OPAQUE_LINK_LSA:
612 {
613 struct ospf_interface *oi = (struct ospf_interface *)(oipt->owner);
614 listnode_delete (oi->opaque_lsa_self, oipt);
615 break;
616 }
617 case OSPF_OPAQUE_AREA_LSA:
618 {
619 struct ospf_area *area = (struct ospf_area *)(oipt->owner);
620 listnode_delete (area->opaque_lsa_self, oipt);
621 break;
622 }
623 case OSPF_OPAQUE_AS_LSA:
624 {
625 struct ospf *top = (struct ospf *)(oipt->owner);
626 listnode_delete (top->opaque_lsa_self, oipt);
627 break;
628 }
629 default:
630 zlog_warn ("free_opaque_info_per_type: Unexpected LSA-type(%u)", oipt->lsa_type);
631 break; /* This case may not exist. */
632 }
633
paul718e3742002-12-13 20:15:29 +0000634 OSPF_TIMER_OFF (oipt->t_opaque_lsa_self);
635 list_delete (oipt->id_list);
636 XFREE (MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
637 return;
638}
639
640static struct opaque_info_per_type *
641lookup_opaque_info_by_type (struct ospf_lsa *lsa)
642{
643 struct ospf *top;
644 struct ospf_area *area;
645 struct ospf_interface *oi;
paul87d6f872004-09-24 08:01:38 +0000646 struct list *listtop = NULL;
paul1eb8ef22005-04-07 07:30:20 +0000647 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000648 struct opaque_info_per_type *oipt = NULL;
649 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
650
651 switch (lsa->data->type)
652 {
653 case OSPF_OPAQUE_LINK_LSA:
654 if ((oi = lsa->oi) != NULL)
655 listtop = oi->opaque_lsa_self;
656 else
657 zlog_warn ("Type-9 Opaque-LSA: Reference to OI is missing?");
658 break;
659 case OSPF_OPAQUE_AREA_LSA:
660 if ((area = lsa->area) != NULL)
661 listtop = area->opaque_lsa_self;
662 else
663 zlog_warn ("Type-10 Opaque-LSA: Reference to AREA is missing?");
664 break;
665 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +0000666 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000667 if ((area = lsa->area) != NULL && (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +0000668 {
669 zlog_warn ("Type-11 Opaque-LSA: Reference to OSPF is missing?");
670 break; /* Unlikely to happen. */
671 }
672 listtop = top->opaque_lsa_self;
673 break;
674 default:
675 zlog_warn ("lookup_opaque_info_by_type: Unexpected LSA-type(%u)", lsa->data->type);
676 break;
677 }
678
679 if (listtop != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000680 for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt))
paul87d6f872004-09-24 08:01:38 +0000681 if (oipt->opaque_type == key)
682 return oipt;
paul718e3742002-12-13 20:15:29 +0000683
684 return NULL;
685}
686
687static struct opaque_info_per_id *
688register_opaque_info_per_id (struct opaque_info_per_type *oipt,
689 struct ospf_lsa *new)
690{
691 struct opaque_info_per_id *oipi;
692
693 if ((oipi = XCALLOC (MTYPE_OPAQUE_INFO_PER_ID,
694 sizeof (struct opaque_info_per_id))) == NULL)
695 {
ajs6099b3b2004-11-20 02:06:59 +0000696 zlog_warn ("register_opaque_info_per_id: XMALLOC: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000697 goto out;
698 }
699 oipi->opaque_id = GET_OPAQUE_ID (ntohl (new->data->id.s_addr));
700 oipi->t_opaque_lsa_self = NULL;
701 oipi->opqctl_type = oipt;
702 oipi->lsa = ospf_lsa_lock (new);
703
704 listnode_add (oipt->id_list, oipi);
705
706out:
707 return oipi;
708}
709
710static void
711free_opaque_info_per_id (void *val)
712{
713 struct opaque_info_per_id *oipi = (struct opaque_info_per_id *) val;
714
715 OSPF_TIMER_OFF (oipi->t_opaque_lsa_self);
716 if (oipi->lsa != NULL)
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000717 ospf_lsa_unlock (&oipi->lsa);
paul718e3742002-12-13 20:15:29 +0000718 XFREE (MTYPE_OPAQUE_INFO_PER_ID, oipi);
719 return;
720}
721
722static struct opaque_info_per_id *
723lookup_opaque_info_by_id (struct opaque_info_per_type *oipt,
724 struct ospf_lsa *lsa)
725{
paul1eb8ef22005-04-07 07:30:20 +0000726 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000727 struct opaque_info_per_id *oipi;
728 u_int32_t key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
729
paul1eb8ef22005-04-07 07:30:20 +0000730 for (ALL_LIST_ELEMENTS (oipt->id_list, node, nnode, oipi))
paul87d6f872004-09-24 08:01:38 +0000731 if (oipi->opaque_id == key)
732 return oipi;
paul718e3742002-12-13 20:15:29 +0000733
734 return NULL;
735}
736
737static struct opaque_info_per_id *
738register_opaque_lsa (struct ospf_lsa *new)
739{
740 struct ospf_opaque_functab *functab;
741 struct opaque_info_per_type *oipt;
742 struct opaque_info_per_id *oipi = NULL;
743
744 if ((functab = ospf_opaque_functab_lookup (new)) == NULL)
745 goto out;
746
747 if ((oipt = lookup_opaque_info_by_type (new)) == NULL
748 && (oipt = register_opaque_info_per_type (functab, new)) == NULL)
749 goto out;
750
751 if ((oipi = register_opaque_info_per_id (oipt, new)) == NULL)
752 goto out;
753
754out:
755 return oipi;
756}
757
758/*------------------------------------------------------------------------*
759 * Followings are (vty) configuration functions for Opaque-LSAs handling.
760 *------------------------------------------------------------------------*/
761
762DEFUN (capability_opaque,
763 capability_opaque_cmd,
764 "capability opaque",
765 "Enable specific OSPF feature\n"
766 "Opaque LSA\n")
767{
768 struct ospf *ospf = (struct ospf *) vty->index;
769
770 /* Turn on the "master switch" of opaque-lsa capability. */
771 if (!CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
772 {
773 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000774 zlog_debug ("Opaque capability: OFF -> ON");
paul718e3742002-12-13 20:15:29 +0000775
776 SET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
777 ospf_renegotiate_optional_capabilities (ospf);
778 }
779 return CMD_SUCCESS;
780}
781
782ALIAS (capability_opaque,
783 ospf_opaque_capable_cmd,
784 "ospf opaque-lsa",
785 "OSPF specific commands\n"
786 "Enable the Opaque-LSA capability (rfc2370)\n")
787
788DEFUN (no_capability_opaque,
789 no_capability_opaque_cmd,
790 "no capability opaque",
791 NO_STR
792 "Enable specific OSPF feature\n"
793 "Opaque LSA\n")
794{
795 struct ospf *ospf = (struct ospf *) vty->index;
796
797 /* Turn off the "master switch" of opaque-lsa capability. */
798 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
799 {
800 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000801 zlog_debug ("Opaque capability: ON -> OFF");
paul718e3742002-12-13 20:15:29 +0000802
803 UNSET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
804 ospf_renegotiate_optional_capabilities (ospf);
805 }
806 return CMD_SUCCESS;
807}
808
809ALIAS (no_capability_opaque,
810 no_ospf_opaque_capable_cmd,
811 "no ospf opaque-lsa",
812 NO_STR
813 "OSPF specific commands\n"
814 "Disable the Opaque-LSA capability (rfc2370)\n")
815
816static void
817ospf_opaque_register_vty (void)
818{
819 install_element (OSPF_NODE, &capability_opaque_cmd);
820 install_element (OSPF_NODE, &no_capability_opaque_cmd);
821 install_element (OSPF_NODE, &ospf_opaque_capable_cmd);
822 install_element (OSPF_NODE, &no_ospf_opaque_capable_cmd);
823 return;
824}
825
826/*------------------------------------------------------------------------*
827 * Followings are collection of user-registered function callers.
828 *------------------------------------------------------------------------*/
829
830static int
paul87d6f872004-09-24 08:01:38 +0000831opaque_lsa_new_if_callback (struct list *funclist, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000832{
paul1eb8ef22005-04-07 07:30:20 +0000833 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000834 struct ospf_opaque_functab *functab;
835 int rc = -1;
836
paul1eb8ef22005-04-07 07:30:20 +0000837 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000838 if (functab->new_if_hook != NULL)
839 if ((* functab->new_if_hook)(ifp) != 0)
840 goto out;
paul718e3742002-12-13 20:15:29 +0000841 rc = 0;
842out:
843 return rc;
844}
845
846static int
paul87d6f872004-09-24 08:01:38 +0000847opaque_lsa_del_if_callback (struct list *funclist, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000848{
paul1eb8ef22005-04-07 07:30:20 +0000849 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000850 struct ospf_opaque_functab *functab;
851 int rc = -1;
852
paul1eb8ef22005-04-07 07:30:20 +0000853 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000854 if (functab->del_if_hook != NULL)
855 if ((* functab->del_if_hook)(ifp) != 0)
856 goto out;
paul718e3742002-12-13 20:15:29 +0000857 rc = 0;
858out:
859 return rc;
860}
861
862static void
paul87d6f872004-09-24 08:01:38 +0000863opaque_lsa_ism_change_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000864 struct ospf_interface *oi, int old_status)
865{
paul1eb8ef22005-04-07 07:30:20 +0000866 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000867 struct ospf_opaque_functab *functab;
868
paul1eb8ef22005-04-07 07:30:20 +0000869 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000870 if (functab->ism_change_hook != NULL)
871 (* functab->ism_change_hook)(oi, old_status);
872
paul718e3742002-12-13 20:15:29 +0000873 return;
874}
875
876static void
paul87d6f872004-09-24 08:01:38 +0000877opaque_lsa_nsm_change_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000878 struct ospf_neighbor *nbr, int old_status)
879{
paul1eb8ef22005-04-07 07:30:20 +0000880 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000881 struct ospf_opaque_functab *functab;
882
paul1eb8ef22005-04-07 07:30:20 +0000883 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000884 if (functab->nsm_change_hook != NULL)
885 (* functab->nsm_change_hook)(nbr, old_status);
paul718e3742002-12-13 20:15:29 +0000886 return;
887}
888
889static void
paul87d6f872004-09-24 08:01:38 +0000890opaque_lsa_config_write_router_callback (struct list *funclist,
891 struct vty *vty)
paul718e3742002-12-13 20:15:29 +0000892{
paul1eb8ef22005-04-07 07:30:20 +0000893 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000894 struct ospf_opaque_functab *functab;
895
paul1eb8ef22005-04-07 07:30:20 +0000896 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000897 if (functab->config_write_router != NULL)
898 (* functab->config_write_router)(vty);
paul718e3742002-12-13 20:15:29 +0000899 return;
900}
901
902static void
paul87d6f872004-09-24 08:01:38 +0000903opaque_lsa_config_write_if_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000904 struct vty *vty, struct interface *ifp)
905{
paul1eb8ef22005-04-07 07:30:20 +0000906 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000907 struct ospf_opaque_functab *functab;
908
paul1eb8ef22005-04-07 07:30:20 +0000909 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000910 if (functab->config_write_if != NULL)
911 (* functab->config_write_if)(vty, ifp);
paul718e3742002-12-13 20:15:29 +0000912 return;
913}
914
915static void
paul87d6f872004-09-24 08:01:38 +0000916opaque_lsa_config_write_debug_callback (struct list *funclist, struct vty *vty)
paul718e3742002-12-13 20:15:29 +0000917{
paul1eb8ef22005-04-07 07:30:20 +0000918 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000919 struct ospf_opaque_functab *functab;
920
paul1eb8ef22005-04-07 07:30:20 +0000921 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000922 if (functab->config_write_debug != NULL)
923 (* functab->config_write_debug)(vty);
paul718e3742002-12-13 20:15:29 +0000924 return;
925}
926
927static int
paul87d6f872004-09-24 08:01:38 +0000928opaque_lsa_originate_callback (struct list *funclist, void *lsa_type_dependent)
paul718e3742002-12-13 20:15:29 +0000929{
paul1eb8ef22005-04-07 07:30:20 +0000930 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000931 struct ospf_opaque_functab *functab;
932 int rc = -1;
933
paul1eb8ef22005-04-07 07:30:20 +0000934 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000935 if (functab->lsa_originator != NULL)
936 if ((* functab->lsa_originator)(lsa_type_dependent) != 0)
937 goto out;
paul718e3742002-12-13 20:15:29 +0000938 rc = 0;
939out:
940 return rc;
941}
942
943static int
paul87d6f872004-09-24 08:01:38 +0000944new_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000945{
paul1eb8ef22005-04-07 07:30:20 +0000946 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000947 struct ospf_opaque_functab *functab;
948 int rc = -1;
949
950 /* This function handles ALL types of LSAs, not only opaque ones. */
paul1eb8ef22005-04-07 07:30:20 +0000951 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000952 if (functab->new_lsa_hook != NULL)
953 if ((* functab->new_lsa_hook)(lsa) != 0)
954 goto out;
paul718e3742002-12-13 20:15:29 +0000955 rc = 0;
956out:
957 return rc;
958}
959
960static int
paul87d6f872004-09-24 08:01:38 +0000961del_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000962{
paul1eb8ef22005-04-07 07:30:20 +0000963 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000964 struct ospf_opaque_functab *functab;
965 int rc = -1;
966
967 /* This function handles ALL types of LSAs, not only opaque ones. */
paul1eb8ef22005-04-07 07:30:20 +0000968 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000969 if (functab->del_lsa_hook != NULL)
970 if ((* functab->del_lsa_hook)(lsa) != 0)
971 goto out;
paul718e3742002-12-13 20:15:29 +0000972 rc = 0;
973out:
974 return rc;
975}
976
977/*------------------------------------------------------------------------*
978 * Followings are glue functions to call Opaque-LSA specific processing.
979 *------------------------------------------------------------------------*/
980
981int
982ospf_opaque_new_if (struct interface *ifp)
983{
paul87d6f872004-09-24 08:01:38 +0000984 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000985 int rc = -1;
986
paul09e4efd2003-01-18 00:12:02 +0000987 funclist = ospf_opaque_wildcard_funclist;
988 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
989 goto out;
990
paul718e3742002-12-13 20:15:29 +0000991 funclist = ospf_opaque_type9_funclist;
992 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
993 goto out;
994
995 funclist = ospf_opaque_type10_funclist;
996 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
997 goto out;
998
999 funclist = ospf_opaque_type11_funclist;
1000 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
1001 goto out;
1002
1003 rc = 0;
1004out:
1005 return rc;
1006}
1007
1008int
1009ospf_opaque_del_if (struct interface *ifp)
1010{
paul87d6f872004-09-24 08:01:38 +00001011 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001012 int rc = -1;
1013
paul09e4efd2003-01-18 00:12:02 +00001014 funclist = ospf_opaque_wildcard_funclist;
1015 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1016 goto out;
1017
paul718e3742002-12-13 20:15:29 +00001018 funclist = ospf_opaque_type9_funclist;
1019 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1020 goto out;
1021
1022 funclist = ospf_opaque_type10_funclist;
1023 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1024 goto out;
1025
1026 funclist = ospf_opaque_type11_funclist;
1027 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1028 goto out;
1029
1030 rc = 0;
1031out:
1032 return rc;
1033}
1034
1035void
1036ospf_opaque_ism_change (struct ospf_interface *oi, int old_status)
1037{
paul87d6f872004-09-24 08:01:38 +00001038 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001039
paul09e4efd2003-01-18 00:12:02 +00001040 funclist = ospf_opaque_wildcard_funclist;
1041 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1042
paul718e3742002-12-13 20:15:29 +00001043 funclist = ospf_opaque_type9_funclist;
1044 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1045
1046 funclist = ospf_opaque_type10_funclist;
1047 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1048
1049 funclist = ospf_opaque_type11_funclist;
1050 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1051
1052 return;
1053}
1054
1055void
1056ospf_opaque_nsm_change (struct ospf_neighbor *nbr, int old_state)
1057{
1058 struct ospf *top;
paul87d6f872004-09-24 08:01:38 +00001059 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001060
1061 if ((top = oi_to_top (nbr->oi)) == NULL)
1062 goto out;
1063
1064 if (old_state != NSM_Full && nbr->state == NSM_Full)
1065 {
1066 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
1067 {
1068 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1069 {
1070 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001071 zlog_debug ("Opaque-LSA: Now get operational!");
paul718e3742002-12-13 20:15:29 +00001072
1073 SET_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT);
1074 }
1075
1076 ospf_opaque_lsa_originate_schedule (nbr->oi, NULL);
1077 }
1078 }
1079 else
1080 if (old_state == NSM_Full && nbr->state != NSM_Full)
1081 {
1082#ifdef NOTYET
1083 /*
1084 * If no more opaque-capable full-state neighbor remains in the
1085 * flooding scope which corresponds to Opaque-LSA type, periodic
1086 * LS flooding should be stopped.
1087 */
1088#endif /* NOTYET */
1089 ;
1090 }
1091
paul09e4efd2003-01-18 00:12:02 +00001092 funclist = ospf_opaque_wildcard_funclist;
1093 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1094
paul718e3742002-12-13 20:15:29 +00001095 funclist = ospf_opaque_type9_funclist;
1096 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1097
1098 funclist = ospf_opaque_type10_funclist;
1099 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1100
1101 funclist = ospf_opaque_type11_funclist;
1102 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1103
1104out:
1105 return;
1106}
1107
1108void
1109ospf_opaque_config_write_router (struct vty *vty, struct ospf *ospf)
1110{
paul87d6f872004-09-24 08:01:38 +00001111 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001112
1113 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
1114 vty_out (vty, " capability opaque%s", VTY_NEWLINE);
1115
paul09e4efd2003-01-18 00:12:02 +00001116 funclist = ospf_opaque_wildcard_funclist;
1117 opaque_lsa_config_write_router_callback (funclist, vty);
1118
paul718e3742002-12-13 20:15:29 +00001119 funclist = ospf_opaque_type9_funclist;
1120 opaque_lsa_config_write_router_callback (funclist, vty);
1121
1122 funclist = ospf_opaque_type10_funclist;
1123 opaque_lsa_config_write_router_callback (funclist, vty);
1124
1125 funclist = ospf_opaque_type11_funclist;
1126 opaque_lsa_config_write_router_callback (funclist, vty);
1127
1128 return;
1129}
1130
1131void
1132ospf_opaque_config_write_if (struct vty *vty, struct interface *ifp)
1133{
paul87d6f872004-09-24 08:01:38 +00001134 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001135
paul09e4efd2003-01-18 00:12:02 +00001136 funclist = ospf_opaque_wildcard_funclist;
1137 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1138
paul718e3742002-12-13 20:15:29 +00001139 funclist = ospf_opaque_type9_funclist;
1140 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1141
1142 funclist = ospf_opaque_type10_funclist;
1143 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1144
1145 funclist = ospf_opaque_type11_funclist;
1146 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1147
1148 return;
1149}
1150
1151void
1152ospf_opaque_config_write_debug (struct vty *vty)
1153{
paul87d6f872004-09-24 08:01:38 +00001154 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001155
paul09e4efd2003-01-18 00:12:02 +00001156 funclist = ospf_opaque_wildcard_funclist;
1157 opaque_lsa_config_write_debug_callback (funclist, vty);
1158
paul718e3742002-12-13 20:15:29 +00001159 funclist = ospf_opaque_type9_funclist;
1160 opaque_lsa_config_write_debug_callback (funclist, vty);
1161
1162 funclist = ospf_opaque_type10_funclist;
1163 opaque_lsa_config_write_debug_callback (funclist, vty);
1164
1165 funclist = ospf_opaque_type11_funclist;
1166 opaque_lsa_config_write_debug_callback (funclist, vty);
1167
1168 return;
1169}
1170
1171void
1172show_opaque_info_detail (struct vty *vty, struct ospf_lsa *lsa)
1173{
1174 struct lsa_header *lsah = (struct lsa_header *) lsa->data;
1175 u_int32_t lsid = ntohl (lsah->id.s_addr);
1176 u_char opaque_type = GET_OPAQUE_TYPE (lsid);
1177 u_int32_t opaque_id = GET_OPAQUE_ID (lsid);
1178 struct ospf_opaque_functab *functab;
1179
1180 /* Switch output functionality by vty address. */
1181 if (vty != NULL)
1182 {
paul020709f2003-04-04 02:44:16 +00001183 vty_out (vty, " Opaque-Type %u (%s)%s", opaque_type,
1184 ospf_opaque_type_name (opaque_type), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001185 vty_out (vty, " Opaque-ID 0x%x%s", opaque_id, VTY_NEWLINE);
1186
1187 vty_out (vty, " Opaque-Info: %u octets of data%s%s",
1188 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1189 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)",
1190 VTY_NEWLINE);
1191 }
1192 else
1193 {
ajs2a42e282004-12-08 18:43:03 +00001194 zlog_debug (" Opaque-Type %u (%s)", opaque_type,
paul020709f2003-04-04 02:44:16 +00001195 ospf_opaque_type_name (opaque_type));
ajs2a42e282004-12-08 18:43:03 +00001196 zlog_debug (" Opaque-ID 0x%x", opaque_id);
paul718e3742002-12-13 20:15:29 +00001197
ajs2a42e282004-12-08 18:43:03 +00001198 zlog_debug (" Opaque-Info: %u octets of data%s",
paul718e3742002-12-13 20:15:29 +00001199 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1200 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)");
1201 }
1202
1203 /* Call individual output functions. */
1204 if ((functab = ospf_opaque_functab_lookup (lsa)) != NULL)
1205 if (functab->show_opaque_info != NULL)
1206 (* functab->show_opaque_info)(vty, lsa);
1207
1208 return;
1209}
1210
1211void
1212ospf_opaque_lsa_dump (struct stream *s, u_int16_t length)
1213{
1214 struct ospf_lsa lsa;
1215
1216 lsa.data = (struct lsa_header *) STREAM_PNT (s);
1217 show_opaque_info_detail (NULL, &lsa);
1218 return;
1219}
1220
1221static int
1222ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa)
1223{
paul87d6f872004-09-24 08:01:38 +00001224 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001225 int rc = -1;
1226
1227 /*
1228 * Some Opaque-LSA user may want to monitor every LSA installation
1229 * into the LSDB, regardless with target LSA type.
1230 */
paul09e4efd2003-01-18 00:12:02 +00001231 funclist = ospf_opaque_wildcard_funclist;
1232 if (new_lsa_callback (funclist, lsa) != 0)
1233 goto out;
1234
paul718e3742002-12-13 20:15:29 +00001235 funclist = ospf_opaque_type9_funclist;
1236 if (new_lsa_callback (funclist, lsa) != 0)
1237 goto out;
1238
1239 funclist = ospf_opaque_type10_funclist;
1240 if (new_lsa_callback (funclist, lsa) != 0)
1241 goto out;
1242
1243 funclist = ospf_opaque_type11_funclist;
1244 if (new_lsa_callback (funclist, lsa) != 0)
1245 goto out;
1246
1247 rc = 0;
1248out:
1249 return rc;
1250}
1251
1252static int
1253ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa)
1254{
paul87d6f872004-09-24 08:01:38 +00001255 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001256 int rc = -1;
1257
1258 /*
1259 * Some Opaque-LSA user may want to monitor every LSA deletion
1260 * from the LSDB, regardless with target LSA type.
1261 */
paul09e4efd2003-01-18 00:12:02 +00001262 funclist = ospf_opaque_wildcard_funclist;
1263 if (del_lsa_callback (funclist, lsa) != 0)
1264 goto out;
1265
paul718e3742002-12-13 20:15:29 +00001266 funclist = ospf_opaque_type9_funclist;
1267 if (del_lsa_callback (funclist, lsa) != 0)
1268 goto out;
1269
1270 funclist = ospf_opaque_type10_funclist;
1271 if (del_lsa_callback (funclist, lsa) != 0)
1272 goto out;
1273
1274 funclist = ospf_opaque_type11_funclist;
1275 if (del_lsa_callback (funclist, lsa) != 0)
1276 goto out;
1277
1278 rc = 0;
1279out:
1280 return rc;
1281}
1282
1283/*------------------------------------------------------------------------*
1284 * Followings are Opaque-LSA origination/refresh management functions.
1285 *------------------------------------------------------------------------*/
1286
1287static int ospf_opaque_type9_lsa_originate (struct thread *t);
1288static int ospf_opaque_type10_lsa_originate (struct thread *t);
1289static int ospf_opaque_type11_lsa_originate (struct thread *t);
paul87d6f872004-09-24 08:01:38 +00001290static void ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg);
paul718e3742002-12-13 20:15:29 +00001291
1292void
1293ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0)
1294{
1295 struct ospf *top;
1296 struct ospf_area *area;
paul1eb8ef22005-04-07 07:30:20 +00001297 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001298 struct opaque_info_per_type *oipt;
1299 int delay = 0;
1300
1301 if ((top = oi_to_top (oi)) == NULL || (area = oi->area) == NULL)
1302 {
1303 zlog_warn ("ospf_opaque_lsa_originate_schedule: Invalid argument?");
1304 goto out;
1305 }
1306
1307 /* It may not a right time to schedule origination now. */
1308 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1309 {
1310 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001311 zlog_debug ("ospf_opaque_lsa_originate_schedule: Not operational.");
paul718e3742002-12-13 20:15:29 +00001312 goto out; /* This is not an error. */
1313 }
1314 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
1315 {
1316 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001317 zlog_debug ("ospf_opaque_lsa_originate_schedule: Under blockade.");
paul718e3742002-12-13 20:15:29 +00001318 goto out; /* This is not an error, too. */
1319 }
1320
1321 if (delay0 != NULL)
1322 delay = *delay0;
1323
1324 /*
1325 * There might be some entries that have been waiting for triggering
1326 * of per opaque-type re-origination get resumed.
1327 */
1328 ospf_opaque_lsa_reoriginate_resume ( oi->opaque_lsa_self, (void *) oi);
1329 ospf_opaque_lsa_reoriginate_resume (area->opaque_lsa_self, (void *) area);
1330 ospf_opaque_lsa_reoriginate_resume ( top->opaque_lsa_self, (void *) top);
1331
1332 /*
1333 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1334 */
1335 if (! list_isempty (ospf_opaque_type9_funclist)
1336 && list_isempty (oi->opaque_lsa_self)
1337 && oi->t_opaque_lsa_self == NULL)
1338 {
1339 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001340 zlog_debug ("Schedule Type-9 Opaque-LSA origination in %d sec later.", delay);
paul718e3742002-12-13 20:15:29 +00001341 oi->t_opaque_lsa_self =
1342 thread_add_timer (master, ospf_opaque_type9_lsa_originate, oi, delay);
1343 delay += OSPF_MIN_LS_INTERVAL;
1344 }
1345
1346 if (! list_isempty (ospf_opaque_type10_funclist)
1347 && list_isempty (area->opaque_lsa_self)
1348 && area->t_opaque_lsa_self == NULL)
1349 {
1350 /*
1351 * One AREA may contain multiple OIs, but above 2nd and 3rd
1352 * conditions prevent from scheduling the originate function
1353 * again and again.
1354 */
1355 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001356 zlog_debug ("Schedule Type-10 Opaque-LSA origination in %d sec later.", delay);
paul718e3742002-12-13 20:15:29 +00001357 area->t_opaque_lsa_self =
1358 thread_add_timer (master, ospf_opaque_type10_lsa_originate,
1359 area, delay);
1360 delay += OSPF_MIN_LS_INTERVAL;
1361 }
1362
1363 if (! list_isempty (ospf_opaque_type11_funclist)
1364 && list_isempty (top->opaque_lsa_self)
1365 && top->t_opaque_lsa_self == NULL)
1366 {
1367 /*
1368 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1369 * conditions prevent from scheduling the originate function
1370 * again and again.
1371 */
1372 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001373 zlog_debug ("Schedule Type-11 Opaque-LSA origination in %d sec later.", delay);
paul718e3742002-12-13 20:15:29 +00001374 top->t_opaque_lsa_self =
1375 thread_add_timer (master, ospf_opaque_type11_lsa_originate,
1376 top, delay);
1377 delay += OSPF_MIN_LS_INTERVAL;
1378 }
1379
1380 /*
1381 * Following section treats a special situation that this node's
1382 * opaque capability has changed as "ON -> OFF -> ON".
1383 */
1384 if (! list_isempty (ospf_opaque_type9_funclist)
1385 && ! list_isempty (oi->opaque_lsa_self))
1386 {
paul1eb8ef22005-04-07 07:30:20 +00001387 for (ALL_LIST_ELEMENTS (oi->opaque_lsa_self, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001388 {
hasso0d85b992004-03-18 19:18:33 +00001389 /*
1390 * removed the test for
1391 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1392 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1393 * not being empty.
1394 */
paul1eb8ef22005-04-07 07:30:20 +00001395 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1396 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001397 continue;
1398
1399 ospf_opaque_lsa_reoriginate_schedule ((void *) oi,
1400 OSPF_OPAQUE_LINK_LSA, oipt->opaque_type);
1401 }
1402 }
1403
1404 if (! list_isempty (ospf_opaque_type10_funclist)
1405 && ! list_isempty (area->opaque_lsa_self))
1406 {
paul1eb8ef22005-04-07 07:30:20 +00001407 for (ALL_LIST_ELEMENTS (area->opaque_lsa_self, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001408 {
hasso0d85b992004-03-18 19:18:33 +00001409 /*
1410 * removed the test for
1411 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1412 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1413 * not being empty.
1414 */
paul1eb8ef22005-04-07 07:30:20 +00001415 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1416 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001417 continue;
1418
1419 ospf_opaque_lsa_reoriginate_schedule ((void *) area,
1420 OSPF_OPAQUE_AREA_LSA, oipt->opaque_type);
1421 }
1422 }
1423
1424 if (! list_isempty (ospf_opaque_type11_funclist)
1425 && ! list_isempty (top->opaque_lsa_self))
1426 {
paul1eb8ef22005-04-07 07:30:20 +00001427 for (ALL_LIST_ELEMENTS (top->opaque_lsa_self, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001428 {
hasso0d85b992004-03-18 19:18:33 +00001429 /*
1430 * removed the test for
1431 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1432 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1433 * not being empty.
1434 */
paul1eb8ef22005-04-07 07:30:20 +00001435 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1436 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001437 continue;
1438
1439 ospf_opaque_lsa_reoriginate_schedule ((void *) top,
1440 OSPF_OPAQUE_AS_LSA, oipt->opaque_type);
1441 }
1442 }
1443
1444 if (delay0 != NULL)
1445 *delay0 = delay;
1446
1447out:
1448 return;
1449}
1450
1451static int
1452ospf_opaque_type9_lsa_originate (struct thread *t)
1453{
1454 struct ospf_interface *oi;
1455 int rc;
1456
1457 oi = THREAD_ARG (t);
1458 oi->t_opaque_lsa_self = NULL;
1459
1460 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001461 zlog_debug ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
paul718e3742002-12-13 20:15:29 +00001462 IF_NAME (oi));
1463
1464 rc = opaque_lsa_originate_callback (ospf_opaque_type9_funclist, oi);
1465
1466 return rc;
1467}
1468
1469static int
1470ospf_opaque_type10_lsa_originate (struct thread *t)
1471{
1472 struct ospf_area *area;
1473 int rc;
1474
1475 area = THREAD_ARG (t);
1476 area->t_opaque_lsa_self = NULL;
1477
1478 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001479 zlog_debug ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
paul718e3742002-12-13 20:15:29 +00001480 inet_ntoa (area->area_id));
1481
1482 rc = opaque_lsa_originate_callback (ospf_opaque_type10_funclist, area);
1483
1484 return rc;
1485}
1486
1487static int
1488ospf_opaque_type11_lsa_originate (struct thread *t)
1489{
1490 struct ospf *top;
1491 int rc;
1492
1493 top = THREAD_ARG (t);
1494 top->t_opaque_lsa_self = NULL;
1495
1496 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001497 zlog_debug ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
paul718e3742002-12-13 20:15:29 +00001498
1499 rc = opaque_lsa_originate_callback (ospf_opaque_type11_funclist, top);
1500
1501 return rc;
1502}
1503
1504static void
paul87d6f872004-09-24 08:01:38 +00001505ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg)
paul718e3742002-12-13 20:15:29 +00001506{
paul1eb8ef22005-04-07 07:30:20 +00001507 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001508 struct opaque_info_per_type *oipt;
1509 struct ospf_opaque_functab *functab;
1510
1511 if (listtop == NULL)
1512 goto out;
1513
1514 /*
1515 * Pickup oipt entries those which in SUSPEND status, and give
1516 * them a chance to start re-origination now.
1517 */
paul1eb8ef22005-04-07 07:30:20 +00001518 for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001519 {
paul87d6f872004-09-24 08:01:38 +00001520 if (oipt->status != PROC_SUSPEND)
paul718e3742002-12-13 20:15:29 +00001521 continue;
1522
1523 oipt->status = PROC_NORMAL;
1524
1525 if ((functab = oipt->functab) == NULL
paul87d6f872004-09-24 08:01:38 +00001526 || functab->lsa_originator == NULL)
paul718e3742002-12-13 20:15:29 +00001527 continue;
1528
1529 if ((* functab->lsa_originator)(arg) != 0)
1530 {
1531 zlog_warn ("ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", oipt->opaque_type);
1532 continue;
1533 }
1534 }
1535
1536out:
1537 return;
1538}
1539
1540struct ospf_lsa *
1541ospf_opaque_lsa_install (struct ospf_lsa *lsa, int rt_recalc)
1542{
1543 struct ospf_lsa *new = NULL;
1544 struct opaque_info_per_type *oipt;
1545 struct opaque_info_per_id *oipi;
1546 struct ospf *top;
1547
1548 /* Don't take "rt_recalc" into consideration for now. *//* XXX */
1549
1550 if (! IS_LSA_SELF (lsa))
1551 {
1552 new = lsa; /* Don't touch this LSA. */
1553 goto out;
1554 }
1555
1556 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
ajs2a42e282004-12-08 18:43:03 +00001557 zlog_debug ("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)));
paul718e3742002-12-13 20:15:29 +00001558
1559 /* Replace the existing lsa with the new one. */
1560 if ((oipt = lookup_opaque_info_by_type (lsa)) != NULL
paul87d6f872004-09-24 08:01:38 +00001561 && (oipi = lookup_opaque_info_by_id (oipt, lsa)) != NULL)
paul718e3742002-12-13 20:15:29 +00001562 {
Paul Jakma1fe6ed32006-07-26 09:37:26 +00001563 ospf_lsa_unlock (&oipi->lsa);
paul718e3742002-12-13 20:15:29 +00001564 oipi->lsa = ospf_lsa_lock (lsa);
1565 }
1566 /* Register the new lsa entry and get its control info. */
1567 else
1568 if ((oipi = register_opaque_lsa (lsa)) == NULL)
1569 {
1570 zlog_warn ("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1571 goto out;
1572 }
1573
1574 /*
1575 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1576 * for periodic refresh of self-originated Opaque-LSAs.
1577 */
1578 switch (lsa->data->type)
1579 {
1580 case OSPF_OPAQUE_LINK_LSA:
paul09e4efd2003-01-18 00:12:02 +00001581 if ((top = oi_to_top (lsa->oi)) == NULL)
1582 {
1583 /* Above conditions must have passed. */
1584 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1585 goto out;
1586 }
1587 break;
paul718e3742002-12-13 20:15:29 +00001588 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00001589 if (lsa->area == NULL || (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001590 {
1591 /* Above conditions must have passed. */
1592 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1593 goto out;
1594 }
1595 break;
1596 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +00001597 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001598 if (lsa->area != NULL && (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001599 {
1600 /* Above conditions must have passed. */
1601 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1602 goto out;
1603 }
1604 break;
1605 default:
1606 zlog_warn ("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", lsa->data->type);
1607 goto out;
1608 }
1609
1610 ospf_refresher_register_lsa (top, lsa);
1611 new = lsa;
1612
1613out:
1614 return new;
1615}
1616
Paul Jakmad71ea652011-03-22 15:23:55 +00001617struct ospf_lsa *
paul718e3742002-12-13 20:15:29 +00001618ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
1619{
paul020709f2003-04-04 02:44:16 +00001620 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001621 struct ospf_opaque_functab *functab;
Paul Jakmad71ea652011-03-22 15:23:55 +00001622 struct ospf_lsa *new = NULL;
1623
paul020709f2003-04-04 02:44:16 +00001624 ospf = ospf_lookup ();
1625
paul718e3742002-12-13 20:15:29 +00001626 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL
paul87d6f872004-09-24 08:01:38 +00001627 || functab->lsa_refresher == NULL)
paul718e3742002-12-13 20:15:29 +00001628 {
1629 /*
1630 * Though this LSA seems to have originated on this node, the
1631 * handling module for this "lsa-type and opaque-type" was
1632 * already deleted sometime ago.
1633 * Anyway, this node still has a responsibility to flush this
1634 * LSA from the routing domain.
1635 */
1636 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001637 zlog_debug ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id));
paul718e3742002-12-13 20:15:29 +00001638
1639 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
Paul Jakma02d942c2010-01-24 23:36:20 +00001640 ospf_lsa_flush (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00001641 }
1642 else
Paul Jakmad71ea652011-03-22 15:23:55 +00001643 new = (* functab->lsa_refresher)(lsa);
paul718e3742002-12-13 20:15:29 +00001644
Paul Jakmad71ea652011-03-22 15:23:55 +00001645 return new;
paul718e3742002-12-13 20:15:29 +00001646}
1647
1648/*------------------------------------------------------------------------*
1649 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1650 * triggered by external interventions (vty session, signaling, etc).
1651 *------------------------------------------------------------------------*/
1652
1653#define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
1654 if (!(T)) \
1655 (T) = thread_add_timer (master, (F), (L), (V))
1656
1657static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type);
1658static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t);
1659static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t);
1660static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t);
1661static int ospf_opaque_lsa_refresh_timer (struct thread *t);
1662
1663void
1664ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
1665 u_char lsa_type, u_char opaque_type)
1666{
1667 struct ospf *top;
1668 struct ospf_area dummy, *area = NULL;
1669 struct ospf_interface *oi = NULL;
1670
1671 struct ospf_lsa *lsa;
1672 struct opaque_info_per_type *oipt;
paul87d6f872004-09-24 08:01:38 +00001673 int (*func) (struct thread * t) = NULL;
paul718e3742002-12-13 20:15:29 +00001674 int delay;
1675
1676 switch (lsa_type)
1677 {
1678 case OSPF_OPAQUE_LINK_LSA:
1679 if ((oi = (struct ospf_interface *) lsa_type_dependent) == NULL)
1680 {
paul87d6f872004-09-24 08:01:38 +00001681 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1682 " Type-9 Opaque-LSA: Invalid parameter?");
1683 goto out;
paul718e3742002-12-13 20:15:29 +00001684 }
1685 if ((top = oi_to_top (oi)) == NULL)
1686 {
paul87d6f872004-09-24 08:01:38 +00001687 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1688 IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001689 goto out;
1690 }
paul87d6f872004-09-24 08:01:38 +00001691 if (!list_isempty (ospf_opaque_type9_funclist)
1692 && list_isempty (oi->opaque_lsa_self)
1693 && oi->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001694 {
paul87d6f872004-09-24 08:01:38 +00001695 zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u):"
1696 " Common origination for OI(%s) has already started",
1697 opaque_type, IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001698 goto out;
1699 }
1700 func = ospf_opaque_type9_lsa_reoriginate_timer;
1701 break;
1702 case OSPF_OPAQUE_AREA_LSA:
1703 if ((area = (struct ospf_area *) lsa_type_dependent) == NULL)
1704 {
paul87d6f872004-09-24 08:01:38 +00001705 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1706 " Type-10 Opaque-LSA: Invalid parameter?");
paul718e3742002-12-13 20:15:29 +00001707 goto out;
1708 }
paul68980082003-03-25 05:07:42 +00001709 if ((top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001710 {
paul87d6f872004-09-24 08:01:38 +00001711 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1712 " AREA(%s) -> TOP?", inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001713 goto out;
1714 }
paul87d6f872004-09-24 08:01:38 +00001715 if (!list_isempty (ospf_opaque_type10_funclist)
1716 && list_isempty (area->opaque_lsa_self)
1717 && area->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001718 {
paul87d6f872004-09-24 08:01:38 +00001719 zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u):"
1720 " Common origination for AREA(%s) has already started",
1721 opaque_type, inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001722 goto out;
1723 }
1724 func = ospf_opaque_type10_lsa_reoriginate_timer;
1725 break;
1726 case OSPF_OPAQUE_AS_LSA:
1727 if ((top = (struct ospf *) lsa_type_dependent) == NULL)
1728 {
paul87d6f872004-09-24 08:01:38 +00001729 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1730 " Type-11 Opaque-LSA: Invalid parameter?");
1731 goto out;
paul718e3742002-12-13 20:15:29 +00001732 }
paul87d6f872004-09-24 08:01:38 +00001733 if (!list_isempty (ospf_opaque_type11_funclist)
1734 && list_isempty (top->opaque_lsa_self)
1735 && top->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001736 {
paul87d6f872004-09-24 08:01:38 +00001737 zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u):"
1738 " Common origination has already started", opaque_type);
paul718e3742002-12-13 20:15:29 +00001739 goto out;
1740 }
1741
1742 /* Fake "area" to pass "ospf" to a lookup function later. */
paul68980082003-03-25 05:07:42 +00001743 dummy.ospf = top;
paul718e3742002-12-13 20:15:29 +00001744 area = &dummy;
1745
1746 func = ospf_opaque_type11_lsa_reoriginate_timer;
1747 break;
1748 default:
paul87d6f872004-09-24 08:01:38 +00001749 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1750 " Unexpected LSA-type(%u)",
1751 lsa_type);
paul718e3742002-12-13 20:15:29 +00001752 goto out;
1753 }
1754
1755 /* It may not a right time to schedule reorigination now. */
paul87d6f872004-09-24 08:01:38 +00001756 if (!CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
paul718e3742002-12-13 20:15:29 +00001757 {
1758 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001759 zlog_debug ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
paul87d6f872004-09-24 08:01:38 +00001760 goto out; /* This is not an error. */
paul718e3742002-12-13 20:15:29 +00001761 }
1762 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
1763 {
1764 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001765 zlog_debug ("ospf_opaque_lsa_reoriginate_schedule: Under blockade.");
paul87d6f872004-09-24 08:01:38 +00001766 goto out; /* This is not an error, too. */
paul718e3742002-12-13 20:15:29 +00001767 }
1768
1769 /* Generate a dummy lsa to be passed for a lookup function. */
1770 lsa = pseudo_lsa (oi, area, lsa_type, opaque_type);
1771
1772 if ((oipt = lookup_opaque_info_by_type (lsa)) == NULL)
1773 {
1774 struct ospf_opaque_functab *functab;
1775 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL)
1776 {
paul87d6f872004-09-24 08:01:38 +00001777 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1778 " No associated function?: lsa_type(%u),"
1779 " opaque_type(%u)",
1780 lsa_type, opaque_type);
paul718e3742002-12-13 20:15:29 +00001781 goto out;
1782 }
1783 if ((oipt = register_opaque_info_per_type (functab, lsa)) == NULL)
1784 {
paul87d6f872004-09-24 08:01:38 +00001785 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1786 " Cannot get a control info?: lsa_type(%u),"
1787 " opaque_type(%u)",
1788 lsa_type, opaque_type);
paul718e3742002-12-13 20:15:29 +00001789 goto out;
1790 }
1791 }
1792
1793 if (oipt->t_opaque_lsa_self != NULL)
1794 {
1795 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001796 zlog_debug ("Type-%u Opaque-LSA has already scheduled to"
paul87d6f872004-09-24 08:01:38 +00001797 " RE-ORIGINATE: [opaque-type=%u]",
1798 lsa_type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
paul718e3742002-12-13 20:15:29 +00001799 goto out;
1800 }
1801
1802 /*
1803 * Different from initial origination time, in which various conditions
1804 * (opaque capability, neighbor status etc) are assured by caller of
1805 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1806 * it is highly possible that these conditions might not be satisfied
1807 * at the time of re-origination function is to be called.
1808 */
1809 delay = OSPF_MIN_LS_INTERVAL; /* XXX */
1810
1811 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001812 zlog_debug ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
paul87d6f872004-09-24 08:01:38 +00001813 " sec later: [opaque-type=%u]",
1814 lsa_type, delay,
1815 GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
paul718e3742002-12-13 20:15:29 +00001816
1817 OSPF_OPAQUE_TIMER_ON (oipt->t_opaque_lsa_self, func, oipt, delay);
1818
1819out:
1820 return;
1821}
1822
1823static struct ospf_lsa *
1824pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area,
1825 u_char lsa_type, u_char opaque_type)
1826{
1827 static struct ospf_lsa lsa = { 0 };
1828 static struct lsa_header lsah = { 0 };
1829 u_int32_t tmp;
1830
1831 lsa.oi = oi;
1832 lsa.area = area;
1833 lsa.data = &lsah;
1834
1835 lsah.type = lsa_type;
1836 tmp = SET_OPAQUE_LSID (opaque_type, 0); /* Opaque-ID is unused here. */
1837 lsah.id.s_addr = htonl (tmp);
1838
1839 return &lsa;
1840}
1841
1842static int
1843ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t)
1844{
1845 struct opaque_info_per_type *oipt;
1846 struct ospf_opaque_functab *functab;
1847 struct ospf *top;
1848 struct ospf_interface *oi;
1849 int rc = -1;
1850
1851 oipt = THREAD_ARG (t);
1852 oipt->t_opaque_lsa_self = NULL;
1853
1854 if ((functab = oipt->functab) == NULL
1855 || functab->lsa_originator == NULL)
1856 {
1857 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1858 goto out;
1859 }
1860
1861 oi = (struct ospf_interface *) oipt->owner;
1862 if ((top = oi_to_top (oi)) == NULL)
1863 {
1864 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1865 goto out;
1866 }
1867
1868 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)
1869 || ! ospf_if_is_enable (oi)
paul68980082003-03-25 05:07:42 +00001870 || ospf_nbr_count_opaque_capable (oi) == 0)
paul718e3742002-12-13 20:15:29 +00001871 {
1872 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001873 zlog_debug ("Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
paul718e3742002-12-13 20:15:29 +00001874
1875 oipt->status = PROC_SUSPEND;
1876 rc = 0;
1877 goto out;
1878 }
1879
1880 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001881 zlog_debug ("Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)", oipt->opaque_type, IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001882
1883 rc = (* functab->lsa_originator)(oi);
1884out:
1885 return rc;
1886}
1887
1888static int
1889ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t)
1890{
1891 struct opaque_info_per_type *oipt;
1892 struct ospf_opaque_functab *functab;
paul1eb8ef22005-04-07 07:30:20 +00001893 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001894 struct ospf *top;
1895 struct ospf_area *area;
1896 struct ospf_interface *oi;
1897 int n, rc = -1;
1898
1899 oipt = THREAD_ARG (t);
1900 oipt->t_opaque_lsa_self = NULL;
1901
1902 if ((functab = oipt->functab) == NULL
1903 || functab->lsa_originator == NULL)
1904 {
1905 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1906 goto out;
1907 }
1908
1909 area = (struct ospf_area *) oipt->owner;
paul68980082003-03-25 05:07:42 +00001910 if (area == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001911 {
1912 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1913 goto out;
1914 }
1915
1916 /* There must be at least one "opaque-capable, full-state" neighbor. */
1917 n = 0;
paul1eb8ef22005-04-07 07:30:20 +00001918 for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi))
paul718e3742002-12-13 20:15:29 +00001919 {
paul68980082003-03-25 05:07:42 +00001920 if ((n = ospf_nbr_count_opaque_capable (oi)) > 0)
paul718e3742002-12-13 20:15:29 +00001921 break;
1922 }
1923
1924 if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1925 {
1926 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001927 zlog_debug ("Suspend re-origination of Type-10 Opaque-LSAs"
paul87d6f872004-09-24 08:01:38 +00001928 " (opaque-type=%u) for a while...",
1929 oipt->opaque_type);
paul718e3742002-12-13 20:15:29 +00001930
1931 oipt->status = PROC_SUSPEND;
1932 rc = 0;
1933 goto out;
1934 }
1935
1936 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001937 zlog_debug ("Timer[Type10-LSA]: Re-originate Opaque-LSAs"
paul87d6f872004-09-24 08:01:38 +00001938 " (opaque-type=%u) for Area %s",
1939 oipt->opaque_type, inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001940
1941 rc = (* functab->lsa_originator)(area);
1942out:
1943 return rc;
1944}
1945
1946static int
1947ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t)
1948{
1949 struct opaque_info_per_type *oipt;
1950 struct ospf_opaque_functab *functab;
1951 struct ospf *top;
1952 int rc = -1;
1953
1954 oipt = THREAD_ARG (t);
1955 oipt->t_opaque_lsa_self = NULL;
1956
1957 if ((functab = oipt->functab) == NULL
paul87d6f872004-09-24 08:01:38 +00001958 || functab->lsa_originator == NULL)
paul718e3742002-12-13 20:15:29 +00001959 {
paul87d6f872004-09-24 08:01:38 +00001960 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer:"
1961 " No associated function?");
paul718e3742002-12-13 20:15:29 +00001962 goto out;
1963 }
1964
1965 if ((top = (struct ospf *) oipt->owner) == NULL)
1966 {
1967 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1968 goto out;
1969 }
1970
1971 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1972 {
1973 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001974 zlog_debug ("Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
paul718e3742002-12-13 20:15:29 +00001975
1976 oipt->status = PROC_SUSPEND;
1977 rc = 0;
1978 goto out;
1979 }
1980
1981 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001982 zlog_debug ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type);
paul718e3742002-12-13 20:15:29 +00001983
1984 rc = (* functab->lsa_originator)(top);
1985out:
1986 return rc;
1987}
1988
paul718e3742002-12-13 20:15:29 +00001989void
1990ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
1991{
1992 struct opaque_info_per_type *oipt;
1993 struct opaque_info_per_id *oipi;
1994 struct ospf_lsa *lsa;
1995 int delay;
1996
1997 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
1998 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
1999 {
2000 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
2001 goto out;
2002 }
2003
2004 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2005 if ((lsa = oipi->lsa) == NULL)
2006 {
2007 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
2008 goto out;
2009 }
2010
2011 if (oipi->t_opaque_lsa_self != NULL)
2012 {
2013 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002014 zlog_debug ("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)));
paul718e3742002-12-13 20:15:29 +00002015 goto out;
2016 }
2017
2018 /* Delete this lsa from neighbor retransmit-list. */
2019 switch (lsa->data->type)
2020 {
2021 case OSPF_OPAQUE_LINK_LSA:
2022 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002023 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002024 break;
2025 case OSPF_OPAQUE_AS_LSA:
ajse6a0bf92005-09-17 18:53:38 +00002026 ospf_ls_retransmit_delete_nbr_as (lsa0->area->ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002027 break;
2028 default:
2029 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2030 goto out;
2031 }
2032
2033 delay = ospf_lsa_refresh_delay (lsa);
2034
2035 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002036 zlog_debug ("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)));
paul718e3742002-12-13 20:15:29 +00002037
2038 OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self,
2039 ospf_opaque_lsa_refresh_timer, oipi, delay);
2040out:
2041 return;
2042}
2043
2044static int
2045ospf_opaque_lsa_refresh_timer (struct thread *t)
2046{
2047 struct opaque_info_per_id *oipi;
2048 struct ospf_opaque_functab *functab;
2049 struct ospf_lsa *lsa;
2050
2051 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002052 zlog_debug ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
paul718e3742002-12-13 20:15:29 +00002053
2054 oipi = THREAD_ARG (t);
2055 oipi->t_opaque_lsa_self = NULL;
2056
2057 if ((lsa = oipi->lsa) != NULL)
2058 if ((functab = oipi->opqctl_type->functab) != NULL)
2059 if (functab->lsa_refresher != NULL)
2060 (* functab->lsa_refresher)(lsa);
2061
2062 return 0;
2063}
2064
2065void
2066ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
2067{
2068 struct opaque_info_per_type *oipt;
2069 struct opaque_info_per_id *oipi;
2070 struct ospf_lsa *lsa;
2071
2072 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
2073 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
2074 {
2075 zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2076 goto out;
2077 }
2078
2079 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2080 if ((lsa = oipi->lsa) == NULL)
2081 {
2082 zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
2083 goto out;
2084 }
2085
2086 /* Delete this lsa from neighbor retransmit-list. */
2087 switch (lsa->data->type)
2088 {
2089 case OSPF_OPAQUE_LINK_LSA:
2090 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002091 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002092 break;
2093 case OSPF_OPAQUE_AS_LSA:
ajse6a0bf92005-09-17 18:53:38 +00002094 ospf_ls_retransmit_delete_nbr_as (lsa0->area->ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002095 break;
2096 default:
2097 zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2098 goto out;
2099 }
2100
2101 /* Dequeue listnode entry from the list. */
2102 listnode_delete (oipt->id_list, oipi);
2103
2104 /* Avoid misjudgement in the next lookup. */
2105 if (listcount (oipt->id_list) == 0)
2106 oipt->id_list->head = oipt->id_list->tail = NULL;
2107
2108 /* Disassociate internal control information with the given lsa. */
paul718e3742002-12-13 20:15:29 +00002109 free_opaque_info_per_id ((void *) oipi);
2110
2111 /* Force given lsa's age to MaxAge. */
2112 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2113
2114 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002115 zlog_debug ("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)));
paul718e3742002-12-13 20:15:29 +00002116
2117 /* This lsa will be flushed and removed eventually. */
Paul Jakma02d942c2010-01-24 23:36:20 +00002118 ospf_lsa_flush (lsa0->area->ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002119
2120out:
2121 return;
2122}
2123
2124/*------------------------------------------------------------------------*
2125 * Followings are control functions to block origination after restart.
2126 *------------------------------------------------------------------------*/
2127
2128static void ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs, struct ospf_neighbor *inbr, struct ospf_lsa *lsa);
Olivier Dugeon14921062014-11-03 14:59:06 +01002129#ifdef BUGGY_UNLOCK
paul718e3742002-12-13 20:15:29 +00002130static void ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi);
2131static void ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area);
2132static void ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top);
2133static unsigned long ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type);
Olivier Dugeon14921062014-11-03 14:59:06 +01002134#endif /* BUGGY_UNLOCK */
paul718e3742002-12-13 20:15:29 +00002135
2136void
paul87d6f872004-09-24 08:01:38 +00002137ospf_opaque_adjust_lsreq (struct ospf_neighbor *nbr, struct list *lsas)
paul718e3742002-12-13 20:15:29 +00002138{
2139 struct ospf *top;
2140 struct ospf_area *area;
2141 struct ospf_interface *oi;
paul1eb8ef22005-04-07 07:30:20 +00002142 struct listnode *node1, *nnode1;
2143 struct listnode *node2, *nnode2;
paul718e3742002-12-13 20:15:29 +00002144 struct ospf_lsa *lsa;
2145
2146 if ((top = oi_to_top (nbr->oi)) == NULL)
2147 goto out;
2148
2149 /*
2150 * If an instance of self-originated Opaque-LSA is found in the given
2151 * LSA list, and it is not installed to LSDB yet, exclude it from the
2152 * list "nbr->ls_req". In this way, it is assured that an LSReq message,
2153 * which might be sent in the process of flooding, will not request for
2154 * the LSA to be flushed immediately; otherwise, depending on timing,
2155 * an LSUpd message will carry instances of target LSAs with MaxAge,
2156 * while other LSUpd message might carry old LSA instances (non-MaxAge).
2157 * Obviously, the latter would trigger miserable situations that repeat
2158 * installation and removal of unwanted LSAs indefinitely.
2159 */
paul1eb8ef22005-04-07 07:30:20 +00002160 for (ALL_LIST_ELEMENTS (lsas, node1, nnode1, lsa))
paul718e3742002-12-13 20:15:29 +00002161 {
paul718e3742002-12-13 20:15:29 +00002162 /* Filter out unwanted LSAs. */
2163 if (! IS_OPAQUE_LSA (lsa->data->type))
2164 continue;
2165 if (! IPV4_ADDR_SAME (&lsa->data->adv_router, &top->router_id))
2166 continue;
2167
2168 /*
2169 * Don't touch an LSA which has MaxAge; two possible cases.
2170 *
2171 * 1) This LSA has originally flushed by myself (received LSUpd
2172 * message's router-id is equal to my router-id), and flooded
2173 * back by an opaque-capable router.
2174 *
2175 * 2) This LSA has expired in an opaque-capable router and thus
2176 * flushed by the router.
2177 */
2178 if (IS_LSA_MAXAGE (lsa))
2179 continue;
2180
2181 /* If the LSA has installed in the LSDB, nothing to do here. */
2182 if (ospf_lsa_lookup_by_header (nbr->oi->area, lsa->data) != NULL)
2183 continue;
2184
2185 /* Ok, here we go. */
2186 switch (lsa->data->type)
2187 {
2188 case OSPF_OPAQUE_LINK_LSA:
2189 oi = nbr->oi;
2190 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2191 break;
2192 case OSPF_OPAQUE_AREA_LSA:
2193 area = nbr->oi->area;
paul1eb8ef22005-04-07 07:30:20 +00002194 for (ALL_LIST_ELEMENTS (area->oiflist, node2, nnode2, oi))
2195 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
paul718e3742002-12-13 20:15:29 +00002196 break;
2197 case OSPF_OPAQUE_AS_LSA:
paul1eb8ef22005-04-07 07:30:20 +00002198 for (ALL_LIST_ELEMENTS (top->oiflist, node2, nnode2, oi))
2199 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
paul718e3742002-12-13 20:15:29 +00002200 break;
2201 default:
2202 break;
2203 }
2204 }
2205
2206out:
2207 return;
2208}
2209
2210static void
2211ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs,
2212 struct ospf_neighbor *inbr,
2213 struct ospf_lsa *lsa)
2214{
2215 struct route_node *rn;
2216 struct ospf_neighbor *onbr;
2217 struct ospf_lsa *ls_req;
2218
2219 for (rn = route_top (nbrs); rn; rn = route_next (rn))
2220 {
2221 if ((onbr = rn->info) == NULL)
2222 continue;
2223 if (onbr == inbr)
2224 continue;
2225 if ((ls_req = ospf_ls_request_lookup (onbr, lsa)) == NULL)
2226 continue;
2227
2228 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002229 zlog_debug ("LSA[%s]: Exclude this entry from LSReq to send.", dump_lsa_key (lsa));
paul718e3742002-12-13 20:15:29 +00002230
2231 ospf_ls_request_delete (onbr, ls_req);
2232/* ospf_check_nbr_loading (onbr);*//* XXX */
2233 }
2234
2235 return;
2236}
2237
2238void
paul87d6f872004-09-24 08:01:38 +00002239ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr,
paul69310a62005-05-11 18:09:59 +00002240 struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002241{
2242 struct ospf *top;
paul718e3742002-12-13 20:15:29 +00002243 u_char before;
2244
2245 if ((top = oi_to_top (nbr->oi)) == NULL)
Paul Jakma1fe6ed32006-07-26 09:37:26 +00002246 return;
paul718e3742002-12-13 20:15:29 +00002247
2248 before = IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque);
2249
paul69310a62005-05-11 18:09:59 +00002250 /*
2251 * Since these LSA entries are not yet installed into corresponding
2252 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2253 */
2254 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2255 switch (lsa->data->type)
paul718e3742002-12-13 20:15:29 +00002256 {
paul69310a62005-05-11 18:09:59 +00002257 case OSPF_OPAQUE_LINK_LSA:
2258 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
2259 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2260 break;
2261 case OSPF_OPAQUE_AREA_LSA:
2262 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
2263 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2264 break;
2265 case OSPF_OPAQUE_AS_LSA:
2266 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
2267 ospf_flood_through_as (top, NULL/*inbr*/, lsa);
2268 break;
2269 default:
2270 zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
Paul Jakma1fe6ed32006-07-26 09:37:26 +00002271 return;
paul718e3742002-12-13 20:15:29 +00002272 }
2273
paul69310a62005-05-11 18:09:59 +00002274 ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */
2275
paul718e3742002-12-13 20:15:29 +00002276 if (before == 0 && IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2277 {
2278 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002279 zlog_debug ("Block Opaque-LSA origination: OFF -> ON");
paul718e3742002-12-13 20:15:29 +00002280 }
paul718e3742002-12-13 20:15:29 +00002281}
2282
2283void
paul69310a62005-05-11 18:09:59 +00002284ospf_opaque_ls_ack_received (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002285{
2286 struct ospf *top;
paul69310a62005-05-11 18:09:59 +00002287 int delay;
2288 struct ospf_interface *oi;
paul1eb8ef22005-04-07 07:30:20 +00002289 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002290
2291 if ((top = oi_to_top (nbr->oi)) == NULL)
paul69310a62005-05-11 18:09:59 +00002292 return;
2293
2294 if (!IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2295 return;
2296
2297 switch (lsa->data->type)
paul718e3742002-12-13 20:15:29 +00002298 {
paul69310a62005-05-11 18:09:59 +00002299 case OSPF_OPAQUE_LINK_LSA:
2300 if (CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT))
Olivier Dugeon14921062014-11-03 14:59:06 +01002301 UNSET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
2302 /* BUGGY_UNLOCK: ospf_opaque_type9_lsa_rxmt_nbr_check (nbr->oi); */
paul69310a62005-05-11 18:09:59 +00002303 /* Callback function... */
2304 break;
2305 case OSPF_OPAQUE_AREA_LSA:
2306 if (CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT))
Olivier Dugeon14921062014-11-03 14:59:06 +01002307 UNSET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
2308 /* BUGGY_UNLOCK: ospf_opaque_type10_lsa_rxmt_nbr_check (nbr->oi->area); */
paul69310a62005-05-11 18:09:59 +00002309 /* Callback function... */
2310 break;
2311 case OSPF_OPAQUE_AS_LSA:
2312 if (CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT))
Olivier Dugeon14921062014-11-03 14:59:06 +01002313 UNSET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
2314 /* BUGGY_UNLOCK: ospf_opaque_type11_lsa_rxmt_nbr_check (top); */
paul69310a62005-05-11 18:09:59 +00002315 /* Callback function... */
2316 break;
2317 default:
2318 zlog_warn ("ospf_opaque_ls_ack_received: Unexpected LSA-type(%u)", lsa->data->type);
2319 return;
paul718e3742002-12-13 20:15:29 +00002320 }
paul69310a62005-05-11 18:09:59 +00002321
paul718e3742002-12-13 20:15:29 +00002322 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
paul69310a62005-05-11 18:09:59 +00002323 return; /* Blocking still in progress. */
Olivier Dugeon14921062014-11-03 14:59:06 +01002324
2325 if (IS_DEBUG_OSPF_EVENT)
2326 zlog_debug ("Block Opaque-LSA origination: ON -> OFF");
paul69310a62005-05-11 18:09:59 +00002327
2328 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
2329 return; /* Opaque capability condition must have changed. */
paul718e3742002-12-13 20:15:29 +00002330
paul69310a62005-05-11 18:09:59 +00002331 /* Ok, let's start origination of Opaque-LSAs. */
2332 delay = OSPF_MIN_LS_INTERVAL;
2333
2334 for (ALL_LIST_ELEMENTS (top->oiflist, node, nnode, oi))
2335 {
2336 if (! ospf_if_is_enable (oi)
2337 || ospf_nbr_count_opaque_capable (oi) == 0)
2338 continue;
2339
2340 ospf_opaque_lsa_originate_schedule (oi, &delay);
2341 }
2342
paul718e3742002-12-13 20:15:29 +00002343 return;
2344}
2345
Olivier Dugeon14921062014-11-03 14:59:06 +01002346#ifdef BUGGY_UNLOCK
paul718e3742002-12-13 20:15:29 +00002347static void
2348ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi)
2349{
2350 unsigned long n;
2351
2352 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_LINK_LSA);
2353 if (n == 0)
2354 {
2355 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002356 zlog_debug ("Self-originated type-9 Opaque-LSAs: OI(%s): Flush completed", IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00002357
paul68980082003-03-25 05:07:42 +00002358 UNSET_FLAG (oi->area->ospf->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
paul718e3742002-12-13 20:15:29 +00002359 }
2360 return;
2361}
2362
2363static void
2364ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area)
2365{
paul87d6f872004-09-24 08:01:38 +00002366 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002367 struct ospf_interface *oi;
2368 unsigned long n = 0;
2369
paul1eb8ef22005-04-07 07:30:20 +00002370 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00002371 {
paul718e3742002-12-13 20:15:29 +00002372 if (area->area_id.s_addr != OSPF_AREA_BACKBONE
paul1eb8ef22005-04-07 07:30:20 +00002373 && oi->type == OSPF_IFTYPE_VIRTUALLINK)
paul718e3742002-12-13 20:15:29 +00002374 continue;
2375
2376 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AREA_LSA);
2377 if (n > 0)
2378 break;
2379 }
2380
2381 if (n == 0)
2382 {
2383 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002384 zlog_debug ("Self-originated type-10 Opaque-LSAs: AREA(%s): Flush completed", inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00002385
paul68980082003-03-25 05:07:42 +00002386 UNSET_FLAG (area->ospf->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
paul718e3742002-12-13 20:15:29 +00002387 }
2388
2389 return;
2390}
2391
2392static void
2393ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top)
2394{
paul87d6f872004-09-24 08:01:38 +00002395 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002396 struct ospf_interface *oi;
2397 unsigned long n = 0;
2398
paul1eb8ef22005-04-07 07:30:20 +00002399 for (ALL_LIST_ELEMENTS_RO (top->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00002400 {
paul718e3742002-12-13 20:15:29 +00002401 switch (oi->type)
2402 {
2403 case OSPF_IFTYPE_VIRTUALLINK:
2404 continue;
2405 default:
2406 break;
2407 }
2408
2409 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AS_LSA);
2410 if (n > 0)
2411 goto out;
2412 }
2413
2414 if (n == 0)
2415 {
2416 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002417 zlog_debug ("Self-originated type-11 Opaque-LSAs: Flush completed");
paul718e3742002-12-13 20:15:29 +00002418
2419 UNSET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
2420 }
2421
2422out:
2423 return;
2424}
2425
2426static unsigned long
2427ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type)
2428{
2429 struct route_node *rn;
2430 struct ospf_neighbor *nbr;
2431 struct ospf *top;
2432 unsigned long n = 0;
2433
2434 for (rn = route_top (nbrs); rn; rn = route_next (rn))
2435 {
2436 if ((nbr = rn->info) == NULL)
2437 continue;
2438 if ((top = oi_to_top (nbr->oi)) == NULL)
2439 continue;
2440 if (IPV4_ADDR_SAME (&nbr->router_id, &top->router_id))
2441 continue;
2442 n += ospf_ls_retransmit_count_self (nbr, lsa_type);
2443 }
2444
2445 return n;
2446}
Olivier Dugeon14921062014-11-03 14:59:06 +01002447#endif /* BUGGY_UNLOCK */
paul718e3742002-12-13 20:15:29 +00002448
2449/*------------------------------------------------------------------------*
2450 * Followings are util functions; probably be used by Opaque-LSAs only...
2451 *------------------------------------------------------------------------*/
2452
2453void
2454htonf (float *src, float *dst)
2455{
2456 u_int32_t lu1, lu2;
2457
2458 memcpy (&lu1, src, sizeof (u_int32_t));
2459 lu2 = htonl (lu1);
2460 memcpy (dst, &lu2, sizeof (u_int32_t));
2461 return;
2462}
2463
2464void
2465ntohf (float *src, float *dst)
2466{
2467 u_int32_t lu1, lu2;
2468
2469 memcpy (&lu1, src, sizeof (u_int32_t));
2470 lu2 = ntohl (lu1);
2471 memcpy (dst, &lu2, sizeof (u_int32_t));
2472 return;
2473}
2474
2475struct ospf *
2476oi_to_top (struct ospf_interface *oi)
2477{
2478 struct ospf *top = NULL;
2479 struct ospf_area *area;
2480
paul68980082003-03-25 05:07:42 +00002481 if (oi == NULL || (area = oi->area) == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00002482 zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");
2483
2484 return top;
2485}
2486
2487#endif /* HAVE_OPAQUE_LSA */