blob: f584fc71f4306e17f9b2d3313f567ec5cc11f47e [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 }
Paul Jakmae30677a2015-01-20 15:45:36 +00001314
paul718e3742002-12-13 20:15:29 +00001315 if (delay0 != NULL)
1316 delay = *delay0;
1317
1318 /*
1319 * There might be some entries that have been waiting for triggering
1320 * of per opaque-type re-origination get resumed.
1321 */
1322 ospf_opaque_lsa_reoriginate_resume ( oi->opaque_lsa_self, (void *) oi);
1323 ospf_opaque_lsa_reoriginate_resume (area->opaque_lsa_self, (void *) area);
1324 ospf_opaque_lsa_reoriginate_resume ( top->opaque_lsa_self, (void *) top);
1325
1326 /*
1327 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1328 */
1329 if (! list_isempty (ospf_opaque_type9_funclist)
1330 && list_isempty (oi->opaque_lsa_self)
1331 && oi->t_opaque_lsa_self == NULL)
1332 {
1333 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001334 zlog_debug ("Schedule Type-9 Opaque-LSA origination in %d sec later.", delay);
paul718e3742002-12-13 20:15:29 +00001335 oi->t_opaque_lsa_self =
1336 thread_add_timer (master, ospf_opaque_type9_lsa_originate, oi, delay);
1337 delay += OSPF_MIN_LS_INTERVAL;
1338 }
1339
1340 if (! list_isempty (ospf_opaque_type10_funclist)
1341 && list_isempty (area->opaque_lsa_self)
1342 && area->t_opaque_lsa_self == NULL)
1343 {
1344 /*
1345 * One AREA may contain multiple OIs, but above 2nd and 3rd
1346 * conditions prevent from scheduling the originate function
1347 * again and again.
1348 */
1349 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001350 zlog_debug ("Schedule Type-10 Opaque-LSA origination in %d sec later.", delay);
paul718e3742002-12-13 20:15:29 +00001351 area->t_opaque_lsa_self =
1352 thread_add_timer (master, ospf_opaque_type10_lsa_originate,
1353 area, delay);
1354 delay += OSPF_MIN_LS_INTERVAL;
1355 }
1356
1357 if (! list_isempty (ospf_opaque_type11_funclist)
1358 && list_isempty (top->opaque_lsa_self)
1359 && top->t_opaque_lsa_self == NULL)
1360 {
1361 /*
1362 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1363 * conditions prevent from scheduling the originate function
1364 * again and again.
1365 */
1366 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001367 zlog_debug ("Schedule Type-11 Opaque-LSA origination in %d sec later.", delay);
paul718e3742002-12-13 20:15:29 +00001368 top->t_opaque_lsa_self =
1369 thread_add_timer (master, ospf_opaque_type11_lsa_originate,
1370 top, delay);
1371 delay += OSPF_MIN_LS_INTERVAL;
1372 }
1373
1374 /*
1375 * Following section treats a special situation that this node's
1376 * opaque capability has changed as "ON -> OFF -> ON".
1377 */
1378 if (! list_isempty (ospf_opaque_type9_funclist)
1379 && ! list_isempty (oi->opaque_lsa_self))
1380 {
paul1eb8ef22005-04-07 07:30:20 +00001381 for (ALL_LIST_ELEMENTS (oi->opaque_lsa_self, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001382 {
hasso0d85b992004-03-18 19:18:33 +00001383 /*
1384 * removed the test for
1385 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1386 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1387 * not being empty.
1388 */
paul1eb8ef22005-04-07 07:30:20 +00001389 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1390 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001391 continue;
1392
1393 ospf_opaque_lsa_reoriginate_schedule ((void *) oi,
1394 OSPF_OPAQUE_LINK_LSA, oipt->opaque_type);
1395 }
1396 }
1397
1398 if (! list_isempty (ospf_opaque_type10_funclist)
1399 && ! list_isempty (area->opaque_lsa_self))
1400 {
paul1eb8ef22005-04-07 07:30:20 +00001401 for (ALL_LIST_ELEMENTS (area->opaque_lsa_self, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001402 {
hasso0d85b992004-03-18 19:18:33 +00001403 /*
1404 * removed the test for
1405 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1406 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1407 * not being empty.
1408 */
paul1eb8ef22005-04-07 07:30:20 +00001409 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1410 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001411 continue;
1412
1413 ospf_opaque_lsa_reoriginate_schedule ((void *) area,
1414 OSPF_OPAQUE_AREA_LSA, oipt->opaque_type);
1415 }
1416 }
1417
1418 if (! list_isempty (ospf_opaque_type11_funclist)
1419 && ! list_isempty (top->opaque_lsa_self))
1420 {
paul1eb8ef22005-04-07 07:30:20 +00001421 for (ALL_LIST_ELEMENTS (top->opaque_lsa_self, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001422 {
hasso0d85b992004-03-18 19:18:33 +00001423 /*
1424 * removed the test for
1425 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1426 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1427 * not being empty.
1428 */
paul1eb8ef22005-04-07 07:30:20 +00001429 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1430 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001431 continue;
1432
1433 ospf_opaque_lsa_reoriginate_schedule ((void *) top,
1434 OSPF_OPAQUE_AS_LSA, oipt->opaque_type);
1435 }
1436 }
1437
1438 if (delay0 != NULL)
1439 *delay0 = delay;
1440
1441out:
1442 return;
1443}
1444
1445static int
1446ospf_opaque_type9_lsa_originate (struct thread *t)
1447{
1448 struct ospf_interface *oi;
1449 int rc;
1450
1451 oi = THREAD_ARG (t);
1452 oi->t_opaque_lsa_self = NULL;
1453
1454 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001455 zlog_debug ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
paul718e3742002-12-13 20:15:29 +00001456 IF_NAME (oi));
1457
1458 rc = opaque_lsa_originate_callback (ospf_opaque_type9_funclist, oi);
1459
1460 return rc;
1461}
1462
1463static int
1464ospf_opaque_type10_lsa_originate (struct thread *t)
1465{
1466 struct ospf_area *area;
1467 int rc;
1468
1469 area = THREAD_ARG (t);
1470 area->t_opaque_lsa_self = NULL;
1471
1472 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001473 zlog_debug ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
paul718e3742002-12-13 20:15:29 +00001474 inet_ntoa (area->area_id));
1475
1476 rc = opaque_lsa_originate_callback (ospf_opaque_type10_funclist, area);
1477
1478 return rc;
1479}
1480
1481static int
1482ospf_opaque_type11_lsa_originate (struct thread *t)
1483{
1484 struct ospf *top;
1485 int rc;
1486
1487 top = THREAD_ARG (t);
1488 top->t_opaque_lsa_self = NULL;
1489
1490 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001491 zlog_debug ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
paul718e3742002-12-13 20:15:29 +00001492
1493 rc = opaque_lsa_originate_callback (ospf_opaque_type11_funclist, top);
1494
1495 return rc;
1496}
1497
1498static void
paul87d6f872004-09-24 08:01:38 +00001499ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg)
paul718e3742002-12-13 20:15:29 +00001500{
paul1eb8ef22005-04-07 07:30:20 +00001501 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001502 struct opaque_info_per_type *oipt;
1503 struct ospf_opaque_functab *functab;
1504
1505 if (listtop == NULL)
1506 goto out;
1507
1508 /*
1509 * Pickup oipt entries those which in SUSPEND status, and give
1510 * them a chance to start re-origination now.
1511 */
paul1eb8ef22005-04-07 07:30:20 +00001512 for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001513 {
paul87d6f872004-09-24 08:01:38 +00001514 if (oipt->status != PROC_SUSPEND)
paul718e3742002-12-13 20:15:29 +00001515 continue;
1516
1517 oipt->status = PROC_NORMAL;
1518
1519 if ((functab = oipt->functab) == NULL
paul87d6f872004-09-24 08:01:38 +00001520 || functab->lsa_originator == NULL)
paul718e3742002-12-13 20:15:29 +00001521 continue;
1522
1523 if ((* functab->lsa_originator)(arg) != 0)
1524 {
1525 zlog_warn ("ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", oipt->opaque_type);
1526 continue;
1527 }
1528 }
1529
1530out:
1531 return;
1532}
1533
1534struct ospf_lsa *
1535ospf_opaque_lsa_install (struct ospf_lsa *lsa, int rt_recalc)
1536{
1537 struct ospf_lsa *new = NULL;
1538 struct opaque_info_per_type *oipt;
1539 struct opaque_info_per_id *oipi;
1540 struct ospf *top;
1541
1542 /* Don't take "rt_recalc" into consideration for now. *//* XXX */
1543
1544 if (! IS_LSA_SELF (lsa))
1545 {
1546 new = lsa; /* Don't touch this LSA. */
1547 goto out;
1548 }
1549
1550 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
ajs2a42e282004-12-08 18:43:03 +00001551 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 +00001552
1553 /* Replace the existing lsa with the new one. */
1554 if ((oipt = lookup_opaque_info_by_type (lsa)) != NULL
paul87d6f872004-09-24 08:01:38 +00001555 && (oipi = lookup_opaque_info_by_id (oipt, lsa)) != NULL)
paul718e3742002-12-13 20:15:29 +00001556 {
Paul Jakma1fe6ed32006-07-26 09:37:26 +00001557 ospf_lsa_unlock (&oipi->lsa);
paul718e3742002-12-13 20:15:29 +00001558 oipi->lsa = ospf_lsa_lock (lsa);
1559 }
1560 /* Register the new lsa entry and get its control info. */
1561 else
1562 if ((oipi = register_opaque_lsa (lsa)) == NULL)
1563 {
1564 zlog_warn ("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1565 goto out;
1566 }
1567
1568 /*
1569 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1570 * for periodic refresh of self-originated Opaque-LSAs.
1571 */
1572 switch (lsa->data->type)
1573 {
1574 case OSPF_OPAQUE_LINK_LSA:
paul09e4efd2003-01-18 00:12:02 +00001575 if ((top = oi_to_top (lsa->oi)) == NULL)
1576 {
1577 /* Above conditions must have passed. */
1578 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1579 goto out;
1580 }
1581 break;
paul718e3742002-12-13 20:15:29 +00001582 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00001583 if (lsa->area == NULL || (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001584 {
1585 /* Above conditions must have passed. */
1586 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1587 goto out;
1588 }
1589 break;
1590 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +00001591 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001592 if (lsa->area != NULL && (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001593 {
1594 /* Above conditions must have passed. */
1595 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1596 goto out;
1597 }
1598 break;
1599 default:
1600 zlog_warn ("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", lsa->data->type);
1601 goto out;
1602 }
1603
1604 ospf_refresher_register_lsa (top, lsa);
1605 new = lsa;
1606
1607out:
1608 return new;
1609}
1610
Paul Jakmad71ea652011-03-22 15:23:55 +00001611struct ospf_lsa *
paul718e3742002-12-13 20:15:29 +00001612ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
1613{
paul020709f2003-04-04 02:44:16 +00001614 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001615 struct ospf_opaque_functab *functab;
Paul Jakmad71ea652011-03-22 15:23:55 +00001616 struct ospf_lsa *new = NULL;
1617
paul020709f2003-04-04 02:44:16 +00001618 ospf = ospf_lookup ();
1619
paul718e3742002-12-13 20:15:29 +00001620 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL
paul87d6f872004-09-24 08:01:38 +00001621 || functab->lsa_refresher == NULL)
paul718e3742002-12-13 20:15:29 +00001622 {
1623 /*
1624 * Though this LSA seems to have originated on this node, the
1625 * handling module for this "lsa-type and opaque-type" was
1626 * already deleted sometime ago.
1627 * Anyway, this node still has a responsibility to flush this
1628 * LSA from the routing domain.
1629 */
1630 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001631 zlog_debug ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id));
paul718e3742002-12-13 20:15:29 +00001632
1633 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
Paul Jakma02d942c2010-01-24 23:36:20 +00001634 ospf_lsa_flush (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00001635 }
1636 else
Paul Jakmad71ea652011-03-22 15:23:55 +00001637 new = (* functab->lsa_refresher)(lsa);
paul718e3742002-12-13 20:15:29 +00001638
Paul Jakmad71ea652011-03-22 15:23:55 +00001639 return new;
paul718e3742002-12-13 20:15:29 +00001640}
1641
1642/*------------------------------------------------------------------------*
1643 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1644 * triggered by external interventions (vty session, signaling, etc).
1645 *------------------------------------------------------------------------*/
1646
1647#define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
1648 if (!(T)) \
1649 (T) = thread_add_timer (master, (F), (L), (V))
1650
1651static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type);
1652static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t);
1653static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t);
1654static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t);
1655static int ospf_opaque_lsa_refresh_timer (struct thread *t);
1656
1657void
1658ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
1659 u_char lsa_type, u_char opaque_type)
1660{
1661 struct ospf *top;
1662 struct ospf_area dummy, *area = NULL;
1663 struct ospf_interface *oi = NULL;
1664
1665 struct ospf_lsa *lsa;
1666 struct opaque_info_per_type *oipt;
paul87d6f872004-09-24 08:01:38 +00001667 int (*func) (struct thread * t) = NULL;
paul718e3742002-12-13 20:15:29 +00001668 int delay;
1669
1670 switch (lsa_type)
1671 {
1672 case OSPF_OPAQUE_LINK_LSA:
1673 if ((oi = (struct ospf_interface *) lsa_type_dependent) == NULL)
1674 {
paul87d6f872004-09-24 08:01:38 +00001675 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1676 " Type-9 Opaque-LSA: Invalid parameter?");
1677 goto out;
paul718e3742002-12-13 20:15:29 +00001678 }
1679 if ((top = oi_to_top (oi)) == NULL)
1680 {
paul87d6f872004-09-24 08:01:38 +00001681 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1682 IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001683 goto out;
1684 }
paul87d6f872004-09-24 08:01:38 +00001685 if (!list_isempty (ospf_opaque_type9_funclist)
1686 && list_isempty (oi->opaque_lsa_self)
1687 && oi->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001688 {
paul87d6f872004-09-24 08:01:38 +00001689 zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u):"
1690 " Common origination for OI(%s) has already started",
1691 opaque_type, IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001692 goto out;
1693 }
1694 func = ospf_opaque_type9_lsa_reoriginate_timer;
1695 break;
1696 case OSPF_OPAQUE_AREA_LSA:
1697 if ((area = (struct ospf_area *) lsa_type_dependent) == NULL)
1698 {
paul87d6f872004-09-24 08:01:38 +00001699 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1700 " Type-10 Opaque-LSA: Invalid parameter?");
paul718e3742002-12-13 20:15:29 +00001701 goto out;
1702 }
paul68980082003-03-25 05:07:42 +00001703 if ((top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001704 {
paul87d6f872004-09-24 08:01:38 +00001705 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1706 " AREA(%s) -> TOP?", inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001707 goto out;
1708 }
paul87d6f872004-09-24 08:01:38 +00001709 if (!list_isempty (ospf_opaque_type10_funclist)
1710 && list_isempty (area->opaque_lsa_self)
1711 && area->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001712 {
paul87d6f872004-09-24 08:01:38 +00001713 zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u):"
1714 " Common origination for AREA(%s) has already started",
1715 opaque_type, inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001716 goto out;
1717 }
1718 func = ospf_opaque_type10_lsa_reoriginate_timer;
1719 break;
1720 case OSPF_OPAQUE_AS_LSA:
1721 if ((top = (struct ospf *) lsa_type_dependent) == NULL)
1722 {
paul87d6f872004-09-24 08:01:38 +00001723 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1724 " Type-11 Opaque-LSA: Invalid parameter?");
1725 goto out;
paul718e3742002-12-13 20:15:29 +00001726 }
paul87d6f872004-09-24 08:01:38 +00001727 if (!list_isempty (ospf_opaque_type11_funclist)
1728 && list_isempty (top->opaque_lsa_self)
1729 && top->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001730 {
paul87d6f872004-09-24 08:01:38 +00001731 zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u):"
1732 " Common origination has already started", opaque_type);
paul718e3742002-12-13 20:15:29 +00001733 goto out;
1734 }
1735
1736 /* Fake "area" to pass "ospf" to a lookup function later. */
paul68980082003-03-25 05:07:42 +00001737 dummy.ospf = top;
paul718e3742002-12-13 20:15:29 +00001738 area = &dummy;
1739
1740 func = ospf_opaque_type11_lsa_reoriginate_timer;
1741 break;
1742 default:
paul87d6f872004-09-24 08:01:38 +00001743 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1744 " Unexpected LSA-type(%u)",
1745 lsa_type);
paul718e3742002-12-13 20:15:29 +00001746 goto out;
1747 }
1748
1749 /* It may not a right time to schedule reorigination now. */
paul87d6f872004-09-24 08:01:38 +00001750 if (!CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
paul718e3742002-12-13 20:15:29 +00001751 {
1752 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001753 zlog_debug ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
paul87d6f872004-09-24 08:01:38 +00001754 goto out; /* This is not an error. */
paul718e3742002-12-13 20:15:29 +00001755 }
Paul Jakmae30677a2015-01-20 15:45:36 +00001756
paul718e3742002-12-13 20:15:29 +00001757 /* Generate a dummy lsa to be passed for a lookup function. */
1758 lsa = pseudo_lsa (oi, area, lsa_type, opaque_type);
1759
1760 if ((oipt = lookup_opaque_info_by_type (lsa)) == NULL)
1761 {
1762 struct ospf_opaque_functab *functab;
1763 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL)
1764 {
paul87d6f872004-09-24 08:01:38 +00001765 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1766 " No associated function?: lsa_type(%u),"
1767 " opaque_type(%u)",
1768 lsa_type, opaque_type);
paul718e3742002-12-13 20:15:29 +00001769 goto out;
1770 }
1771 if ((oipt = register_opaque_info_per_type (functab, lsa)) == NULL)
1772 {
paul87d6f872004-09-24 08:01:38 +00001773 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1774 " Cannot get a control info?: lsa_type(%u),"
1775 " opaque_type(%u)",
1776 lsa_type, opaque_type);
paul718e3742002-12-13 20:15:29 +00001777 goto out;
1778 }
1779 }
1780
1781 if (oipt->t_opaque_lsa_self != NULL)
1782 {
1783 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001784 zlog_debug ("Type-%u Opaque-LSA has already scheduled to"
paul87d6f872004-09-24 08:01:38 +00001785 " RE-ORIGINATE: [opaque-type=%u]",
1786 lsa_type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
paul718e3742002-12-13 20:15:29 +00001787 goto out;
1788 }
1789
1790 /*
1791 * Different from initial origination time, in which various conditions
1792 * (opaque capability, neighbor status etc) are assured by caller of
1793 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1794 * it is highly possible that these conditions might not be satisfied
1795 * at the time of re-origination function is to be called.
1796 */
1797 delay = OSPF_MIN_LS_INTERVAL; /* XXX */
1798
1799 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001800 zlog_debug ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
paul87d6f872004-09-24 08:01:38 +00001801 " sec later: [opaque-type=%u]",
1802 lsa_type, delay,
1803 GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
paul718e3742002-12-13 20:15:29 +00001804
1805 OSPF_OPAQUE_TIMER_ON (oipt->t_opaque_lsa_self, func, oipt, delay);
1806
1807out:
1808 return;
1809}
1810
1811static struct ospf_lsa *
1812pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area,
1813 u_char lsa_type, u_char opaque_type)
1814{
1815 static struct ospf_lsa lsa = { 0 };
1816 static struct lsa_header lsah = { 0 };
1817 u_int32_t tmp;
1818
1819 lsa.oi = oi;
1820 lsa.area = area;
1821 lsa.data = &lsah;
1822
1823 lsah.type = lsa_type;
1824 tmp = SET_OPAQUE_LSID (opaque_type, 0); /* Opaque-ID is unused here. */
1825 lsah.id.s_addr = htonl (tmp);
1826
1827 return &lsa;
1828}
1829
1830static int
1831ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t)
1832{
1833 struct opaque_info_per_type *oipt;
1834 struct ospf_opaque_functab *functab;
1835 struct ospf *top;
1836 struct ospf_interface *oi;
1837 int rc = -1;
1838
1839 oipt = THREAD_ARG (t);
1840 oipt->t_opaque_lsa_self = NULL;
1841
1842 if ((functab = oipt->functab) == NULL
1843 || functab->lsa_originator == NULL)
1844 {
1845 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1846 goto out;
1847 }
1848
1849 oi = (struct ospf_interface *) oipt->owner;
1850 if ((top = oi_to_top (oi)) == NULL)
1851 {
1852 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1853 goto out;
1854 }
1855
1856 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)
1857 || ! ospf_if_is_enable (oi)
paul68980082003-03-25 05:07:42 +00001858 || ospf_nbr_count_opaque_capable (oi) == 0)
paul718e3742002-12-13 20:15:29 +00001859 {
1860 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001861 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 +00001862
1863 oipt->status = PROC_SUSPEND;
1864 rc = 0;
1865 goto out;
1866 }
1867
1868 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001869 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 +00001870
1871 rc = (* functab->lsa_originator)(oi);
1872out:
1873 return rc;
1874}
1875
1876static int
1877ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t)
1878{
1879 struct opaque_info_per_type *oipt;
1880 struct ospf_opaque_functab *functab;
paul1eb8ef22005-04-07 07:30:20 +00001881 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001882 struct ospf *top;
1883 struct ospf_area *area;
1884 struct ospf_interface *oi;
1885 int n, rc = -1;
1886
1887 oipt = THREAD_ARG (t);
1888 oipt->t_opaque_lsa_self = NULL;
1889
1890 if ((functab = oipt->functab) == NULL
1891 || functab->lsa_originator == NULL)
1892 {
1893 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1894 goto out;
1895 }
1896
1897 area = (struct ospf_area *) oipt->owner;
paul68980082003-03-25 05:07:42 +00001898 if (area == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001899 {
1900 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1901 goto out;
1902 }
1903
1904 /* There must be at least one "opaque-capable, full-state" neighbor. */
1905 n = 0;
paul1eb8ef22005-04-07 07:30:20 +00001906 for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi))
paul718e3742002-12-13 20:15:29 +00001907 {
paul68980082003-03-25 05:07:42 +00001908 if ((n = ospf_nbr_count_opaque_capable (oi)) > 0)
paul718e3742002-12-13 20:15:29 +00001909 break;
1910 }
1911
1912 if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1913 {
1914 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001915 zlog_debug ("Suspend re-origination of Type-10 Opaque-LSAs"
paul87d6f872004-09-24 08:01:38 +00001916 " (opaque-type=%u) for a while...",
1917 oipt->opaque_type);
paul718e3742002-12-13 20:15:29 +00001918
1919 oipt->status = PROC_SUSPEND;
1920 rc = 0;
1921 goto out;
1922 }
1923
1924 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001925 zlog_debug ("Timer[Type10-LSA]: Re-originate Opaque-LSAs"
paul87d6f872004-09-24 08:01:38 +00001926 " (opaque-type=%u) for Area %s",
1927 oipt->opaque_type, inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001928
1929 rc = (* functab->lsa_originator)(area);
1930out:
1931 return rc;
1932}
1933
1934static int
1935ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t)
1936{
1937 struct opaque_info_per_type *oipt;
1938 struct ospf_opaque_functab *functab;
1939 struct ospf *top;
1940 int rc = -1;
1941
1942 oipt = THREAD_ARG (t);
1943 oipt->t_opaque_lsa_self = NULL;
1944
1945 if ((functab = oipt->functab) == NULL
paul87d6f872004-09-24 08:01:38 +00001946 || functab->lsa_originator == NULL)
paul718e3742002-12-13 20:15:29 +00001947 {
paul87d6f872004-09-24 08:01:38 +00001948 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer:"
1949 " No associated function?");
paul718e3742002-12-13 20:15:29 +00001950 goto out;
1951 }
1952
1953 if ((top = (struct ospf *) oipt->owner) == NULL)
1954 {
1955 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1956 goto out;
1957 }
1958
1959 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1960 {
1961 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001962 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 +00001963
1964 oipt->status = PROC_SUSPEND;
1965 rc = 0;
1966 goto out;
1967 }
1968
1969 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001970 zlog_debug ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type);
paul718e3742002-12-13 20:15:29 +00001971
1972 rc = (* functab->lsa_originator)(top);
1973out:
1974 return rc;
1975}
1976
paul718e3742002-12-13 20:15:29 +00001977void
1978ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
1979{
1980 struct opaque_info_per_type *oipt;
1981 struct opaque_info_per_id *oipi;
1982 struct ospf_lsa *lsa;
1983 int delay;
1984
1985 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
1986 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
1987 {
1988 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
1989 goto out;
1990 }
1991
1992 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
1993 if ((lsa = oipi->lsa) == NULL)
1994 {
1995 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
1996 goto out;
1997 }
1998
1999 if (oipi->t_opaque_lsa_self != NULL)
2000 {
2001 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002002 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 +00002003 goto out;
2004 }
2005
2006 /* Delete this lsa from neighbor retransmit-list. */
2007 switch (lsa->data->type)
2008 {
2009 case OSPF_OPAQUE_LINK_LSA:
2010 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002011 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002012 break;
2013 case OSPF_OPAQUE_AS_LSA:
ajse6a0bf92005-09-17 18:53:38 +00002014 ospf_ls_retransmit_delete_nbr_as (lsa0->area->ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002015 break;
2016 default:
2017 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2018 goto out;
2019 }
2020
2021 delay = ospf_lsa_refresh_delay (lsa);
2022
2023 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002024 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 +00002025
2026 OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self,
2027 ospf_opaque_lsa_refresh_timer, oipi, delay);
2028out:
2029 return;
2030}
2031
2032static int
2033ospf_opaque_lsa_refresh_timer (struct thread *t)
2034{
2035 struct opaque_info_per_id *oipi;
2036 struct ospf_opaque_functab *functab;
2037 struct ospf_lsa *lsa;
2038
2039 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002040 zlog_debug ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
paul718e3742002-12-13 20:15:29 +00002041
2042 oipi = THREAD_ARG (t);
2043 oipi->t_opaque_lsa_self = NULL;
2044
2045 if ((lsa = oipi->lsa) != NULL)
2046 if ((functab = oipi->opqctl_type->functab) != NULL)
2047 if (functab->lsa_refresher != NULL)
2048 (* functab->lsa_refresher)(lsa);
2049
2050 return 0;
2051}
2052
2053void
2054ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
2055{
2056 struct opaque_info_per_type *oipt;
2057 struct opaque_info_per_id *oipi;
2058 struct ospf_lsa *lsa;
2059
2060 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
2061 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
2062 {
2063 zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2064 goto out;
2065 }
2066
2067 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2068 if ((lsa = oipi->lsa) == NULL)
2069 {
2070 zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
2071 goto out;
2072 }
2073
2074 /* Delete this lsa from neighbor retransmit-list. */
2075 switch (lsa->data->type)
2076 {
2077 case OSPF_OPAQUE_LINK_LSA:
2078 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002079 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002080 break;
2081 case OSPF_OPAQUE_AS_LSA:
ajse6a0bf92005-09-17 18:53:38 +00002082 ospf_ls_retransmit_delete_nbr_as (lsa0->area->ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002083 break;
2084 default:
2085 zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2086 goto out;
2087 }
2088
2089 /* Dequeue listnode entry from the list. */
2090 listnode_delete (oipt->id_list, oipi);
2091
2092 /* Avoid misjudgement in the next lookup. */
2093 if (listcount (oipt->id_list) == 0)
2094 oipt->id_list->head = oipt->id_list->tail = NULL;
2095
2096 /* Disassociate internal control information with the given lsa. */
paul718e3742002-12-13 20:15:29 +00002097 free_opaque_info_per_id ((void *) oipi);
2098
2099 /* Force given lsa's age to MaxAge. */
2100 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2101
2102 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002103 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 +00002104
2105 /* This lsa will be flushed and removed eventually. */
Paul Jakma02d942c2010-01-24 23:36:20 +00002106 ospf_lsa_flush (lsa0->area->ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002107
2108out:
2109 return;
2110}
2111
paul718e3742002-12-13 20:15:29 +00002112void
paul87d6f872004-09-24 08:01:38 +00002113ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr,
paul69310a62005-05-11 18:09:59 +00002114 struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002115{
2116 struct ospf *top;
Paul Jakmae30677a2015-01-20 15:45:36 +00002117
paul718e3742002-12-13 20:15:29 +00002118 if ((top = oi_to_top (nbr->oi)) == NULL)
Paul Jakma1fe6ed32006-07-26 09:37:26 +00002119 return;
paul718e3742002-12-13 20:15:29 +00002120
paul69310a62005-05-11 18:09:59 +00002121 /*
2122 * Since these LSA entries are not yet installed into corresponding
2123 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2124 */
2125 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2126 switch (lsa->data->type)
paul718e3742002-12-13 20:15:29 +00002127 {
paul69310a62005-05-11 18:09:59 +00002128 case OSPF_OPAQUE_LINK_LSA:
paul69310a62005-05-11 18:09:59 +00002129 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2130 break;
2131 case OSPF_OPAQUE_AREA_LSA:
paul69310a62005-05-11 18:09:59 +00002132 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2133 break;
2134 case OSPF_OPAQUE_AS_LSA:
paul69310a62005-05-11 18:09:59 +00002135 ospf_flood_through_as (top, NULL/*inbr*/, lsa);
2136 break;
2137 default:
2138 zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
Paul Jakma1fe6ed32006-07-26 09:37:26 +00002139 return;
paul718e3742002-12-13 20:15:29 +00002140 }
Paul Jakmae30677a2015-01-20 15:45:36 +00002141 ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */
paul718e3742002-12-13 20:15:29 +00002142}
2143
paul718e3742002-12-13 20:15:29 +00002144/*------------------------------------------------------------------------*
2145 * Followings are util functions; probably be used by Opaque-LSAs only...
2146 *------------------------------------------------------------------------*/
2147
2148void
2149htonf (float *src, float *dst)
2150{
2151 u_int32_t lu1, lu2;
2152
2153 memcpy (&lu1, src, sizeof (u_int32_t));
2154 lu2 = htonl (lu1);
2155 memcpy (dst, &lu2, sizeof (u_int32_t));
2156 return;
2157}
2158
2159void
2160ntohf (float *src, float *dst)
2161{
2162 u_int32_t lu1, lu2;
2163
2164 memcpy (&lu1, src, sizeof (u_int32_t));
2165 lu2 = ntohl (lu1);
2166 memcpy (dst, &lu2, sizeof (u_int32_t));
2167 return;
2168}
2169
2170struct ospf *
2171oi_to_top (struct ospf_interface *oi)
2172{
2173 struct ospf *top = NULL;
2174 struct ospf_area *area;
2175
paul68980082003-03-25 05:07:42 +00002176 if (oi == NULL || (area = oi->area) == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00002177 zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");
2178
2179 return top;
2180}
2181
2182#endif /* HAVE_OPAQUE_LSA */