blob: 215676e61441f913b3754d9345c28bafef34631c [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>
paul718e3742002-12-13 20:15:29 +000030
31#include "linklist.h"
32#include "prefix.h"
33#include "if.h"
34#include "table.h"
35#include "memory.h"
36#include "command.h"
37#include "vty.h"
38#include "stream.h"
39#include "log.h"
40#include "thread.h"
41#include "hash.h"
42#include "sockunion.h" /* for inet_aton() */
43
44#include "ospfd/ospfd.h"
45#include "ospfd/ospf_interface.h"
46#include "ospfd/ospf_ism.h"
47#include "ospfd/ospf_asbr.h"
48#include "ospfd/ospf_lsa.h"
49#include "ospfd/ospf_lsdb.h"
50#include "ospfd/ospf_neighbor.h"
51#include "ospfd/ospf_nsm.h"
52#include "ospfd/ospf_flood.h"
53#include "ospfd/ospf_packet.h"
54#include "ospfd/ospf_spf.h"
55#include "ospfd/ospf_dump.h"
56#include "ospfd/ospf_route.h"
57#include "ospfd/ospf_ase.h"
58#include "ospfd/ospf_zebra.h"
59
60/*------------------------------------------------------------------------*
61 * Followings are initialize/terminate functions for Opaque-LSAs handling.
62 *------------------------------------------------------------------------*/
63
64#ifdef HAVE_OSPF_TE
65#include "ospfd/ospf_te.h"
66#endif /* HAVE_OSPF_TE */
67
paul283ae332003-03-17 01:16:55 +000068#ifdef SUPPORT_OSPF_API
69int ospf_apiserver_init (void);
70void ospf_apiserver_term (void);
hassof4d58ce2004-10-12 06:13:54 +000071/* Init apiserver? It's disabled by default. */
72int ospf_apiserver_enable;
paul283ae332003-03-17 01:16:55 +000073#endif /* SUPPORT_OSPF_API */
74
paul718e3742002-12-13 20:15:29 +000075static void ospf_opaque_register_vty (void);
76static void ospf_opaque_funclist_init (void);
77static void ospf_opaque_funclist_term (void);
78static void free_opaque_info_per_type (void *val);
79static void free_opaque_info_per_id (void *val);
80static int ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa);
81static int ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa);
82
83void
84ospf_opaque_init (void)
85{
86 ospf_opaque_register_vty ();
87 ospf_opaque_funclist_init ();
88
89#ifdef HAVE_OSPF_TE
90 if (ospf_mpls_te_init () != 0)
91 exit (1);
92#endif /* HAVE_OSPF_TE */
93
paul283ae332003-03-17 01:16:55 +000094#ifdef SUPPORT_OSPF_API
hassoc3abdb72004-10-11 16:27:03 +000095 if ((ospf_apiserver_enable) && (ospf_apiserver_init () != 0))
paul283ae332003-03-17 01:16:55 +000096 exit (1);
97#endif /* SUPPORT_OSPF_API */
98
paul718e3742002-12-13 20:15:29 +000099 return;
100}
101
102void
103ospf_opaque_term (void)
104{
105#ifdef HAVE_OSPF_TE
106 ospf_mpls_te_term ();
107#endif /* HAVE_OSPF_TE */
108
paul283ae332003-03-17 01:16:55 +0000109#ifdef SUPPORT_OSPF_API
110 ospf_apiserver_term ();
111#endif /* SUPPORT_OSPF_API */
112
paul718e3742002-12-13 20:15:29 +0000113 ospf_opaque_funclist_term ();
114 return;
115}
116
117int
118ospf_opaque_type9_lsa_init (struct ospf_interface *oi)
119{
120 if (oi->opaque_lsa_self != NULL)
121 list_delete (oi->opaque_lsa_self);
122
123 oi->opaque_lsa_self = list_new ();
124 oi->opaque_lsa_self->del = free_opaque_info_per_type;
125 oi->t_opaque_lsa_self = NULL;
126 return 0;
127}
128
129void
130ospf_opaque_type9_lsa_term (struct ospf_interface *oi)
131{
132 OSPF_TIMER_OFF (oi->t_opaque_lsa_self);
133 if (oi->opaque_lsa_self != NULL)
134 list_delete (oi->opaque_lsa_self);
135 oi->opaque_lsa_self = NULL;
136 return;
137}
138
139int
140ospf_opaque_type10_lsa_init (struct ospf_area *area)
141{
142 if (area->opaque_lsa_self != NULL)
143 list_delete (area->opaque_lsa_self);
144
145 area->opaque_lsa_self = list_new ();
146 area->opaque_lsa_self->del = free_opaque_info_per_type;
147 area->t_opaque_lsa_self = NULL;
148
149#ifdef MONITOR_LSDB_CHANGE
150 area->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
151 area->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
152#endif /* MONITOR_LSDB_CHANGE */
153 return 0;
154}
155
156void
157ospf_opaque_type10_lsa_term (struct ospf_area *area)
158{
159#ifdef MONITOR_LSDB_CHANGE
160 area->lsdb->new_lsa_hook =
161 area->lsdb->del_lsa_hook = NULL;
162#endif /* MONITOR_LSDB_CHANGE */
163
164 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
165 if (area->opaque_lsa_self != NULL)
166 list_delete (area->opaque_lsa_self);
167 area->opaque_lsa_self = NULL;
168 return;
169}
170
171int
172ospf_opaque_type11_lsa_init (struct ospf *top)
173{
174 if (top->opaque_lsa_self != NULL)
175 list_delete (top->opaque_lsa_self);
176
177 top->opaque_lsa_self = list_new ();
178 top->opaque_lsa_self->del = free_opaque_info_per_type;
179 top->t_opaque_lsa_self = NULL;
180
181#ifdef MONITOR_LSDB_CHANGE
182 top->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
183 top->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
184#endif /* MONITOR_LSDB_CHANGE */
185 return 0;
186}
187
188void
189ospf_opaque_type11_lsa_term (struct ospf *top)
190{
191#ifdef MONITOR_LSDB_CHANGE
192 top->lsdb->new_lsa_hook =
193 top->lsdb->del_lsa_hook = NULL;
194#endif /* MONITOR_LSDB_CHANGE */
195
196 OSPF_TIMER_OFF (top->t_opaque_lsa_self);
197 if (top->opaque_lsa_self != NULL)
198 list_delete (top->opaque_lsa_self);
199 top->opaque_lsa_self = NULL;
200 return;
201}
202
203static const char *
204ospf_opaque_type_name (u_char opaque_type)
205{
206 const char *name = "Unknown";
207
208 switch (opaque_type)
209 {
210 case OPAQUE_TYPE_WILDCARD: /* This is a special assignment! */
211 name = "Wildcard";
212 break;
213 case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA:
214 name = "Traffic Engineering LSA";
215 break;
216 case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC:
217 name = "Sycamore optical topology description";
218 break;
219 case OPAQUE_TYPE_GRACE_LSA:
220 name = "Grace-LSA";
221 break;
222 default:
223 if (OPAQUE_TYPE_RANGE_UNASSIGNED (opaque_type))
224 name = "Unassigned";
Andrew Certain0798cee2012-12-04 13:43:42 -0800225 else
226 {
227 u_int32_t bigger_range = opaque_type;
228 /*
229 * Get around type-limits warning: comparison is always true due to limited range of data type
230 */
231 if (OPAQUE_TYPE_RANGE_RESERVED (bigger_range))
232 name = "Private/Experimental";
233 }
paul718e3742002-12-13 20:15:29 +0000234 break;
235 }
236 return name;
237}
238
239/*------------------------------------------------------------------------*
240 * Followings are management functions to store user specified callbacks.
241 *------------------------------------------------------------------------*/
242
243struct opaque_info_per_type; /* Forward declaration. */
244
245struct ospf_opaque_functab
246{
247 u_char opaque_type;
248 struct opaque_info_per_type *oipt;
249
250 int (* new_if_hook)(struct interface *ifp);
251 int (* del_if_hook)(struct interface *ifp);
252 void (* ism_change_hook)(struct ospf_interface *oi, int old_status);
253 void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status);
254 void (* config_write_router)(struct vty *vty);
255 void (* config_write_if )(struct vty *vty, struct interface *ifp);
256 void (* config_write_debug )(struct vty *vty);
257 void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa);
258 int (* lsa_originator)(void *arg);
Paul Jakmad71ea652011-03-22 15:23:55 +0000259 struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa);
paul718e3742002-12-13 20:15:29 +0000260 int (* new_lsa_hook)(struct ospf_lsa *lsa);
261 int (* del_lsa_hook)(struct ospf_lsa *lsa);
262};
263
paul87d6f872004-09-24 08:01:38 +0000264/* Handle LSA-9/10/11 altogether. */
265static struct list *ospf_opaque_wildcard_funclist;
266static struct list *ospf_opaque_type9_funclist;
267static struct list *ospf_opaque_type10_funclist;
268static struct list *ospf_opaque_type11_funclist;
paul718e3742002-12-13 20:15:29 +0000269
270static void
271ospf_opaque_del_functab (void *val)
272{
273 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, val);
274 return;
275}
276
277static void
278ospf_opaque_funclist_init (void)
279{
paul87d6f872004-09-24 08:01:38 +0000280 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000281
paul09e4efd2003-01-18 00:12:02 +0000282 funclist = ospf_opaque_wildcard_funclist = list_new ();
283 funclist->del = ospf_opaque_del_functab;
284
paul718e3742002-12-13 20:15:29 +0000285 funclist = ospf_opaque_type9_funclist = list_new ();
286 funclist->del = ospf_opaque_del_functab;
287
288 funclist = ospf_opaque_type10_funclist = list_new ();
289 funclist->del = ospf_opaque_del_functab;
290
291 funclist = ospf_opaque_type11_funclist = list_new ();
292 funclist->del = ospf_opaque_del_functab;
293 return;
294}
295
296static void
297ospf_opaque_funclist_term (void)
298{
paul87d6f872004-09-24 08:01:38 +0000299 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000300
paul09e4efd2003-01-18 00:12:02 +0000301 funclist = ospf_opaque_wildcard_funclist;
302 list_delete (funclist);
303
paul718e3742002-12-13 20:15:29 +0000304 funclist = ospf_opaque_type9_funclist;
305 list_delete (funclist);
306
307 funclist = ospf_opaque_type10_funclist;
308 list_delete (funclist);
309
310 funclist = ospf_opaque_type11_funclist;
311 list_delete (funclist);
312 return;
313}
314
paul87d6f872004-09-24 08:01:38 +0000315static struct list *
paul718e3742002-12-13 20:15:29 +0000316ospf_get_opaque_funclist (u_char lsa_type)
317{
paul87d6f872004-09-24 08:01:38 +0000318 struct list *funclist = NULL;
paul718e3742002-12-13 20:15:29 +0000319
320 switch (lsa_type)
321 {
paul09e4efd2003-01-18 00:12:02 +0000322 case OPAQUE_TYPE_WILDCARD:
323 /* XXX
324 * This is an ugly trick to handle type-9/10/11 LSA altogether.
325 * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor
326 * an officially assigned opaque-type.
327 * Though it is possible that the value might be officially used
328 * in the future, we use it internally as a special label, for now.
329 */
330 funclist = ospf_opaque_wildcard_funclist;
331 break;
paul718e3742002-12-13 20:15:29 +0000332 case OSPF_OPAQUE_LINK_LSA:
333 funclist = ospf_opaque_type9_funclist;
334 break;
335 case OSPF_OPAQUE_AREA_LSA:
336 funclist = ospf_opaque_type10_funclist;
337 break;
338 case OSPF_OPAQUE_AS_LSA:
339 funclist = ospf_opaque_type11_funclist;
340 break;
341 default:
342 zlog_warn ("ospf_get_opaque_funclist: Unexpected LSA-type(%u)", lsa_type);
343 break;
344 }
345 return funclist;
346}
347
paul87d6f872004-09-24 08:01:38 +0000348/* XXX: such a huge argument list can /not/ be healthy... */
paul718e3742002-12-13 20:15:29 +0000349int
350ospf_register_opaque_functab (
351 u_char lsa_type,
352 u_char opaque_type,
353 int (* new_if_hook)(struct interface *ifp),
354 int (* del_if_hook)(struct interface *ifp),
355 void (* ism_change_hook)(struct ospf_interface *oi, int old_status),
356 void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status),
357 void (* config_write_router)(struct vty *vty),
358 void (* config_write_if )(struct vty *vty, struct interface *ifp),
359 void (* config_write_debug )(struct vty *vty),
360 void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa),
361 int (* lsa_originator)(void *arg),
Paul Jakmad71ea652011-03-22 15:23:55 +0000362 struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa),
paul718e3742002-12-13 20:15:29 +0000363 int (* new_lsa_hook)(struct ospf_lsa *lsa),
364 int (* del_lsa_hook)(struct ospf_lsa *lsa))
365{
paul87d6f872004-09-24 08:01:38 +0000366 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000367 struct ospf_opaque_functab *new;
368 int rc = -1;
369
370 if ((funclist = ospf_get_opaque_funclist (lsa_type)) == NULL)
371 {
paul87d6f872004-09-24 08:01:38 +0000372 zlog_warn ("ospf_register_opaque_functab: Cannot get funclist"
373 " for Type-%u LSAs?",
374 lsa_type);
paul718e3742002-12-13 20:15:29 +0000375 goto out;
376 }
377 else
378 {
paul1eb8ef22005-04-07 07:30:20 +0000379 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000380 struct ospf_opaque_functab *functab;
paul87d6f872004-09-24 08:01:38 +0000381
paul1eb8ef22005-04-07 07:30:20 +0000382 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000383 if (functab->opaque_type == opaque_type)
384 {
385 zlog_warn ("ospf_register_opaque_functab: Duplicated entry?:"
386 " lsa_type(%u), opaque_type(%u)",
387 lsa_type, opaque_type);
388 goto out;
389 }
paul718e3742002-12-13 20:15:29 +0000390 }
391
392 if ((new = XCALLOC (MTYPE_OSPF_OPAQUE_FUNCTAB,
393 sizeof (struct ospf_opaque_functab))) == NULL)
394 {
paul87d6f872004-09-24 08:01:38 +0000395 zlog_warn ("ospf_register_opaque_functab: XMALLOC: %s",
ajs6099b3b2004-11-20 02:06:59 +0000396 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000397 goto out;
398 }
399
400 new->opaque_type = opaque_type;
401 new->oipt = NULL;
402 new->new_if_hook = new_if_hook;
403 new->del_if_hook = del_if_hook;
404 new->ism_change_hook = ism_change_hook;
405 new->nsm_change_hook = nsm_change_hook;
406 new->config_write_router = config_write_router;
407 new->config_write_if = config_write_if;
408 new->config_write_debug = config_write_debug;
409 new->show_opaque_info = show_opaque_info;
410 new->lsa_originator = lsa_originator;
411 new->lsa_refresher = lsa_refresher;
412 new->new_lsa_hook = new_lsa_hook;
413 new->del_lsa_hook = del_lsa_hook;
414
415 listnode_add (funclist, new);
416 rc = 0;
417
418out:
419 return rc;
420}
421
422void
423ospf_delete_opaque_functab (u_char lsa_type, u_char opaque_type)
424{
paul87d6f872004-09-24 08:01:38 +0000425 struct list *funclist;
paul1eb8ef22005-04-07 07:30:20 +0000426 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000427 struct ospf_opaque_functab *functab;
428
429 if ((funclist = ospf_get_opaque_funclist (lsa_type)) != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000430 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul718e3742002-12-13 20:15:29 +0000431 {
paul1eb8ef22005-04-07 07:30:20 +0000432 if (functab->opaque_type == opaque_type)
paul718e3742002-12-13 20:15:29 +0000433 {
434 /* Cleanup internal control information, if it still remains. */
435 if (functab->oipt != NULL)
436 free_opaque_info_per_type (functab->oipt);
437
438 /* Dequeue listnode entry from the list. */
439 listnode_delete (funclist, functab);
440
441 /* Avoid misjudgement in the next lookup. */
442 if (listcount (funclist) == 0)
443 funclist->head = funclist->tail = NULL;
444
445 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, functab);
paul87d6f872004-09-24 08:01:38 +0000446 break;
paul718e3742002-12-13 20:15:29 +0000447 }
448 }
paul87d6f872004-09-24 08:01:38 +0000449
paul718e3742002-12-13 20:15:29 +0000450 return;
451}
452
453static struct ospf_opaque_functab *
454ospf_opaque_functab_lookup (struct ospf_lsa *lsa)
455{
paul87d6f872004-09-24 08:01:38 +0000456 struct list *funclist;
457 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000458 struct ospf_opaque_functab *functab;
459 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
460
461 if ((funclist = ospf_get_opaque_funclist (lsa->data->type)) != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000462 for (ALL_LIST_ELEMENTS_RO (funclist, node, functab))
paul87d6f872004-09-24 08:01:38 +0000463 if (functab->opaque_type == key)
464 return functab;
paul718e3742002-12-13 20:15:29 +0000465
466 return NULL;
467}
468
469/*------------------------------------------------------------------------*
470 * Followings are management functions for self-originated LSA entries.
471 *------------------------------------------------------------------------*/
472
473/*
474 * Opaque-LSA control information per opaque-type.
475 * Single Opaque-Type may have multiple instances; each of them will be
476 * identified by their opaque-id.
477 */
478struct opaque_info_per_type
479{
paul09e4efd2003-01-18 00:12:02 +0000480 u_char lsa_type;
paul718e3742002-12-13 20:15:29 +0000481 u_char opaque_type;
482
483 enum { PROC_NORMAL, PROC_SUSPEND } status;
484
485 /*
486 * Thread for (re-)origination scheduling for this opaque-type.
487 *
488 * Initial origination of Opaque-LSAs is controlled by generic
489 * Opaque-LSA handling module so that same opaque-type entries are
490 * called all at once when certain conditions are met.
491 * However, there might be cases that some Opaque-LSA clients need
492 * to (re-)originate their own Opaque-LSAs out-of-sync with others.
493 * This thread is prepared for that specific purpose.
494 */
495 struct thread *t_opaque_lsa_self;
496
497 /*
paul09e4efd2003-01-18 00:12:02 +0000498 * Backpointer to an "owner" which is LSA-type dependent.
paul718e3742002-12-13 20:15:29 +0000499 * type-9: struct ospf_interface
500 * type-10: struct ospf_area
501 * type-11: struct ospf
502 */
503 void *owner;
504
505 /* Collection of callback functions for this opaque-type. */
506 struct ospf_opaque_functab *functab;
507
508 /* List of Opaque-LSA control informations per opaque-id. */
paul87d6f872004-09-24 08:01:38 +0000509 struct list *id_list;
paul718e3742002-12-13 20:15:29 +0000510};
511
512/* Opaque-LSA control information per opaque-id. */
513struct opaque_info_per_id
514{
515 u_int32_t opaque_id;
516
517 /* Thread for refresh/flush scheduling for this opaque-type/id. */
518 struct thread *t_opaque_lsa_self;
519
520 /* Backpointer to Opaque-LSA control information per opaque-type. */
521 struct opaque_info_per_type *opqctl_type;
522
523 /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
524 struct ospf_lsa *lsa;
525};
526
527static struct opaque_info_per_type *register_opaque_info_per_type (struct ospf_opaque_functab *functab, struct ospf_lsa *new);
528static struct opaque_info_per_type *lookup_opaque_info_by_type (struct ospf_lsa *lsa);
529static struct opaque_info_per_id *register_opaque_info_per_id (struct opaque_info_per_type *oipt, struct ospf_lsa *new);
530static struct opaque_info_per_id *lookup_opaque_info_by_id (struct opaque_info_per_type *oipt, struct ospf_lsa *lsa);
531static struct opaque_info_per_id *register_opaque_lsa (struct ospf_lsa *new);
532
533
534static struct opaque_info_per_type *
535register_opaque_info_per_type (struct ospf_opaque_functab *functab,
536 struct ospf_lsa *new)
537{
538 struct ospf *top;
539 struct opaque_info_per_type *oipt;
540
541 if ((oipt = XCALLOC (MTYPE_OPAQUE_INFO_PER_TYPE,
542 sizeof (struct opaque_info_per_type))) == NULL)
543 {
ajs6099b3b2004-11-20 02:06:59 +0000544 zlog_warn ("register_opaque_info_per_type: XMALLOC: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000545 goto out;
546 }
547
548 switch (new->data->type)
549 {
550 case OSPF_OPAQUE_LINK_LSA:
551 oipt->owner = new->oi;
552 listnode_add (new->oi->opaque_lsa_self, oipt);
553 break;
554 case OSPF_OPAQUE_AREA_LSA:
555 oipt->owner = new->area;
556 listnode_add (new->area->opaque_lsa_self, oipt);
557 break;
558 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +0000559 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000560 if (new->area != NULL && (top = new->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +0000561 {
562 free_opaque_info_per_type ((void *) oipt);
563 oipt = NULL;
564 goto out; /* This case may not exist. */
565 }
566 oipt->owner = top;
567 listnode_add (top->opaque_lsa_self, oipt);
568 break;
569 default:
paul09e4efd2003-01-18 00:12:02 +0000570 zlog_warn ("register_opaque_info_per_type: Unexpected LSA-type(%u)", new->data->type);
paul718e3742002-12-13 20:15:29 +0000571 free_opaque_info_per_type ((void *) oipt);
572 oipt = NULL;
573 goto out; /* This case may not exist. */
574 }
575
paul09e4efd2003-01-18 00:12:02 +0000576 oipt->lsa_type = new->data->type;
paul718e3742002-12-13 20:15:29 +0000577 oipt->opaque_type = GET_OPAQUE_TYPE (ntohl (new->data->id.s_addr));
578 oipt->status = PROC_NORMAL;
579 oipt->t_opaque_lsa_self = NULL;
580 oipt->functab = functab;
581 functab->oipt = oipt;
582 oipt->id_list = list_new ();
583 oipt->id_list->del = free_opaque_info_per_id;
584
585out:
586 return oipt;
587}
588
589static void
590free_opaque_info_per_type (void *val)
591{
592 struct opaque_info_per_type *oipt = (struct opaque_info_per_type *) val;
593 struct opaque_info_per_id *oipi;
594 struct ospf_lsa *lsa;
paul1eb8ef22005-04-07 07:30:20 +0000595 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000596
597 /* Control information per opaque-id may still exist. */
paul1eb8ef22005-04-07 07:30:20 +0000598 for (ALL_LIST_ELEMENTS (oipt->id_list, node, nnode, oipi))
paul718e3742002-12-13 20:15:29 +0000599 {
paul718e3742002-12-13 20:15:29 +0000600 if ((lsa = oipi->lsa) == NULL)
601 continue;
602 if (IS_LSA_MAXAGE (lsa))
603 continue;
604 ospf_opaque_lsa_flush_schedule (lsa);
605 }
606
paul09e4efd2003-01-18 00:12:02 +0000607 /* Remove "oipt" from its owner's self-originated LSA list. */
608 switch (oipt->lsa_type)
609 {
610 case OSPF_OPAQUE_LINK_LSA:
611 {
612 struct ospf_interface *oi = (struct ospf_interface *)(oipt->owner);
613 listnode_delete (oi->opaque_lsa_self, oipt);
614 break;
615 }
616 case OSPF_OPAQUE_AREA_LSA:
617 {
618 struct ospf_area *area = (struct ospf_area *)(oipt->owner);
619 listnode_delete (area->opaque_lsa_self, oipt);
620 break;
621 }
622 case OSPF_OPAQUE_AS_LSA:
623 {
624 struct ospf *top = (struct ospf *)(oipt->owner);
625 listnode_delete (top->opaque_lsa_self, oipt);
626 break;
627 }
628 default:
629 zlog_warn ("free_opaque_info_per_type: Unexpected LSA-type(%u)", oipt->lsa_type);
630 break; /* This case may not exist. */
631 }
632
paul718e3742002-12-13 20:15:29 +0000633 OSPF_TIMER_OFF (oipt->t_opaque_lsa_self);
634 list_delete (oipt->id_list);
635 XFREE (MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
636 return;
637}
638
639static struct opaque_info_per_type *
640lookup_opaque_info_by_type (struct ospf_lsa *lsa)
641{
642 struct ospf *top;
643 struct ospf_area *area;
644 struct ospf_interface *oi;
paul87d6f872004-09-24 08:01:38 +0000645 struct list *listtop = NULL;
paul1eb8ef22005-04-07 07:30:20 +0000646 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000647 struct opaque_info_per_type *oipt = NULL;
648 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
649
650 switch (lsa->data->type)
651 {
652 case OSPF_OPAQUE_LINK_LSA:
653 if ((oi = lsa->oi) != NULL)
654 listtop = oi->opaque_lsa_self;
655 else
656 zlog_warn ("Type-9 Opaque-LSA: Reference to OI is missing?");
657 break;
658 case OSPF_OPAQUE_AREA_LSA:
659 if ((area = lsa->area) != NULL)
660 listtop = area->opaque_lsa_self;
661 else
662 zlog_warn ("Type-10 Opaque-LSA: Reference to AREA is missing?");
663 break;
664 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +0000665 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000666 if ((area = lsa->area) != NULL && (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +0000667 {
668 zlog_warn ("Type-11 Opaque-LSA: Reference to OSPF is missing?");
669 break; /* Unlikely to happen. */
670 }
671 listtop = top->opaque_lsa_self;
672 break;
673 default:
674 zlog_warn ("lookup_opaque_info_by_type: Unexpected LSA-type(%u)", lsa->data->type);
675 break;
676 }
677
678 if (listtop != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000679 for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt))
paul87d6f872004-09-24 08:01:38 +0000680 if (oipt->opaque_type == key)
681 return oipt;
paul718e3742002-12-13 20:15:29 +0000682
683 return NULL;
684}
685
686static struct opaque_info_per_id *
687register_opaque_info_per_id (struct opaque_info_per_type *oipt,
688 struct ospf_lsa *new)
689{
690 struct opaque_info_per_id *oipi;
691
692 if ((oipi = XCALLOC (MTYPE_OPAQUE_INFO_PER_ID,
693 sizeof (struct opaque_info_per_id))) == NULL)
694 {
ajs6099b3b2004-11-20 02:06:59 +0000695 zlog_warn ("register_opaque_info_per_id: XMALLOC: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000696 goto out;
697 }
698 oipi->opaque_id = GET_OPAQUE_ID (ntohl (new->data->id.s_addr));
699 oipi->t_opaque_lsa_self = NULL;
700 oipi->opqctl_type = oipt;
701 oipi->lsa = ospf_lsa_lock (new);
702
703 listnode_add (oipt->id_list, oipi);
704
705out:
706 return oipi;
707}
708
709static void
710free_opaque_info_per_id (void *val)
711{
712 struct opaque_info_per_id *oipi = (struct opaque_info_per_id *) val;
713
714 OSPF_TIMER_OFF (oipi->t_opaque_lsa_self);
715 if (oipi->lsa != NULL)
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000716 ospf_lsa_unlock (&oipi->lsa);
paul718e3742002-12-13 20:15:29 +0000717 XFREE (MTYPE_OPAQUE_INFO_PER_ID, oipi);
718 return;
719}
720
721static struct opaque_info_per_id *
722lookup_opaque_info_by_id (struct opaque_info_per_type *oipt,
723 struct ospf_lsa *lsa)
724{
paul1eb8ef22005-04-07 07:30:20 +0000725 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000726 struct opaque_info_per_id *oipi;
727 u_int32_t key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
728
paul1eb8ef22005-04-07 07:30:20 +0000729 for (ALL_LIST_ELEMENTS (oipt->id_list, node, nnode, oipi))
paul87d6f872004-09-24 08:01:38 +0000730 if (oipi->opaque_id == key)
731 return oipi;
paul718e3742002-12-13 20:15:29 +0000732
733 return NULL;
734}
735
736static struct opaque_info_per_id *
737register_opaque_lsa (struct ospf_lsa *new)
738{
739 struct ospf_opaque_functab *functab;
740 struct opaque_info_per_type *oipt;
741 struct opaque_info_per_id *oipi = NULL;
742
743 if ((functab = ospf_opaque_functab_lookup (new)) == NULL)
744 goto out;
745
746 if ((oipt = lookup_opaque_info_by_type (new)) == NULL
747 && (oipt = register_opaque_info_per_type (functab, new)) == NULL)
748 goto out;
749
750 if ((oipi = register_opaque_info_per_id (oipt, new)) == NULL)
751 goto out;
752
753out:
754 return oipi;
755}
756
757/*------------------------------------------------------------------------*
758 * Followings are (vty) configuration functions for Opaque-LSAs handling.
759 *------------------------------------------------------------------------*/
760
761DEFUN (capability_opaque,
762 capability_opaque_cmd,
763 "capability opaque",
764 "Enable specific OSPF feature\n"
765 "Opaque LSA\n")
766{
767 struct ospf *ospf = (struct ospf *) vty->index;
768
769 /* Turn on the "master switch" of opaque-lsa capability. */
770 if (!CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
771 {
772 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000773 zlog_debug ("Opaque capability: OFF -> ON");
paul718e3742002-12-13 20:15:29 +0000774
775 SET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
776 ospf_renegotiate_optional_capabilities (ospf);
777 }
778 return CMD_SUCCESS;
779}
780
781ALIAS (capability_opaque,
782 ospf_opaque_capable_cmd,
783 "ospf opaque-lsa",
784 "OSPF specific commands\n"
785 "Enable the Opaque-LSA capability (rfc2370)\n")
786
787DEFUN (no_capability_opaque,
788 no_capability_opaque_cmd,
789 "no capability opaque",
790 NO_STR
791 "Enable specific OSPF feature\n"
792 "Opaque LSA\n")
793{
794 struct ospf *ospf = (struct ospf *) vty->index;
795
796 /* Turn off the "master switch" of opaque-lsa capability. */
797 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
798 {
799 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000800 zlog_debug ("Opaque capability: ON -> OFF");
paul718e3742002-12-13 20:15:29 +0000801
802 UNSET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
803 ospf_renegotiate_optional_capabilities (ospf);
804 }
805 return CMD_SUCCESS;
806}
807
808ALIAS (no_capability_opaque,
809 no_ospf_opaque_capable_cmd,
810 "no ospf opaque-lsa",
811 NO_STR
812 "OSPF specific commands\n"
813 "Disable the Opaque-LSA capability (rfc2370)\n")
814
815static void
816ospf_opaque_register_vty (void)
817{
818 install_element (OSPF_NODE, &capability_opaque_cmd);
819 install_element (OSPF_NODE, &no_capability_opaque_cmd);
820 install_element (OSPF_NODE, &ospf_opaque_capable_cmd);
821 install_element (OSPF_NODE, &no_ospf_opaque_capable_cmd);
822 return;
823}
824
825/*------------------------------------------------------------------------*
826 * Followings are collection of user-registered function callers.
827 *------------------------------------------------------------------------*/
828
829static int
paul87d6f872004-09-24 08:01:38 +0000830opaque_lsa_new_if_callback (struct list *funclist, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000831{
paul1eb8ef22005-04-07 07:30:20 +0000832 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000833 struct ospf_opaque_functab *functab;
834 int rc = -1;
835
paul1eb8ef22005-04-07 07:30:20 +0000836 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000837 if (functab->new_if_hook != NULL)
838 if ((* functab->new_if_hook)(ifp) != 0)
839 goto out;
paul718e3742002-12-13 20:15:29 +0000840 rc = 0;
841out:
842 return rc;
843}
844
845static int
paul87d6f872004-09-24 08:01:38 +0000846opaque_lsa_del_if_callback (struct list *funclist, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000847{
paul1eb8ef22005-04-07 07:30:20 +0000848 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000849 struct ospf_opaque_functab *functab;
850 int rc = -1;
851
paul1eb8ef22005-04-07 07:30:20 +0000852 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000853 if (functab->del_if_hook != NULL)
854 if ((* functab->del_if_hook)(ifp) != 0)
855 goto out;
paul718e3742002-12-13 20:15:29 +0000856 rc = 0;
857out:
858 return rc;
859}
860
861static void
paul87d6f872004-09-24 08:01:38 +0000862opaque_lsa_ism_change_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000863 struct ospf_interface *oi, int old_status)
864{
paul1eb8ef22005-04-07 07:30:20 +0000865 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000866 struct ospf_opaque_functab *functab;
867
paul1eb8ef22005-04-07 07:30:20 +0000868 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000869 if (functab->ism_change_hook != NULL)
870 (* functab->ism_change_hook)(oi, old_status);
871
paul718e3742002-12-13 20:15:29 +0000872 return;
873}
874
875static void
paul87d6f872004-09-24 08:01:38 +0000876opaque_lsa_nsm_change_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000877 struct ospf_neighbor *nbr, int old_status)
878{
paul1eb8ef22005-04-07 07:30:20 +0000879 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000880 struct ospf_opaque_functab *functab;
881
paul1eb8ef22005-04-07 07:30:20 +0000882 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000883 if (functab->nsm_change_hook != NULL)
884 (* functab->nsm_change_hook)(nbr, old_status);
paul718e3742002-12-13 20:15:29 +0000885 return;
886}
887
888static void
paul87d6f872004-09-24 08:01:38 +0000889opaque_lsa_config_write_router_callback (struct list *funclist,
890 struct vty *vty)
paul718e3742002-12-13 20:15:29 +0000891{
paul1eb8ef22005-04-07 07:30:20 +0000892 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000893 struct ospf_opaque_functab *functab;
894
paul1eb8ef22005-04-07 07:30:20 +0000895 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000896 if (functab->config_write_router != NULL)
897 (* functab->config_write_router)(vty);
paul718e3742002-12-13 20:15:29 +0000898 return;
899}
900
901static void
paul87d6f872004-09-24 08:01:38 +0000902opaque_lsa_config_write_if_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000903 struct vty *vty, struct interface *ifp)
904{
paul1eb8ef22005-04-07 07:30:20 +0000905 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000906 struct ospf_opaque_functab *functab;
907
paul1eb8ef22005-04-07 07:30:20 +0000908 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000909 if (functab->config_write_if != NULL)
910 (* functab->config_write_if)(vty, ifp);
paul718e3742002-12-13 20:15:29 +0000911 return;
912}
913
914static void
paul87d6f872004-09-24 08:01:38 +0000915opaque_lsa_config_write_debug_callback (struct list *funclist, struct vty *vty)
paul718e3742002-12-13 20:15:29 +0000916{
paul1eb8ef22005-04-07 07:30:20 +0000917 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000918 struct ospf_opaque_functab *functab;
919
paul1eb8ef22005-04-07 07:30:20 +0000920 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000921 if (functab->config_write_debug != NULL)
922 (* functab->config_write_debug)(vty);
paul718e3742002-12-13 20:15:29 +0000923 return;
924}
925
926static int
paul87d6f872004-09-24 08:01:38 +0000927opaque_lsa_originate_callback (struct list *funclist, void *lsa_type_dependent)
paul718e3742002-12-13 20:15:29 +0000928{
paul1eb8ef22005-04-07 07:30:20 +0000929 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000930 struct ospf_opaque_functab *functab;
931 int rc = -1;
932
paul1eb8ef22005-04-07 07:30:20 +0000933 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000934 if (functab->lsa_originator != NULL)
935 if ((* functab->lsa_originator)(lsa_type_dependent) != 0)
936 goto out;
paul718e3742002-12-13 20:15:29 +0000937 rc = 0;
938out:
939 return rc;
940}
941
942static int
paul87d6f872004-09-24 08:01:38 +0000943new_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000944{
paul1eb8ef22005-04-07 07:30:20 +0000945 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000946 struct ospf_opaque_functab *functab;
947 int rc = -1;
948
949 /* This function handles ALL types of LSAs, not only opaque ones. */
paul1eb8ef22005-04-07 07:30:20 +0000950 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000951 if (functab->new_lsa_hook != NULL)
952 if ((* functab->new_lsa_hook)(lsa) != 0)
953 goto out;
paul718e3742002-12-13 20:15:29 +0000954 rc = 0;
955out:
956 return rc;
957}
958
959static int
paul87d6f872004-09-24 08:01:38 +0000960del_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000961{
paul1eb8ef22005-04-07 07:30:20 +0000962 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000963 struct ospf_opaque_functab *functab;
964 int rc = -1;
965
966 /* This function handles ALL types of LSAs, not only opaque ones. */
paul1eb8ef22005-04-07 07:30:20 +0000967 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000968 if (functab->del_lsa_hook != NULL)
969 if ((* functab->del_lsa_hook)(lsa) != 0)
970 goto out;
paul718e3742002-12-13 20:15:29 +0000971 rc = 0;
972out:
973 return rc;
974}
975
976/*------------------------------------------------------------------------*
977 * Followings are glue functions to call Opaque-LSA specific processing.
978 *------------------------------------------------------------------------*/
979
980int
981ospf_opaque_new_if (struct interface *ifp)
982{
paul87d6f872004-09-24 08:01:38 +0000983 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000984 int rc = -1;
985
paul09e4efd2003-01-18 00:12:02 +0000986 funclist = ospf_opaque_wildcard_funclist;
987 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
988 goto out;
989
paul718e3742002-12-13 20:15:29 +0000990 funclist = ospf_opaque_type9_funclist;
991 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
992 goto out;
993
994 funclist = ospf_opaque_type10_funclist;
995 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
996 goto out;
997
998 funclist = ospf_opaque_type11_funclist;
999 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
1000 goto out;
1001
1002 rc = 0;
1003out:
1004 return rc;
1005}
1006
1007int
1008ospf_opaque_del_if (struct interface *ifp)
1009{
paul87d6f872004-09-24 08:01:38 +00001010 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001011 int rc = -1;
1012
paul09e4efd2003-01-18 00:12:02 +00001013 funclist = ospf_opaque_wildcard_funclist;
1014 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1015 goto out;
1016
paul718e3742002-12-13 20:15:29 +00001017 funclist = ospf_opaque_type9_funclist;
1018 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1019 goto out;
1020
1021 funclist = ospf_opaque_type10_funclist;
1022 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1023 goto out;
1024
1025 funclist = ospf_opaque_type11_funclist;
1026 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1027 goto out;
1028
1029 rc = 0;
1030out:
1031 return rc;
1032}
1033
1034void
1035ospf_opaque_ism_change (struct ospf_interface *oi, int old_status)
1036{
paul87d6f872004-09-24 08:01:38 +00001037 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001038
paul09e4efd2003-01-18 00:12:02 +00001039 funclist = ospf_opaque_wildcard_funclist;
1040 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1041
paul718e3742002-12-13 20:15:29 +00001042 funclist = ospf_opaque_type9_funclist;
1043 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1044
1045 funclist = ospf_opaque_type10_funclist;
1046 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1047
1048 funclist = ospf_opaque_type11_funclist;
1049 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1050
1051 return;
1052}
1053
1054void
1055ospf_opaque_nsm_change (struct ospf_neighbor *nbr, int old_state)
1056{
1057 struct ospf *top;
paul87d6f872004-09-24 08:01:38 +00001058 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001059
1060 if ((top = oi_to_top (nbr->oi)) == NULL)
1061 goto out;
1062
1063 if (old_state != NSM_Full && nbr->state == NSM_Full)
1064 {
1065 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
1066 {
1067 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1068 {
1069 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001070 zlog_debug ("Opaque-LSA: Now get operational!");
paul718e3742002-12-13 20:15:29 +00001071
1072 SET_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT);
1073 }
1074
1075 ospf_opaque_lsa_originate_schedule (nbr->oi, NULL);
1076 }
1077 }
1078 else
1079 if (old_state == NSM_Full && nbr->state != NSM_Full)
1080 {
1081#ifdef NOTYET
1082 /*
1083 * If no more opaque-capable full-state neighbor remains in the
1084 * flooding scope which corresponds to Opaque-LSA type, periodic
1085 * LS flooding should be stopped.
1086 */
1087#endif /* NOTYET */
1088 ;
1089 }
1090
paul09e4efd2003-01-18 00:12:02 +00001091 funclist = ospf_opaque_wildcard_funclist;
1092 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1093
paul718e3742002-12-13 20:15:29 +00001094 funclist = ospf_opaque_type9_funclist;
1095 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1096
1097 funclist = ospf_opaque_type10_funclist;
1098 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1099
1100 funclist = ospf_opaque_type11_funclist;
1101 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1102
1103out:
1104 return;
1105}
1106
1107void
1108ospf_opaque_config_write_router (struct vty *vty, struct ospf *ospf)
1109{
paul87d6f872004-09-24 08:01:38 +00001110 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001111
1112 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
1113 vty_out (vty, " capability opaque%s", VTY_NEWLINE);
1114
paul09e4efd2003-01-18 00:12:02 +00001115 funclist = ospf_opaque_wildcard_funclist;
1116 opaque_lsa_config_write_router_callback (funclist, vty);
1117
paul718e3742002-12-13 20:15:29 +00001118 funclist = ospf_opaque_type9_funclist;
1119 opaque_lsa_config_write_router_callback (funclist, vty);
1120
1121 funclist = ospf_opaque_type10_funclist;
1122 opaque_lsa_config_write_router_callback (funclist, vty);
1123
1124 funclist = ospf_opaque_type11_funclist;
1125 opaque_lsa_config_write_router_callback (funclist, vty);
1126
1127 return;
1128}
1129
1130void
1131ospf_opaque_config_write_if (struct vty *vty, struct interface *ifp)
1132{
paul87d6f872004-09-24 08:01:38 +00001133 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001134
paul09e4efd2003-01-18 00:12:02 +00001135 funclist = ospf_opaque_wildcard_funclist;
1136 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1137
paul718e3742002-12-13 20:15:29 +00001138 funclist = ospf_opaque_type9_funclist;
1139 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1140
1141 funclist = ospf_opaque_type10_funclist;
1142 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1143
1144 funclist = ospf_opaque_type11_funclist;
1145 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1146
1147 return;
1148}
1149
1150void
1151ospf_opaque_config_write_debug (struct vty *vty)
1152{
paul87d6f872004-09-24 08:01:38 +00001153 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001154
paul09e4efd2003-01-18 00:12:02 +00001155 funclist = ospf_opaque_wildcard_funclist;
1156 opaque_lsa_config_write_debug_callback (funclist, vty);
1157
paul718e3742002-12-13 20:15:29 +00001158 funclist = ospf_opaque_type9_funclist;
1159 opaque_lsa_config_write_debug_callback (funclist, vty);
1160
1161 funclist = ospf_opaque_type10_funclist;
1162 opaque_lsa_config_write_debug_callback (funclist, vty);
1163
1164 funclist = ospf_opaque_type11_funclist;
1165 opaque_lsa_config_write_debug_callback (funclist, vty);
1166
1167 return;
1168}
1169
1170void
1171show_opaque_info_detail (struct vty *vty, struct ospf_lsa *lsa)
1172{
1173 struct lsa_header *lsah = (struct lsa_header *) lsa->data;
1174 u_int32_t lsid = ntohl (lsah->id.s_addr);
1175 u_char opaque_type = GET_OPAQUE_TYPE (lsid);
1176 u_int32_t opaque_id = GET_OPAQUE_ID (lsid);
1177 struct ospf_opaque_functab *functab;
1178
1179 /* Switch output functionality by vty address. */
1180 if (vty != NULL)
1181 {
paul020709f2003-04-04 02:44:16 +00001182 vty_out (vty, " Opaque-Type %u (%s)%s", opaque_type,
1183 ospf_opaque_type_name (opaque_type), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001184 vty_out (vty, " Opaque-ID 0x%x%s", opaque_id, VTY_NEWLINE);
1185
1186 vty_out (vty, " Opaque-Info: %u octets of data%s%s",
1187 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1188 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)",
1189 VTY_NEWLINE);
1190 }
1191 else
1192 {
ajs2a42e282004-12-08 18:43:03 +00001193 zlog_debug (" Opaque-Type %u (%s)", opaque_type,
paul020709f2003-04-04 02:44:16 +00001194 ospf_opaque_type_name (opaque_type));
ajs2a42e282004-12-08 18:43:03 +00001195 zlog_debug (" Opaque-ID 0x%x", opaque_id);
paul718e3742002-12-13 20:15:29 +00001196
ajs2a42e282004-12-08 18:43:03 +00001197 zlog_debug (" Opaque-Info: %u octets of data%s",
paul718e3742002-12-13 20:15:29 +00001198 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1199 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)");
1200 }
1201
1202 /* Call individual output functions. */
1203 if ((functab = ospf_opaque_functab_lookup (lsa)) != NULL)
1204 if (functab->show_opaque_info != NULL)
1205 (* functab->show_opaque_info)(vty, lsa);
1206
1207 return;
1208}
1209
1210void
1211ospf_opaque_lsa_dump (struct stream *s, u_int16_t length)
1212{
1213 struct ospf_lsa lsa;
1214
1215 lsa.data = (struct lsa_header *) STREAM_PNT (s);
1216 show_opaque_info_detail (NULL, &lsa);
1217 return;
1218}
1219
1220static int
1221ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa)
1222{
paul87d6f872004-09-24 08:01:38 +00001223 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001224 int rc = -1;
1225
1226 /*
1227 * Some Opaque-LSA user may want to monitor every LSA installation
1228 * into the LSDB, regardless with target LSA type.
1229 */
paul09e4efd2003-01-18 00:12:02 +00001230 funclist = ospf_opaque_wildcard_funclist;
1231 if (new_lsa_callback (funclist, lsa) != 0)
1232 goto out;
1233
paul718e3742002-12-13 20:15:29 +00001234 funclist = ospf_opaque_type9_funclist;
1235 if (new_lsa_callback (funclist, lsa) != 0)
1236 goto out;
1237
1238 funclist = ospf_opaque_type10_funclist;
1239 if (new_lsa_callback (funclist, lsa) != 0)
1240 goto out;
1241
1242 funclist = ospf_opaque_type11_funclist;
1243 if (new_lsa_callback (funclist, lsa) != 0)
1244 goto out;
1245
1246 rc = 0;
1247out:
1248 return rc;
1249}
1250
1251static int
1252ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa)
1253{
paul87d6f872004-09-24 08:01:38 +00001254 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001255 int rc = -1;
1256
1257 /*
1258 * Some Opaque-LSA user may want to monitor every LSA deletion
1259 * from the LSDB, regardless with target LSA type.
1260 */
paul09e4efd2003-01-18 00:12:02 +00001261 funclist = ospf_opaque_wildcard_funclist;
1262 if (del_lsa_callback (funclist, lsa) != 0)
1263 goto out;
1264
paul718e3742002-12-13 20:15:29 +00001265 funclist = ospf_opaque_type9_funclist;
1266 if (del_lsa_callback (funclist, lsa) != 0)
1267 goto out;
1268
1269 funclist = ospf_opaque_type10_funclist;
1270 if (del_lsa_callback (funclist, lsa) != 0)
1271 goto out;
1272
1273 funclist = ospf_opaque_type11_funclist;
1274 if (del_lsa_callback (funclist, lsa) != 0)
1275 goto out;
1276
1277 rc = 0;
1278out:
1279 return rc;
1280}
1281
1282/*------------------------------------------------------------------------*
1283 * Followings are Opaque-LSA origination/refresh management functions.
1284 *------------------------------------------------------------------------*/
1285
1286static int ospf_opaque_type9_lsa_originate (struct thread *t);
1287static int ospf_opaque_type10_lsa_originate (struct thread *t);
1288static int ospf_opaque_type11_lsa_originate (struct thread *t);
paul87d6f872004-09-24 08:01:38 +00001289static void ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg);
paul718e3742002-12-13 20:15:29 +00001290
1291void
1292ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0)
1293{
1294 struct ospf *top;
1295 struct ospf_area *area;
paul1eb8ef22005-04-07 07:30:20 +00001296 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001297 struct opaque_info_per_type *oipt;
1298 int delay = 0;
1299
1300 if ((top = oi_to_top (oi)) == NULL || (area = oi->area) == NULL)
1301 {
1302 zlog_warn ("ospf_opaque_lsa_originate_schedule: Invalid argument?");
1303 goto out;
1304 }
1305
1306 /* It may not a right time to schedule origination now. */
1307 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1308 {
1309 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001310 zlog_debug ("ospf_opaque_lsa_originate_schedule: Not operational.");
paul718e3742002-12-13 20:15:29 +00001311 goto out; /* This is not an error. */
1312 }
Paul Jakmae30677a2015-01-20 15:45:36 +00001313
paul718e3742002-12-13 20:15:29 +00001314 if (delay0 != NULL)
1315 delay = *delay0;
1316
1317 /*
1318 * There might be some entries that have been waiting for triggering
1319 * of per opaque-type re-origination get resumed.
1320 */
1321 ospf_opaque_lsa_reoriginate_resume ( oi->opaque_lsa_self, (void *) oi);
1322 ospf_opaque_lsa_reoriginate_resume (area->opaque_lsa_self, (void *) area);
1323 ospf_opaque_lsa_reoriginate_resume ( top->opaque_lsa_self, (void *) top);
1324
1325 /*
1326 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1327 */
1328 if (! list_isempty (ospf_opaque_type9_funclist)
1329 && list_isempty (oi->opaque_lsa_self)
1330 && oi->t_opaque_lsa_self == NULL)
1331 {
1332 if (IS_DEBUG_OSPF_EVENT)
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001333 zlog_debug ("Schedule Type-9 Opaque-LSA origination in %d ms later.", delay);
paul718e3742002-12-13 20:15:29 +00001334 oi->t_opaque_lsa_self =
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001335 thread_add_timer_msec (master, ospf_opaque_type9_lsa_originate, oi, delay);
1336 delay += top->min_ls_interval;
paul718e3742002-12-13 20:15:29 +00001337 }
1338
1339 if (! list_isempty (ospf_opaque_type10_funclist)
1340 && list_isempty (area->opaque_lsa_self)
1341 && area->t_opaque_lsa_self == NULL)
1342 {
1343 /*
1344 * One AREA may contain multiple OIs, but above 2nd and 3rd
1345 * conditions prevent from scheduling the originate function
1346 * again and again.
1347 */
1348 if (IS_DEBUG_OSPF_EVENT)
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001349 zlog_debug ("Schedule Type-10 Opaque-LSA origination in %d ms later.", delay);
paul718e3742002-12-13 20:15:29 +00001350 area->t_opaque_lsa_self =
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001351 thread_add_timer_msec (master, ospf_opaque_type10_lsa_originate,
paul718e3742002-12-13 20:15:29 +00001352 area, delay);
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001353 delay += top->min_ls_interval;
paul718e3742002-12-13 20:15:29 +00001354 }
1355
1356 if (! list_isempty (ospf_opaque_type11_funclist)
1357 && list_isempty (top->opaque_lsa_self)
1358 && top->t_opaque_lsa_self == NULL)
1359 {
1360 /*
1361 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1362 * conditions prevent from scheduling the originate function
1363 * again and again.
1364 */
1365 if (IS_DEBUG_OSPF_EVENT)
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001366 zlog_debug ("Schedule Type-11 Opaque-LSA origination in %d ms later.", delay);
paul718e3742002-12-13 20:15:29 +00001367 top->t_opaque_lsa_self =
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001368 thread_add_timer_msec (master, ospf_opaque_type11_lsa_originate,
paul718e3742002-12-13 20:15:29 +00001369 top, delay);
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001370 delay += top->min_ls_interval;
paul718e3742002-12-13 20:15:29 +00001371 }
1372
1373 /*
1374 * Following section treats a special situation that this node's
1375 * opaque capability has changed as "ON -> OFF -> ON".
1376 */
1377 if (! list_isempty (ospf_opaque_type9_funclist)
1378 && ! list_isempty (oi->opaque_lsa_self))
1379 {
paul1eb8ef22005-04-07 07:30:20 +00001380 for (ALL_LIST_ELEMENTS (oi->opaque_lsa_self, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001381 {
hasso0d85b992004-03-18 19:18:33 +00001382 /*
1383 * removed the test for
1384 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1385 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1386 * not being empty.
1387 */
paul1eb8ef22005-04-07 07:30:20 +00001388 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1389 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001390 continue;
1391
1392 ospf_opaque_lsa_reoriginate_schedule ((void *) oi,
1393 OSPF_OPAQUE_LINK_LSA, oipt->opaque_type);
1394 }
1395 }
1396
1397 if (! list_isempty (ospf_opaque_type10_funclist)
1398 && ! list_isempty (area->opaque_lsa_self))
1399 {
paul1eb8ef22005-04-07 07:30:20 +00001400 for (ALL_LIST_ELEMENTS (area->opaque_lsa_self, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001401 {
hasso0d85b992004-03-18 19:18:33 +00001402 /*
1403 * removed the test for
1404 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1405 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1406 * not being empty.
1407 */
paul1eb8ef22005-04-07 07:30:20 +00001408 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1409 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001410 continue;
1411
1412 ospf_opaque_lsa_reoriginate_schedule ((void *) area,
1413 OSPF_OPAQUE_AREA_LSA, oipt->opaque_type);
1414 }
1415 }
1416
1417 if (! list_isempty (ospf_opaque_type11_funclist)
1418 && ! list_isempty (top->opaque_lsa_self))
1419 {
paul1eb8ef22005-04-07 07:30:20 +00001420 for (ALL_LIST_ELEMENTS (top->opaque_lsa_self, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001421 {
hasso0d85b992004-03-18 19:18:33 +00001422 /*
1423 * removed the test for
1424 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1425 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1426 * not being empty.
1427 */
paul1eb8ef22005-04-07 07:30:20 +00001428 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1429 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001430 continue;
1431
1432 ospf_opaque_lsa_reoriginate_schedule ((void *) top,
1433 OSPF_OPAQUE_AS_LSA, oipt->opaque_type);
1434 }
1435 }
1436
1437 if (delay0 != NULL)
1438 *delay0 = delay;
1439
1440out:
1441 return;
1442}
1443
1444static int
1445ospf_opaque_type9_lsa_originate (struct thread *t)
1446{
1447 struct ospf_interface *oi;
1448 int rc;
1449
1450 oi = THREAD_ARG (t);
1451 oi->t_opaque_lsa_self = NULL;
1452
1453 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001454 zlog_debug ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
paul718e3742002-12-13 20:15:29 +00001455 IF_NAME (oi));
1456
1457 rc = opaque_lsa_originate_callback (ospf_opaque_type9_funclist, oi);
1458
1459 return rc;
1460}
1461
1462static int
1463ospf_opaque_type10_lsa_originate (struct thread *t)
1464{
1465 struct ospf_area *area;
1466 int rc;
1467
1468 area = THREAD_ARG (t);
1469 area->t_opaque_lsa_self = NULL;
1470
1471 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001472 zlog_debug ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
paul718e3742002-12-13 20:15:29 +00001473 inet_ntoa (area->area_id));
1474
1475 rc = opaque_lsa_originate_callback (ospf_opaque_type10_funclist, area);
1476
1477 return rc;
1478}
1479
1480static int
1481ospf_opaque_type11_lsa_originate (struct thread *t)
1482{
1483 struct ospf *top;
1484 int rc;
1485
1486 top = THREAD_ARG (t);
1487 top->t_opaque_lsa_self = NULL;
1488
1489 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001490 zlog_debug ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
paul718e3742002-12-13 20:15:29 +00001491
1492 rc = opaque_lsa_originate_callback (ospf_opaque_type11_funclist, top);
1493
1494 return rc;
1495}
1496
1497static void
paul87d6f872004-09-24 08:01:38 +00001498ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg)
paul718e3742002-12-13 20:15:29 +00001499{
paul1eb8ef22005-04-07 07:30:20 +00001500 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001501 struct opaque_info_per_type *oipt;
1502 struct ospf_opaque_functab *functab;
1503
1504 if (listtop == NULL)
1505 goto out;
1506
1507 /*
1508 * Pickup oipt entries those which in SUSPEND status, and give
1509 * them a chance to start re-origination now.
1510 */
paul1eb8ef22005-04-07 07:30:20 +00001511 for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001512 {
paul87d6f872004-09-24 08:01:38 +00001513 if (oipt->status != PROC_SUSPEND)
paul718e3742002-12-13 20:15:29 +00001514 continue;
1515
1516 oipt->status = PROC_NORMAL;
1517
1518 if ((functab = oipt->functab) == NULL
paul87d6f872004-09-24 08:01:38 +00001519 || functab->lsa_originator == NULL)
paul718e3742002-12-13 20:15:29 +00001520 continue;
1521
1522 if ((* functab->lsa_originator)(arg) != 0)
1523 {
1524 zlog_warn ("ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", oipt->opaque_type);
1525 continue;
1526 }
1527 }
1528
1529out:
1530 return;
1531}
1532
1533struct ospf_lsa *
1534ospf_opaque_lsa_install (struct ospf_lsa *lsa, int rt_recalc)
1535{
1536 struct ospf_lsa *new = NULL;
1537 struct opaque_info_per_type *oipt;
1538 struct opaque_info_per_id *oipi;
1539 struct ospf *top;
1540
1541 /* Don't take "rt_recalc" into consideration for now. *//* XXX */
1542
1543 if (! IS_LSA_SELF (lsa))
1544 {
1545 new = lsa; /* Don't touch this LSA. */
1546 goto out;
1547 }
1548
1549 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
ajs2a42e282004-12-08 18:43:03 +00001550 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 +00001551
1552 /* Replace the existing lsa with the new one. */
1553 if ((oipt = lookup_opaque_info_by_type (lsa)) != NULL
paul87d6f872004-09-24 08:01:38 +00001554 && (oipi = lookup_opaque_info_by_id (oipt, lsa)) != NULL)
paul718e3742002-12-13 20:15:29 +00001555 {
Paul Jakma1fe6ed32006-07-26 09:37:26 +00001556 ospf_lsa_unlock (&oipi->lsa);
paul718e3742002-12-13 20:15:29 +00001557 oipi->lsa = ospf_lsa_lock (lsa);
1558 }
1559 /* Register the new lsa entry and get its control info. */
1560 else
1561 if ((oipi = register_opaque_lsa (lsa)) == NULL)
1562 {
1563 zlog_warn ("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1564 goto out;
1565 }
1566
1567 /*
1568 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1569 * for periodic refresh of self-originated Opaque-LSAs.
1570 */
1571 switch (lsa->data->type)
1572 {
1573 case OSPF_OPAQUE_LINK_LSA:
paul09e4efd2003-01-18 00:12:02 +00001574 if ((top = oi_to_top (lsa->oi)) == NULL)
1575 {
1576 /* Above conditions must have passed. */
1577 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1578 goto out;
1579 }
1580 break;
paul718e3742002-12-13 20:15:29 +00001581 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00001582 if (lsa->area == NULL || (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001583 {
1584 /* Above conditions must have passed. */
1585 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1586 goto out;
1587 }
1588 break;
1589 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +00001590 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001591 if (lsa->area != NULL && (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001592 {
1593 /* Above conditions must have passed. */
1594 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1595 goto out;
1596 }
1597 break;
1598 default:
1599 zlog_warn ("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", lsa->data->type);
1600 goto out;
1601 }
1602
1603 ospf_refresher_register_lsa (top, lsa);
1604 new = lsa;
1605
1606out:
1607 return new;
1608}
1609
Paul Jakmad71ea652011-03-22 15:23:55 +00001610struct ospf_lsa *
paul718e3742002-12-13 20:15:29 +00001611ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
1612{
paul020709f2003-04-04 02:44:16 +00001613 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001614 struct ospf_opaque_functab *functab;
Paul Jakmad71ea652011-03-22 15:23:55 +00001615 struct ospf_lsa *new = NULL;
1616
paul020709f2003-04-04 02:44:16 +00001617 ospf = ospf_lookup ();
1618
paul718e3742002-12-13 20:15:29 +00001619 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL
paul87d6f872004-09-24 08:01:38 +00001620 || functab->lsa_refresher == NULL)
paul718e3742002-12-13 20:15:29 +00001621 {
1622 /*
1623 * Though this LSA seems to have originated on this node, the
1624 * handling module for this "lsa-type and opaque-type" was
1625 * already deleted sometime ago.
1626 * Anyway, this node still has a responsibility to flush this
1627 * LSA from the routing domain.
1628 */
1629 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001630 zlog_debug ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id));
paul718e3742002-12-13 20:15:29 +00001631
1632 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
Paul Jakma02d942c2010-01-24 23:36:20 +00001633 ospf_lsa_flush (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00001634 }
1635 else
Paul Jakmad71ea652011-03-22 15:23:55 +00001636 new = (* functab->lsa_refresher)(lsa);
paul718e3742002-12-13 20:15:29 +00001637
Paul Jakmad71ea652011-03-22 15:23:55 +00001638 return new;
paul718e3742002-12-13 20:15:29 +00001639}
1640
1641/*------------------------------------------------------------------------*
1642 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1643 * triggered by external interventions (vty session, signaling, etc).
1644 *------------------------------------------------------------------------*/
1645
1646#define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
1647 if (!(T)) \
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001648 (T) = thread_add_timer_msec (master, (F), (L), (V))
paul718e3742002-12-13 20:15:29 +00001649
1650static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type);
1651static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t);
1652static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t);
1653static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t);
1654static int ospf_opaque_lsa_refresh_timer (struct thread *t);
1655
1656void
1657ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
1658 u_char lsa_type, u_char opaque_type)
1659{
1660 struct ospf *top;
1661 struct ospf_area dummy, *area = NULL;
1662 struct ospf_interface *oi = NULL;
1663
1664 struct ospf_lsa *lsa;
1665 struct opaque_info_per_type *oipt;
paul87d6f872004-09-24 08:01:38 +00001666 int (*func) (struct thread * t) = NULL;
paul718e3742002-12-13 20:15:29 +00001667 int delay;
1668
1669 switch (lsa_type)
1670 {
1671 case OSPF_OPAQUE_LINK_LSA:
1672 if ((oi = (struct ospf_interface *) lsa_type_dependent) == NULL)
1673 {
paul87d6f872004-09-24 08:01:38 +00001674 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1675 " Type-9 Opaque-LSA: Invalid parameter?");
1676 goto out;
paul718e3742002-12-13 20:15:29 +00001677 }
1678 if ((top = oi_to_top (oi)) == NULL)
1679 {
paul87d6f872004-09-24 08:01:38 +00001680 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1681 IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001682 goto out;
1683 }
paul87d6f872004-09-24 08:01:38 +00001684 if (!list_isempty (ospf_opaque_type9_funclist)
1685 && list_isempty (oi->opaque_lsa_self)
1686 && oi->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001687 {
paul87d6f872004-09-24 08:01:38 +00001688 zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u):"
1689 " Common origination for OI(%s) has already started",
1690 opaque_type, IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001691 goto out;
1692 }
1693 func = ospf_opaque_type9_lsa_reoriginate_timer;
1694 break;
1695 case OSPF_OPAQUE_AREA_LSA:
1696 if ((area = (struct ospf_area *) lsa_type_dependent) == NULL)
1697 {
paul87d6f872004-09-24 08:01:38 +00001698 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1699 " Type-10 Opaque-LSA: Invalid parameter?");
paul718e3742002-12-13 20:15:29 +00001700 goto out;
1701 }
paul68980082003-03-25 05:07:42 +00001702 if ((top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001703 {
paul87d6f872004-09-24 08:01:38 +00001704 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1705 " AREA(%s) -> TOP?", inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001706 goto out;
1707 }
paul87d6f872004-09-24 08:01:38 +00001708 if (!list_isempty (ospf_opaque_type10_funclist)
1709 && list_isempty (area->opaque_lsa_self)
1710 && area->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001711 {
paul87d6f872004-09-24 08:01:38 +00001712 zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u):"
1713 " Common origination for AREA(%s) has already started",
1714 opaque_type, inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001715 goto out;
1716 }
1717 func = ospf_opaque_type10_lsa_reoriginate_timer;
1718 break;
1719 case OSPF_OPAQUE_AS_LSA:
1720 if ((top = (struct ospf *) lsa_type_dependent) == NULL)
1721 {
paul87d6f872004-09-24 08:01:38 +00001722 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1723 " Type-11 Opaque-LSA: Invalid parameter?");
1724 goto out;
paul718e3742002-12-13 20:15:29 +00001725 }
paul87d6f872004-09-24 08:01:38 +00001726 if (!list_isempty (ospf_opaque_type11_funclist)
1727 && list_isempty (top->opaque_lsa_self)
1728 && top->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001729 {
paul87d6f872004-09-24 08:01:38 +00001730 zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u):"
1731 " Common origination has already started", opaque_type);
paul718e3742002-12-13 20:15:29 +00001732 goto out;
1733 }
1734
1735 /* Fake "area" to pass "ospf" to a lookup function later. */
paul68980082003-03-25 05:07:42 +00001736 dummy.ospf = top;
paul718e3742002-12-13 20:15:29 +00001737 area = &dummy;
1738
1739 func = ospf_opaque_type11_lsa_reoriginate_timer;
1740 break;
1741 default:
paul87d6f872004-09-24 08:01:38 +00001742 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1743 " Unexpected LSA-type(%u)",
1744 lsa_type);
paul718e3742002-12-13 20:15:29 +00001745 goto out;
1746 }
1747
1748 /* It may not a right time to schedule reorigination now. */
paul87d6f872004-09-24 08:01:38 +00001749 if (!CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
paul718e3742002-12-13 20:15:29 +00001750 {
1751 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001752 zlog_debug ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
paul87d6f872004-09-24 08:01:38 +00001753 goto out; /* This is not an error. */
paul718e3742002-12-13 20:15:29 +00001754 }
Paul Jakmae30677a2015-01-20 15:45:36 +00001755
paul718e3742002-12-13 20:15:29 +00001756 /* Generate a dummy lsa to be passed for a lookup function. */
1757 lsa = pseudo_lsa (oi, area, lsa_type, opaque_type);
1758
1759 if ((oipt = lookup_opaque_info_by_type (lsa)) == NULL)
1760 {
1761 struct ospf_opaque_functab *functab;
1762 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL)
1763 {
paul87d6f872004-09-24 08:01:38 +00001764 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1765 " No associated function?: lsa_type(%u),"
1766 " opaque_type(%u)",
1767 lsa_type, opaque_type);
paul718e3742002-12-13 20:15:29 +00001768 goto out;
1769 }
1770 if ((oipt = register_opaque_info_per_type (functab, lsa)) == NULL)
1771 {
paul87d6f872004-09-24 08:01:38 +00001772 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1773 " Cannot get a control info?: lsa_type(%u),"
1774 " opaque_type(%u)",
1775 lsa_type, opaque_type);
paul718e3742002-12-13 20:15:29 +00001776 goto out;
1777 }
1778 }
1779
1780 if (oipt->t_opaque_lsa_self != NULL)
1781 {
1782 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001783 zlog_debug ("Type-%u Opaque-LSA has already scheduled to"
paul87d6f872004-09-24 08:01:38 +00001784 " RE-ORIGINATE: [opaque-type=%u]",
1785 lsa_type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
paul718e3742002-12-13 20:15:29 +00001786 goto out;
1787 }
1788
1789 /*
1790 * Different from initial origination time, in which various conditions
1791 * (opaque capability, neighbor status etc) are assured by caller of
1792 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1793 * it is highly possible that these conditions might not be satisfied
1794 * at the time of re-origination function is to be called.
1795 */
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001796 delay = top->min_ls_interval; /* XXX */
paul718e3742002-12-13 20:15:29 +00001797
1798 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001799 zlog_debug ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001800 " ms later: [opaque-type=%u]",
paul87d6f872004-09-24 08:01:38 +00001801 lsa_type, delay,
1802 GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
paul718e3742002-12-13 20:15:29 +00001803
1804 OSPF_OPAQUE_TIMER_ON (oipt->t_opaque_lsa_self, func, oipt, delay);
1805
1806out:
1807 return;
1808}
1809
1810static struct ospf_lsa *
1811pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area,
1812 u_char lsa_type, u_char opaque_type)
1813{
1814 static struct ospf_lsa lsa = { 0 };
1815 static struct lsa_header lsah = { 0 };
1816 u_int32_t tmp;
1817
1818 lsa.oi = oi;
1819 lsa.area = area;
1820 lsa.data = &lsah;
1821
1822 lsah.type = lsa_type;
1823 tmp = SET_OPAQUE_LSID (opaque_type, 0); /* Opaque-ID is unused here. */
1824 lsah.id.s_addr = htonl (tmp);
1825
1826 return &lsa;
1827}
1828
1829static int
1830ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t)
1831{
1832 struct opaque_info_per_type *oipt;
1833 struct ospf_opaque_functab *functab;
1834 struct ospf *top;
1835 struct ospf_interface *oi;
1836 int rc = -1;
1837
1838 oipt = THREAD_ARG (t);
1839 oipt->t_opaque_lsa_self = NULL;
1840
1841 if ((functab = oipt->functab) == NULL
1842 || functab->lsa_originator == NULL)
1843 {
1844 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1845 goto out;
1846 }
1847
1848 oi = (struct ospf_interface *) oipt->owner;
1849 if ((top = oi_to_top (oi)) == NULL)
1850 {
1851 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1852 goto out;
1853 }
1854
1855 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)
1856 || ! ospf_if_is_enable (oi)
paul68980082003-03-25 05:07:42 +00001857 || ospf_nbr_count_opaque_capable (oi) == 0)
paul718e3742002-12-13 20:15:29 +00001858 {
1859 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001860 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 +00001861
1862 oipt->status = PROC_SUSPEND;
1863 rc = 0;
1864 goto out;
1865 }
1866
1867 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001868 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 +00001869
1870 rc = (* functab->lsa_originator)(oi);
1871out:
1872 return rc;
1873}
1874
1875static int
1876ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t)
1877{
1878 struct opaque_info_per_type *oipt;
1879 struct ospf_opaque_functab *functab;
paul1eb8ef22005-04-07 07:30:20 +00001880 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001881 struct ospf *top;
1882 struct ospf_area *area;
1883 struct ospf_interface *oi;
1884 int n, rc = -1;
1885
1886 oipt = THREAD_ARG (t);
1887 oipt->t_opaque_lsa_self = NULL;
1888
1889 if ((functab = oipt->functab) == NULL
1890 || functab->lsa_originator == NULL)
1891 {
1892 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1893 goto out;
1894 }
1895
1896 area = (struct ospf_area *) oipt->owner;
paul68980082003-03-25 05:07:42 +00001897 if (area == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001898 {
1899 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1900 goto out;
1901 }
1902
1903 /* There must be at least one "opaque-capable, full-state" neighbor. */
1904 n = 0;
paul1eb8ef22005-04-07 07:30:20 +00001905 for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi))
paul718e3742002-12-13 20:15:29 +00001906 {
paul68980082003-03-25 05:07:42 +00001907 if ((n = ospf_nbr_count_opaque_capable (oi)) > 0)
paul718e3742002-12-13 20:15:29 +00001908 break;
1909 }
1910
1911 if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1912 {
1913 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001914 zlog_debug ("Suspend re-origination of Type-10 Opaque-LSAs"
paul87d6f872004-09-24 08:01:38 +00001915 " (opaque-type=%u) for a while...",
1916 oipt->opaque_type);
paul718e3742002-12-13 20:15:29 +00001917
1918 oipt->status = PROC_SUSPEND;
1919 rc = 0;
1920 goto out;
1921 }
1922
1923 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001924 zlog_debug ("Timer[Type10-LSA]: Re-originate Opaque-LSAs"
paul87d6f872004-09-24 08:01:38 +00001925 " (opaque-type=%u) for Area %s",
1926 oipt->opaque_type, inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001927
1928 rc = (* functab->lsa_originator)(area);
1929out:
1930 return rc;
1931}
1932
1933static int
1934ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t)
1935{
1936 struct opaque_info_per_type *oipt;
1937 struct ospf_opaque_functab *functab;
1938 struct ospf *top;
1939 int rc = -1;
1940
1941 oipt = THREAD_ARG (t);
1942 oipt->t_opaque_lsa_self = NULL;
1943
1944 if ((functab = oipt->functab) == NULL
paul87d6f872004-09-24 08:01:38 +00001945 || functab->lsa_originator == NULL)
paul718e3742002-12-13 20:15:29 +00001946 {
paul87d6f872004-09-24 08:01:38 +00001947 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer:"
1948 " No associated function?");
paul718e3742002-12-13 20:15:29 +00001949 goto out;
1950 }
1951
1952 if ((top = (struct ospf *) oipt->owner) == NULL)
1953 {
1954 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1955 goto out;
1956 }
1957
1958 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1959 {
1960 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001961 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 +00001962
1963 oipt->status = PROC_SUSPEND;
1964 rc = 0;
1965 goto out;
1966 }
1967
1968 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001969 zlog_debug ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type);
paul718e3742002-12-13 20:15:29 +00001970
1971 rc = (* functab->lsa_originator)(top);
1972out:
1973 return rc;
1974}
1975
paul718e3742002-12-13 20:15:29 +00001976void
1977ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
1978{
1979 struct opaque_info_per_type *oipt;
1980 struct opaque_info_per_id *oipi;
1981 struct ospf_lsa *lsa;
1982 int delay;
1983
1984 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
1985 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
1986 {
1987 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
1988 goto out;
1989 }
1990
1991 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
1992 if ((lsa = oipi->lsa) == NULL)
1993 {
1994 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
1995 goto out;
1996 }
1997
1998 if (oipi->t_opaque_lsa_self != NULL)
1999 {
2000 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002001 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 +00002002 goto out;
2003 }
2004
2005 /* Delete this lsa from neighbor retransmit-list. */
2006 switch (lsa->data->type)
2007 {
2008 case OSPF_OPAQUE_LINK_LSA:
2009 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002010 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002011 break;
2012 case OSPF_OPAQUE_AS_LSA:
ajse6a0bf92005-09-17 18:53:38 +00002013 ospf_ls_retransmit_delete_nbr_as (lsa0->area->ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002014 break;
2015 default:
2016 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2017 goto out;
2018 }
2019
2020 delay = ospf_lsa_refresh_delay (lsa);
2021
2022 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002023 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 +00002024
2025 OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self,
Michael Rossberg2ef762e2015-07-27 07:56:25 +02002026 ospf_opaque_lsa_refresh_timer, oipi, delay * 1000);
paul718e3742002-12-13 20:15:29 +00002027out:
2028 return;
2029}
2030
2031static int
2032ospf_opaque_lsa_refresh_timer (struct thread *t)
2033{
2034 struct opaque_info_per_id *oipi;
2035 struct ospf_opaque_functab *functab;
2036 struct ospf_lsa *lsa;
2037
2038 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002039 zlog_debug ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
paul718e3742002-12-13 20:15:29 +00002040
2041 oipi = THREAD_ARG (t);
2042 oipi->t_opaque_lsa_self = NULL;
2043
2044 if ((lsa = oipi->lsa) != NULL)
2045 if ((functab = oipi->opqctl_type->functab) != NULL)
2046 if (functab->lsa_refresher != NULL)
2047 (* functab->lsa_refresher)(lsa);
2048
2049 return 0;
2050}
2051
2052void
2053ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
2054{
2055 struct opaque_info_per_type *oipt;
2056 struct opaque_info_per_id *oipi;
2057 struct ospf_lsa *lsa;
2058
2059 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
2060 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
2061 {
2062 zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2063 goto out;
2064 }
2065
2066 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2067 if ((lsa = oipi->lsa) == NULL)
2068 {
2069 zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
2070 goto out;
2071 }
2072
2073 /* Delete this lsa from neighbor retransmit-list. */
2074 switch (lsa->data->type)
2075 {
2076 case OSPF_OPAQUE_LINK_LSA:
2077 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002078 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002079 break;
2080 case OSPF_OPAQUE_AS_LSA:
ajse6a0bf92005-09-17 18:53:38 +00002081 ospf_ls_retransmit_delete_nbr_as (lsa0->area->ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002082 break;
2083 default:
2084 zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2085 goto out;
2086 }
2087
2088 /* Dequeue listnode entry from the list. */
2089 listnode_delete (oipt->id_list, oipi);
2090
2091 /* Avoid misjudgement in the next lookup. */
2092 if (listcount (oipt->id_list) == 0)
2093 oipt->id_list->head = oipt->id_list->tail = NULL;
2094
2095 /* Disassociate internal control information with the given lsa. */
paul718e3742002-12-13 20:15:29 +00002096 free_opaque_info_per_id ((void *) oipi);
2097
2098 /* Force given lsa's age to MaxAge. */
2099 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2100
2101 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002102 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 +00002103
2104 /* This lsa will be flushed and removed eventually. */
Paul Jakma02d942c2010-01-24 23:36:20 +00002105 ospf_lsa_flush (lsa0->area->ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002106
2107out:
2108 return;
2109}
2110
paul718e3742002-12-13 20:15:29 +00002111void
paul87d6f872004-09-24 08:01:38 +00002112ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr,
paul69310a62005-05-11 18:09:59 +00002113 struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002114{
2115 struct ospf *top;
Paul Jakmae30677a2015-01-20 15:45:36 +00002116
paul718e3742002-12-13 20:15:29 +00002117 if ((top = oi_to_top (nbr->oi)) == NULL)
Paul Jakma1fe6ed32006-07-26 09:37:26 +00002118 return;
paul718e3742002-12-13 20:15:29 +00002119
paul69310a62005-05-11 18:09:59 +00002120 /*
2121 * Since these LSA entries are not yet installed into corresponding
2122 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2123 */
2124 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2125 switch (lsa->data->type)
paul718e3742002-12-13 20:15:29 +00002126 {
paul69310a62005-05-11 18:09:59 +00002127 case OSPF_OPAQUE_LINK_LSA:
paul69310a62005-05-11 18:09:59 +00002128 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2129 break;
2130 case OSPF_OPAQUE_AREA_LSA:
paul69310a62005-05-11 18:09:59 +00002131 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2132 break;
2133 case OSPF_OPAQUE_AS_LSA:
paul69310a62005-05-11 18:09:59 +00002134 ospf_flood_through_as (top, NULL/*inbr*/, lsa);
2135 break;
2136 default:
2137 zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
Paul Jakma1fe6ed32006-07-26 09:37:26 +00002138 return;
paul718e3742002-12-13 20:15:29 +00002139 }
Paul Jakmae30677a2015-01-20 15:45:36 +00002140 ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */
paul718e3742002-12-13 20:15:29 +00002141}
2142
paul718e3742002-12-13 20:15:29 +00002143/*------------------------------------------------------------------------*
2144 * Followings are util functions; probably be used by Opaque-LSAs only...
2145 *------------------------------------------------------------------------*/
2146
2147void
2148htonf (float *src, float *dst)
2149{
2150 u_int32_t lu1, lu2;
2151
2152 memcpy (&lu1, src, sizeof (u_int32_t));
2153 lu2 = htonl (lu1);
2154 memcpy (dst, &lu2, sizeof (u_int32_t));
2155 return;
2156}
2157
2158void
2159ntohf (float *src, float *dst)
2160{
2161 u_int32_t lu1, lu2;
2162
2163 memcpy (&lu1, src, sizeof (u_int32_t));
2164 lu2 = ntohl (lu1);
2165 memcpy (dst, &lu2, sizeof (u_int32_t));
2166 return;
2167}
2168
2169struct ospf *
2170oi_to_top (struct ospf_interface *oi)
2171{
2172 struct ospf *top = NULL;
2173 struct ospf_area *area;
2174
paul68980082003-03-25 05:07:42 +00002175 if (oi == NULL || (area = oi->area) == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00002176 zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");
2177
2178 return top;
2179}
2180