blob: 61e98f400964ef99ae6353ceee99ea2f960f0d4a [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
paul718e3742002-12-13 20:15:29 +000064#include "ospfd/ospf_te.h"
paul718e3742002-12-13 20:15:29 +000065
paul283ae332003-03-17 01:16:55 +000066#ifdef SUPPORT_OSPF_API
67int ospf_apiserver_init (void);
68void ospf_apiserver_term (void);
hassof4d58ce2004-10-12 06:13:54 +000069/* Init apiserver? It's disabled by default. */
70int ospf_apiserver_enable;
paul283ae332003-03-17 01:16:55 +000071#endif /* SUPPORT_OSPF_API */
72
paul718e3742002-12-13 20:15:29 +000073static void ospf_opaque_register_vty (void);
74static void ospf_opaque_funclist_init (void);
75static void ospf_opaque_funclist_term (void);
76static void free_opaque_info_per_type (void *val);
77static void free_opaque_info_per_id (void *val);
78static int ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa);
79static int ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa);
80
81void
82ospf_opaque_init (void)
83{
84 ospf_opaque_register_vty ();
85 ospf_opaque_funclist_init ();
86
paul718e3742002-12-13 20:15:29 +000087 if (ospf_mpls_te_init () != 0)
88 exit (1);
paul718e3742002-12-13 20:15:29 +000089
paul283ae332003-03-17 01:16:55 +000090#ifdef SUPPORT_OSPF_API
hassoc3abdb72004-10-11 16:27:03 +000091 if ((ospf_apiserver_enable) && (ospf_apiserver_init () != 0))
paul283ae332003-03-17 01:16:55 +000092 exit (1);
93#endif /* SUPPORT_OSPF_API */
94
paul718e3742002-12-13 20:15:29 +000095 return;
96}
97
98void
99ospf_opaque_term (void)
100{
paul718e3742002-12-13 20:15:29 +0000101 ospf_mpls_te_term ();
paul718e3742002-12-13 20:15:29 +0000102
paul283ae332003-03-17 01:16:55 +0000103#ifdef SUPPORT_OSPF_API
104 ospf_apiserver_term ();
105#endif /* SUPPORT_OSPF_API */
106
paul718e3742002-12-13 20:15:29 +0000107 ospf_opaque_funclist_term ();
108 return;
109}
110
111int
112ospf_opaque_type9_lsa_init (struct ospf_interface *oi)
113{
114 if (oi->opaque_lsa_self != NULL)
115 list_delete (oi->opaque_lsa_self);
116
117 oi->opaque_lsa_self = list_new ();
118 oi->opaque_lsa_self->del = free_opaque_info_per_type;
119 oi->t_opaque_lsa_self = NULL;
120 return 0;
121}
122
123void
124ospf_opaque_type9_lsa_term (struct ospf_interface *oi)
125{
126 OSPF_TIMER_OFF (oi->t_opaque_lsa_self);
127 if (oi->opaque_lsa_self != NULL)
128 list_delete (oi->opaque_lsa_self);
129 oi->opaque_lsa_self = NULL;
130 return;
131}
132
133int
134ospf_opaque_type10_lsa_init (struct ospf_area *area)
135{
136 if (area->opaque_lsa_self != NULL)
137 list_delete (area->opaque_lsa_self);
138
139 area->opaque_lsa_self = list_new ();
140 area->opaque_lsa_self->del = free_opaque_info_per_type;
141 area->t_opaque_lsa_self = NULL;
142
143#ifdef MONITOR_LSDB_CHANGE
144 area->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
145 area->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
146#endif /* MONITOR_LSDB_CHANGE */
147 return 0;
148}
149
150void
151ospf_opaque_type10_lsa_term (struct ospf_area *area)
152{
153#ifdef MONITOR_LSDB_CHANGE
154 area->lsdb->new_lsa_hook =
155 area->lsdb->del_lsa_hook = NULL;
156#endif /* MONITOR_LSDB_CHANGE */
157
158 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
159 if (area->opaque_lsa_self != NULL)
160 list_delete (area->opaque_lsa_self);
161 area->opaque_lsa_self = NULL;
162 return;
163}
164
165int
166ospf_opaque_type11_lsa_init (struct ospf *top)
167{
168 if (top->opaque_lsa_self != NULL)
169 list_delete (top->opaque_lsa_self);
170
171 top->opaque_lsa_self = list_new ();
172 top->opaque_lsa_self->del = free_opaque_info_per_type;
173 top->t_opaque_lsa_self = NULL;
174
175#ifdef MONITOR_LSDB_CHANGE
176 top->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
177 top->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
178#endif /* MONITOR_LSDB_CHANGE */
179 return 0;
180}
181
182void
183ospf_opaque_type11_lsa_term (struct ospf *top)
184{
185#ifdef MONITOR_LSDB_CHANGE
186 top->lsdb->new_lsa_hook =
187 top->lsdb->del_lsa_hook = NULL;
188#endif /* MONITOR_LSDB_CHANGE */
189
190 OSPF_TIMER_OFF (top->t_opaque_lsa_self);
191 if (top->opaque_lsa_self != NULL)
192 list_delete (top->opaque_lsa_self);
193 top->opaque_lsa_self = NULL;
194 return;
195}
196
197static const char *
198ospf_opaque_type_name (u_char opaque_type)
199{
200 const char *name = "Unknown";
201
202 switch (opaque_type)
203 {
204 case OPAQUE_TYPE_WILDCARD: /* This is a special assignment! */
205 name = "Wildcard";
206 break;
207 case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA:
208 name = "Traffic Engineering LSA";
209 break;
210 case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC:
211 name = "Sycamore optical topology description";
212 break;
213 case OPAQUE_TYPE_GRACE_LSA:
214 name = "Grace-LSA";
215 break;
216 default:
217 if (OPAQUE_TYPE_RANGE_UNASSIGNED (opaque_type))
218 name = "Unassigned";
Andrew Certain0798cee2012-12-04 13:43:42 -0800219 else
220 {
221 u_int32_t bigger_range = opaque_type;
222 /*
223 * Get around type-limits warning: comparison is always true due to limited range of data type
224 */
225 if (OPAQUE_TYPE_RANGE_RESERVED (bigger_range))
226 name = "Private/Experimental";
227 }
paul718e3742002-12-13 20:15:29 +0000228 break;
229 }
230 return name;
231}
232
233/*------------------------------------------------------------------------*
234 * Followings are management functions to store user specified callbacks.
235 *------------------------------------------------------------------------*/
236
237struct opaque_info_per_type; /* Forward declaration. */
238
239struct ospf_opaque_functab
240{
241 u_char opaque_type;
242 struct opaque_info_per_type *oipt;
243
244 int (* new_if_hook)(struct interface *ifp);
245 int (* del_if_hook)(struct interface *ifp);
246 void (* ism_change_hook)(struct ospf_interface *oi, int old_status);
247 void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status);
248 void (* config_write_router)(struct vty *vty);
249 void (* config_write_if )(struct vty *vty, struct interface *ifp);
250 void (* config_write_debug )(struct vty *vty);
251 void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa);
252 int (* lsa_originator)(void *arg);
Paul Jakmad71ea652011-03-22 15:23:55 +0000253 struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa);
paul718e3742002-12-13 20:15:29 +0000254 int (* new_lsa_hook)(struct ospf_lsa *lsa);
255 int (* del_lsa_hook)(struct ospf_lsa *lsa);
256};
257
paul87d6f872004-09-24 08:01:38 +0000258/* Handle LSA-9/10/11 altogether. */
259static struct list *ospf_opaque_wildcard_funclist;
260static struct list *ospf_opaque_type9_funclist;
261static struct list *ospf_opaque_type10_funclist;
262static struct list *ospf_opaque_type11_funclist;
paul718e3742002-12-13 20:15:29 +0000263
264static void
265ospf_opaque_del_functab (void *val)
266{
267 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, val);
268 return;
269}
270
271static void
272ospf_opaque_funclist_init (void)
273{
paul87d6f872004-09-24 08:01:38 +0000274 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000275
paul09e4efd2003-01-18 00:12:02 +0000276 funclist = ospf_opaque_wildcard_funclist = list_new ();
277 funclist->del = ospf_opaque_del_functab;
278
paul718e3742002-12-13 20:15:29 +0000279 funclist = ospf_opaque_type9_funclist = list_new ();
280 funclist->del = ospf_opaque_del_functab;
281
282 funclist = ospf_opaque_type10_funclist = list_new ();
283 funclist->del = ospf_opaque_del_functab;
284
285 funclist = ospf_opaque_type11_funclist = list_new ();
286 funclist->del = ospf_opaque_del_functab;
287 return;
288}
289
290static void
291ospf_opaque_funclist_term (void)
292{
paul87d6f872004-09-24 08:01:38 +0000293 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000294
paul09e4efd2003-01-18 00:12:02 +0000295 funclist = ospf_opaque_wildcard_funclist;
296 list_delete (funclist);
297
paul718e3742002-12-13 20:15:29 +0000298 funclist = ospf_opaque_type9_funclist;
299 list_delete (funclist);
300
301 funclist = ospf_opaque_type10_funclist;
302 list_delete (funclist);
303
304 funclist = ospf_opaque_type11_funclist;
305 list_delete (funclist);
306 return;
307}
308
paul87d6f872004-09-24 08:01:38 +0000309static struct list *
paul718e3742002-12-13 20:15:29 +0000310ospf_get_opaque_funclist (u_char lsa_type)
311{
paul87d6f872004-09-24 08:01:38 +0000312 struct list *funclist = NULL;
paul718e3742002-12-13 20:15:29 +0000313
314 switch (lsa_type)
315 {
paul09e4efd2003-01-18 00:12:02 +0000316 case OPAQUE_TYPE_WILDCARD:
317 /* XXX
318 * This is an ugly trick to handle type-9/10/11 LSA altogether.
319 * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor
320 * an officially assigned opaque-type.
321 * Though it is possible that the value might be officially used
322 * in the future, we use it internally as a special label, for now.
323 */
324 funclist = ospf_opaque_wildcard_funclist;
325 break;
paul718e3742002-12-13 20:15:29 +0000326 case OSPF_OPAQUE_LINK_LSA:
327 funclist = ospf_opaque_type9_funclist;
328 break;
329 case OSPF_OPAQUE_AREA_LSA:
330 funclist = ospf_opaque_type10_funclist;
331 break;
332 case OSPF_OPAQUE_AS_LSA:
333 funclist = ospf_opaque_type11_funclist;
334 break;
335 default:
336 zlog_warn ("ospf_get_opaque_funclist: Unexpected LSA-type(%u)", lsa_type);
337 break;
338 }
339 return funclist;
340}
341
paul87d6f872004-09-24 08:01:38 +0000342/* XXX: such a huge argument list can /not/ be healthy... */
paul718e3742002-12-13 20:15:29 +0000343int
344ospf_register_opaque_functab (
345 u_char lsa_type,
346 u_char opaque_type,
347 int (* new_if_hook)(struct interface *ifp),
348 int (* del_if_hook)(struct interface *ifp),
349 void (* ism_change_hook)(struct ospf_interface *oi, int old_status),
350 void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status),
351 void (* config_write_router)(struct vty *vty),
352 void (* config_write_if )(struct vty *vty, struct interface *ifp),
353 void (* config_write_debug )(struct vty *vty),
354 void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa),
355 int (* lsa_originator)(void *arg),
Paul Jakmad71ea652011-03-22 15:23:55 +0000356 struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa),
paul718e3742002-12-13 20:15:29 +0000357 int (* new_lsa_hook)(struct ospf_lsa *lsa),
358 int (* del_lsa_hook)(struct ospf_lsa *lsa))
359{
paul87d6f872004-09-24 08:01:38 +0000360 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000361 struct ospf_opaque_functab *new;
362 int rc = -1;
363
364 if ((funclist = ospf_get_opaque_funclist (lsa_type)) == NULL)
365 {
paul87d6f872004-09-24 08:01:38 +0000366 zlog_warn ("ospf_register_opaque_functab: Cannot get funclist"
367 " for Type-%u LSAs?",
368 lsa_type);
paul718e3742002-12-13 20:15:29 +0000369 goto out;
370 }
371 else
372 {
paul1eb8ef22005-04-07 07:30:20 +0000373 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000374 struct ospf_opaque_functab *functab;
paul87d6f872004-09-24 08:01:38 +0000375
paul1eb8ef22005-04-07 07:30:20 +0000376 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000377 if (functab->opaque_type == opaque_type)
378 {
379 zlog_warn ("ospf_register_opaque_functab: Duplicated entry?:"
380 " lsa_type(%u), opaque_type(%u)",
381 lsa_type, opaque_type);
382 goto out;
383 }
paul718e3742002-12-13 20:15:29 +0000384 }
385
386 if ((new = XCALLOC (MTYPE_OSPF_OPAQUE_FUNCTAB,
387 sizeof (struct ospf_opaque_functab))) == NULL)
388 {
paul87d6f872004-09-24 08:01:38 +0000389 zlog_warn ("ospf_register_opaque_functab: XMALLOC: %s",
ajs6099b3b2004-11-20 02:06:59 +0000390 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000391 goto out;
392 }
393
394 new->opaque_type = opaque_type;
395 new->oipt = NULL;
396 new->new_if_hook = new_if_hook;
397 new->del_if_hook = del_if_hook;
398 new->ism_change_hook = ism_change_hook;
399 new->nsm_change_hook = nsm_change_hook;
400 new->config_write_router = config_write_router;
401 new->config_write_if = config_write_if;
402 new->config_write_debug = config_write_debug;
403 new->show_opaque_info = show_opaque_info;
404 new->lsa_originator = lsa_originator;
405 new->lsa_refresher = lsa_refresher;
406 new->new_lsa_hook = new_lsa_hook;
407 new->del_lsa_hook = del_lsa_hook;
408
409 listnode_add (funclist, new);
410 rc = 0;
411
412out:
413 return rc;
414}
415
416void
417ospf_delete_opaque_functab (u_char lsa_type, u_char opaque_type)
418{
paul87d6f872004-09-24 08:01:38 +0000419 struct list *funclist;
paul1eb8ef22005-04-07 07:30:20 +0000420 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000421 struct ospf_opaque_functab *functab;
422
423 if ((funclist = ospf_get_opaque_funclist (lsa_type)) != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000424 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul718e3742002-12-13 20:15:29 +0000425 {
paul1eb8ef22005-04-07 07:30:20 +0000426 if (functab->opaque_type == opaque_type)
paul718e3742002-12-13 20:15:29 +0000427 {
428 /* Cleanup internal control information, if it still remains. */
429 if (functab->oipt != NULL)
430 free_opaque_info_per_type (functab->oipt);
431
432 /* Dequeue listnode entry from the list. */
433 listnode_delete (funclist, functab);
434
435 /* Avoid misjudgement in the next lookup. */
436 if (listcount (funclist) == 0)
437 funclist->head = funclist->tail = NULL;
438
439 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, functab);
paul87d6f872004-09-24 08:01:38 +0000440 break;
paul718e3742002-12-13 20:15:29 +0000441 }
442 }
paul87d6f872004-09-24 08:01:38 +0000443
paul718e3742002-12-13 20:15:29 +0000444 return;
445}
446
447static struct ospf_opaque_functab *
448ospf_opaque_functab_lookup (struct ospf_lsa *lsa)
449{
paul87d6f872004-09-24 08:01:38 +0000450 struct list *funclist;
451 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000452 struct ospf_opaque_functab *functab;
453 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
454
455 if ((funclist = ospf_get_opaque_funclist (lsa->data->type)) != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000456 for (ALL_LIST_ELEMENTS_RO (funclist, node, functab))
paul87d6f872004-09-24 08:01:38 +0000457 if (functab->opaque_type == key)
458 return functab;
paul718e3742002-12-13 20:15:29 +0000459
460 return NULL;
461}
462
463/*------------------------------------------------------------------------*
464 * Followings are management functions for self-originated LSA entries.
465 *------------------------------------------------------------------------*/
466
467/*
468 * Opaque-LSA control information per opaque-type.
469 * Single Opaque-Type may have multiple instances; each of them will be
470 * identified by their opaque-id.
471 */
472struct opaque_info_per_type
473{
paul09e4efd2003-01-18 00:12:02 +0000474 u_char lsa_type;
paul718e3742002-12-13 20:15:29 +0000475 u_char opaque_type;
476
477 enum { PROC_NORMAL, PROC_SUSPEND } status;
478
479 /*
480 * Thread for (re-)origination scheduling for this opaque-type.
481 *
482 * Initial origination of Opaque-LSAs is controlled by generic
483 * Opaque-LSA handling module so that same opaque-type entries are
484 * called all at once when certain conditions are met.
485 * However, there might be cases that some Opaque-LSA clients need
486 * to (re-)originate their own Opaque-LSAs out-of-sync with others.
487 * This thread is prepared for that specific purpose.
488 */
489 struct thread *t_opaque_lsa_self;
490
491 /*
paul09e4efd2003-01-18 00:12:02 +0000492 * Backpointer to an "owner" which is LSA-type dependent.
paul718e3742002-12-13 20:15:29 +0000493 * type-9: struct ospf_interface
494 * type-10: struct ospf_area
495 * type-11: struct ospf
496 */
497 void *owner;
498
499 /* Collection of callback functions for this opaque-type. */
500 struct ospf_opaque_functab *functab;
501
502 /* List of Opaque-LSA control informations per opaque-id. */
paul87d6f872004-09-24 08:01:38 +0000503 struct list *id_list;
paul718e3742002-12-13 20:15:29 +0000504};
505
506/* Opaque-LSA control information per opaque-id. */
507struct opaque_info_per_id
508{
509 u_int32_t opaque_id;
510
511 /* Thread for refresh/flush scheduling for this opaque-type/id. */
512 struct thread *t_opaque_lsa_self;
513
514 /* Backpointer to Opaque-LSA control information per opaque-type. */
515 struct opaque_info_per_type *opqctl_type;
516
517 /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
518 struct ospf_lsa *lsa;
519};
520
521static struct opaque_info_per_type *register_opaque_info_per_type (struct ospf_opaque_functab *functab, struct ospf_lsa *new);
522static struct opaque_info_per_type *lookup_opaque_info_by_type (struct ospf_lsa *lsa);
523static struct opaque_info_per_id *register_opaque_info_per_id (struct opaque_info_per_type *oipt, struct ospf_lsa *new);
524static struct opaque_info_per_id *lookup_opaque_info_by_id (struct opaque_info_per_type *oipt, struct ospf_lsa *lsa);
525static struct opaque_info_per_id *register_opaque_lsa (struct ospf_lsa *new);
526
527
528static struct opaque_info_per_type *
529register_opaque_info_per_type (struct ospf_opaque_functab *functab,
530 struct ospf_lsa *new)
531{
532 struct ospf *top;
533 struct opaque_info_per_type *oipt;
534
535 if ((oipt = XCALLOC (MTYPE_OPAQUE_INFO_PER_TYPE,
536 sizeof (struct opaque_info_per_type))) == NULL)
537 {
ajs6099b3b2004-11-20 02:06:59 +0000538 zlog_warn ("register_opaque_info_per_type: XMALLOC: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000539 goto out;
540 }
541
542 switch (new->data->type)
543 {
544 case OSPF_OPAQUE_LINK_LSA:
545 oipt->owner = new->oi;
546 listnode_add (new->oi->opaque_lsa_self, oipt);
547 break;
548 case OSPF_OPAQUE_AREA_LSA:
549 oipt->owner = new->area;
550 listnode_add (new->area->opaque_lsa_self, oipt);
551 break;
552 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +0000553 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000554 if (new->area != NULL && (top = new->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +0000555 {
556 free_opaque_info_per_type ((void *) oipt);
557 oipt = NULL;
558 goto out; /* This case may not exist. */
559 }
560 oipt->owner = top;
561 listnode_add (top->opaque_lsa_self, oipt);
562 break;
563 default:
paul09e4efd2003-01-18 00:12:02 +0000564 zlog_warn ("register_opaque_info_per_type: Unexpected LSA-type(%u)", new->data->type);
paul718e3742002-12-13 20:15:29 +0000565 free_opaque_info_per_type ((void *) oipt);
566 oipt = NULL;
567 goto out; /* This case may not exist. */
568 }
569
paul09e4efd2003-01-18 00:12:02 +0000570 oipt->lsa_type = new->data->type;
paul718e3742002-12-13 20:15:29 +0000571 oipt->opaque_type = GET_OPAQUE_TYPE (ntohl (new->data->id.s_addr));
572 oipt->status = PROC_NORMAL;
573 oipt->t_opaque_lsa_self = NULL;
574 oipt->functab = functab;
575 functab->oipt = oipt;
576 oipt->id_list = list_new ();
577 oipt->id_list->del = free_opaque_info_per_id;
578
579out:
580 return oipt;
581}
582
583static void
584free_opaque_info_per_type (void *val)
585{
586 struct opaque_info_per_type *oipt = (struct opaque_info_per_type *) val;
587 struct opaque_info_per_id *oipi;
588 struct ospf_lsa *lsa;
paul1eb8ef22005-04-07 07:30:20 +0000589 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000590
591 /* Control information per opaque-id may still exist. */
paul1eb8ef22005-04-07 07:30:20 +0000592 for (ALL_LIST_ELEMENTS (oipt->id_list, node, nnode, oipi))
paul718e3742002-12-13 20:15:29 +0000593 {
paul718e3742002-12-13 20:15:29 +0000594 if ((lsa = oipi->lsa) == NULL)
595 continue;
596 if (IS_LSA_MAXAGE (lsa))
597 continue;
598 ospf_opaque_lsa_flush_schedule (lsa);
599 }
600
paul09e4efd2003-01-18 00:12:02 +0000601 /* Remove "oipt" from its owner's self-originated LSA list. */
602 switch (oipt->lsa_type)
603 {
604 case OSPF_OPAQUE_LINK_LSA:
605 {
606 struct ospf_interface *oi = (struct ospf_interface *)(oipt->owner);
607 listnode_delete (oi->opaque_lsa_self, oipt);
608 break;
609 }
610 case OSPF_OPAQUE_AREA_LSA:
611 {
612 struct ospf_area *area = (struct ospf_area *)(oipt->owner);
613 listnode_delete (area->opaque_lsa_self, oipt);
614 break;
615 }
616 case OSPF_OPAQUE_AS_LSA:
617 {
618 struct ospf *top = (struct ospf *)(oipt->owner);
619 listnode_delete (top->opaque_lsa_self, oipt);
620 break;
621 }
622 default:
623 zlog_warn ("free_opaque_info_per_type: Unexpected LSA-type(%u)", oipt->lsa_type);
624 break; /* This case may not exist. */
625 }
626
paul718e3742002-12-13 20:15:29 +0000627 OSPF_TIMER_OFF (oipt->t_opaque_lsa_self);
628 list_delete (oipt->id_list);
629 XFREE (MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
630 return;
631}
632
633static struct opaque_info_per_type *
634lookup_opaque_info_by_type (struct ospf_lsa *lsa)
635{
636 struct ospf *top;
637 struct ospf_area *area;
638 struct ospf_interface *oi;
paul87d6f872004-09-24 08:01:38 +0000639 struct list *listtop = NULL;
paul1eb8ef22005-04-07 07:30:20 +0000640 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000641 struct opaque_info_per_type *oipt = NULL;
642 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
643
644 switch (lsa->data->type)
645 {
646 case OSPF_OPAQUE_LINK_LSA:
647 if ((oi = lsa->oi) != NULL)
648 listtop = oi->opaque_lsa_self;
649 else
650 zlog_warn ("Type-9 Opaque-LSA: Reference to OI is missing?");
651 break;
652 case OSPF_OPAQUE_AREA_LSA:
653 if ((area = lsa->area) != NULL)
654 listtop = area->opaque_lsa_self;
655 else
656 zlog_warn ("Type-10 Opaque-LSA: Reference to AREA is missing?");
657 break;
658 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +0000659 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000660 if ((area = lsa->area) != NULL && (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +0000661 {
662 zlog_warn ("Type-11 Opaque-LSA: Reference to OSPF is missing?");
663 break; /* Unlikely to happen. */
664 }
665 listtop = top->opaque_lsa_self;
666 break;
667 default:
668 zlog_warn ("lookup_opaque_info_by_type: Unexpected LSA-type(%u)", lsa->data->type);
669 break;
670 }
671
672 if (listtop != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000673 for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt))
paul87d6f872004-09-24 08:01:38 +0000674 if (oipt->opaque_type == key)
675 return oipt;
paul718e3742002-12-13 20:15:29 +0000676
677 return NULL;
678}
679
680static struct opaque_info_per_id *
681register_opaque_info_per_id (struct opaque_info_per_type *oipt,
682 struct ospf_lsa *new)
683{
684 struct opaque_info_per_id *oipi;
685
686 if ((oipi = XCALLOC (MTYPE_OPAQUE_INFO_PER_ID,
687 sizeof (struct opaque_info_per_id))) == NULL)
688 {
ajs6099b3b2004-11-20 02:06:59 +0000689 zlog_warn ("register_opaque_info_per_id: XMALLOC: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000690 goto out;
691 }
692 oipi->opaque_id = GET_OPAQUE_ID (ntohl (new->data->id.s_addr));
693 oipi->t_opaque_lsa_self = NULL;
694 oipi->opqctl_type = oipt;
695 oipi->lsa = ospf_lsa_lock (new);
696
697 listnode_add (oipt->id_list, oipi);
698
699out:
700 return oipi;
701}
702
703static void
704free_opaque_info_per_id (void *val)
705{
706 struct opaque_info_per_id *oipi = (struct opaque_info_per_id *) val;
707
708 OSPF_TIMER_OFF (oipi->t_opaque_lsa_self);
709 if (oipi->lsa != NULL)
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000710 ospf_lsa_unlock (&oipi->lsa);
paul718e3742002-12-13 20:15:29 +0000711 XFREE (MTYPE_OPAQUE_INFO_PER_ID, oipi);
712 return;
713}
714
715static struct opaque_info_per_id *
716lookup_opaque_info_by_id (struct opaque_info_per_type *oipt,
717 struct ospf_lsa *lsa)
718{
paul1eb8ef22005-04-07 07:30:20 +0000719 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000720 struct opaque_info_per_id *oipi;
721 u_int32_t key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
722
paul1eb8ef22005-04-07 07:30:20 +0000723 for (ALL_LIST_ELEMENTS (oipt->id_list, node, nnode, oipi))
paul87d6f872004-09-24 08:01:38 +0000724 if (oipi->opaque_id == key)
725 return oipi;
paul718e3742002-12-13 20:15:29 +0000726
727 return NULL;
728}
729
730static struct opaque_info_per_id *
731register_opaque_lsa (struct ospf_lsa *new)
732{
733 struct ospf_opaque_functab *functab;
734 struct opaque_info_per_type *oipt;
735 struct opaque_info_per_id *oipi = NULL;
736
737 if ((functab = ospf_opaque_functab_lookup (new)) == NULL)
738 goto out;
739
740 if ((oipt = lookup_opaque_info_by_type (new)) == NULL
741 && (oipt = register_opaque_info_per_type (functab, new)) == NULL)
742 goto out;
743
744 if ((oipi = register_opaque_info_per_id (oipt, new)) == NULL)
745 goto out;
746
747out:
748 return oipi;
749}
750
751/*------------------------------------------------------------------------*
752 * Followings are (vty) configuration functions for Opaque-LSAs handling.
753 *------------------------------------------------------------------------*/
754
755DEFUN (capability_opaque,
756 capability_opaque_cmd,
757 "capability opaque",
758 "Enable specific OSPF feature\n"
759 "Opaque LSA\n")
760{
761 struct ospf *ospf = (struct ospf *) vty->index;
762
763 /* Turn on the "master switch" of opaque-lsa capability. */
764 if (!CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
765 {
766 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000767 zlog_debug ("Opaque capability: OFF -> ON");
paul718e3742002-12-13 20:15:29 +0000768
769 SET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
770 ospf_renegotiate_optional_capabilities (ospf);
771 }
772 return CMD_SUCCESS;
773}
774
775ALIAS (capability_opaque,
776 ospf_opaque_capable_cmd,
777 "ospf opaque-lsa",
778 "OSPF specific commands\n"
779 "Enable the Opaque-LSA capability (rfc2370)\n")
780
781DEFUN (no_capability_opaque,
782 no_capability_opaque_cmd,
783 "no capability opaque",
784 NO_STR
785 "Enable specific OSPF feature\n"
786 "Opaque LSA\n")
787{
788 struct ospf *ospf = (struct ospf *) vty->index;
789
790 /* Turn off the "master switch" of opaque-lsa capability. */
791 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
792 {
793 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000794 zlog_debug ("Opaque capability: ON -> OFF");
paul718e3742002-12-13 20:15:29 +0000795
796 UNSET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
797 ospf_renegotiate_optional_capabilities (ospf);
798 }
799 return CMD_SUCCESS;
800}
801
802ALIAS (no_capability_opaque,
803 no_ospf_opaque_capable_cmd,
804 "no ospf opaque-lsa",
805 NO_STR
806 "OSPF specific commands\n"
807 "Disable the Opaque-LSA capability (rfc2370)\n")
808
809static void
810ospf_opaque_register_vty (void)
811{
812 install_element (OSPF_NODE, &capability_opaque_cmd);
813 install_element (OSPF_NODE, &no_capability_opaque_cmd);
814 install_element (OSPF_NODE, &ospf_opaque_capable_cmd);
815 install_element (OSPF_NODE, &no_ospf_opaque_capable_cmd);
816 return;
817}
818
819/*------------------------------------------------------------------------*
820 * Followings are collection of user-registered function callers.
821 *------------------------------------------------------------------------*/
822
823static int
paul87d6f872004-09-24 08:01:38 +0000824opaque_lsa_new_if_callback (struct list *funclist, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000825{
paul1eb8ef22005-04-07 07:30:20 +0000826 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000827 struct ospf_opaque_functab *functab;
828 int rc = -1;
829
paul1eb8ef22005-04-07 07:30:20 +0000830 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000831 if (functab->new_if_hook != NULL)
832 if ((* functab->new_if_hook)(ifp) != 0)
833 goto out;
paul718e3742002-12-13 20:15:29 +0000834 rc = 0;
835out:
836 return rc;
837}
838
839static int
paul87d6f872004-09-24 08:01:38 +0000840opaque_lsa_del_if_callback (struct list *funclist, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000841{
paul1eb8ef22005-04-07 07:30:20 +0000842 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000843 struct ospf_opaque_functab *functab;
844 int rc = -1;
845
paul1eb8ef22005-04-07 07:30:20 +0000846 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000847 if (functab->del_if_hook != NULL)
848 if ((* functab->del_if_hook)(ifp) != 0)
849 goto out;
paul718e3742002-12-13 20:15:29 +0000850 rc = 0;
851out:
852 return rc;
853}
854
855static void
paul87d6f872004-09-24 08:01:38 +0000856opaque_lsa_ism_change_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000857 struct ospf_interface *oi, int old_status)
858{
paul1eb8ef22005-04-07 07:30:20 +0000859 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000860 struct ospf_opaque_functab *functab;
861
paul1eb8ef22005-04-07 07:30:20 +0000862 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000863 if (functab->ism_change_hook != NULL)
864 (* functab->ism_change_hook)(oi, old_status);
865
paul718e3742002-12-13 20:15:29 +0000866 return;
867}
868
869static void
paul87d6f872004-09-24 08:01:38 +0000870opaque_lsa_nsm_change_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000871 struct ospf_neighbor *nbr, int old_status)
872{
paul1eb8ef22005-04-07 07:30:20 +0000873 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000874 struct ospf_opaque_functab *functab;
875
paul1eb8ef22005-04-07 07:30:20 +0000876 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000877 if (functab->nsm_change_hook != NULL)
878 (* functab->nsm_change_hook)(nbr, old_status);
paul718e3742002-12-13 20:15:29 +0000879 return;
880}
881
882static void
paul87d6f872004-09-24 08:01:38 +0000883opaque_lsa_config_write_router_callback (struct list *funclist,
884 struct vty *vty)
paul718e3742002-12-13 20:15:29 +0000885{
paul1eb8ef22005-04-07 07:30:20 +0000886 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000887 struct ospf_opaque_functab *functab;
888
paul1eb8ef22005-04-07 07:30:20 +0000889 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000890 if (functab->config_write_router != NULL)
891 (* functab->config_write_router)(vty);
paul718e3742002-12-13 20:15:29 +0000892 return;
893}
894
895static void
paul87d6f872004-09-24 08:01:38 +0000896opaque_lsa_config_write_if_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000897 struct vty *vty, struct interface *ifp)
898{
paul1eb8ef22005-04-07 07:30:20 +0000899 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000900 struct ospf_opaque_functab *functab;
901
paul1eb8ef22005-04-07 07:30:20 +0000902 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000903 if (functab->config_write_if != NULL)
904 (* functab->config_write_if)(vty, ifp);
paul718e3742002-12-13 20:15:29 +0000905 return;
906}
907
908static void
paul87d6f872004-09-24 08:01:38 +0000909opaque_lsa_config_write_debug_callback (struct list *funclist, struct vty *vty)
paul718e3742002-12-13 20:15:29 +0000910{
paul1eb8ef22005-04-07 07:30:20 +0000911 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000912 struct ospf_opaque_functab *functab;
913
paul1eb8ef22005-04-07 07:30:20 +0000914 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000915 if (functab->config_write_debug != NULL)
916 (* functab->config_write_debug)(vty);
paul718e3742002-12-13 20:15:29 +0000917 return;
918}
919
920static int
paul87d6f872004-09-24 08:01:38 +0000921opaque_lsa_originate_callback (struct list *funclist, void *lsa_type_dependent)
paul718e3742002-12-13 20:15:29 +0000922{
paul1eb8ef22005-04-07 07:30:20 +0000923 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000924 struct ospf_opaque_functab *functab;
925 int rc = -1;
926
paul1eb8ef22005-04-07 07:30:20 +0000927 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000928 if (functab->lsa_originator != NULL)
929 if ((* functab->lsa_originator)(lsa_type_dependent) != 0)
930 goto out;
paul718e3742002-12-13 20:15:29 +0000931 rc = 0;
932out:
933 return rc;
934}
935
936static int
paul87d6f872004-09-24 08:01:38 +0000937new_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000938{
paul1eb8ef22005-04-07 07:30:20 +0000939 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000940 struct ospf_opaque_functab *functab;
941 int rc = -1;
942
943 /* This function handles ALL types of LSAs, not only opaque ones. */
paul1eb8ef22005-04-07 07:30:20 +0000944 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000945 if (functab->new_lsa_hook != NULL)
946 if ((* functab->new_lsa_hook)(lsa) != 0)
947 goto out;
paul718e3742002-12-13 20:15:29 +0000948 rc = 0;
949out:
950 return rc;
951}
952
953static int
paul87d6f872004-09-24 08:01:38 +0000954del_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000955{
paul1eb8ef22005-04-07 07:30:20 +0000956 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000957 struct ospf_opaque_functab *functab;
958 int rc = -1;
959
960 /* This function handles ALL types of LSAs, not only opaque ones. */
paul1eb8ef22005-04-07 07:30:20 +0000961 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000962 if (functab->del_lsa_hook != NULL)
963 if ((* functab->del_lsa_hook)(lsa) != 0)
964 goto out;
paul718e3742002-12-13 20:15:29 +0000965 rc = 0;
966out:
967 return rc;
968}
969
970/*------------------------------------------------------------------------*
971 * Followings are glue functions to call Opaque-LSA specific processing.
972 *------------------------------------------------------------------------*/
973
974int
975ospf_opaque_new_if (struct interface *ifp)
976{
paul87d6f872004-09-24 08:01:38 +0000977 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000978 int rc = -1;
979
paul09e4efd2003-01-18 00:12:02 +0000980 funclist = ospf_opaque_wildcard_funclist;
981 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
982 goto out;
983
paul718e3742002-12-13 20:15:29 +0000984 funclist = ospf_opaque_type9_funclist;
985 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
986 goto out;
987
988 funclist = ospf_opaque_type10_funclist;
989 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
990 goto out;
991
992 funclist = ospf_opaque_type11_funclist;
993 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
994 goto out;
995
996 rc = 0;
997out:
998 return rc;
999}
1000
1001int
1002ospf_opaque_del_if (struct interface *ifp)
1003{
paul87d6f872004-09-24 08:01:38 +00001004 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001005 int rc = -1;
1006
paul09e4efd2003-01-18 00:12:02 +00001007 funclist = ospf_opaque_wildcard_funclist;
1008 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1009 goto out;
1010
paul718e3742002-12-13 20:15:29 +00001011 funclist = ospf_opaque_type9_funclist;
1012 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1013 goto out;
1014
1015 funclist = ospf_opaque_type10_funclist;
1016 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1017 goto out;
1018
1019 funclist = ospf_opaque_type11_funclist;
1020 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1021 goto out;
1022
1023 rc = 0;
1024out:
1025 return rc;
1026}
1027
1028void
1029ospf_opaque_ism_change (struct ospf_interface *oi, int old_status)
1030{
paul87d6f872004-09-24 08:01:38 +00001031 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001032
paul09e4efd2003-01-18 00:12:02 +00001033 funclist = ospf_opaque_wildcard_funclist;
1034 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1035
paul718e3742002-12-13 20:15:29 +00001036 funclist = ospf_opaque_type9_funclist;
1037 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1038
1039 funclist = ospf_opaque_type10_funclist;
1040 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1041
1042 funclist = ospf_opaque_type11_funclist;
1043 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1044
1045 return;
1046}
1047
1048void
1049ospf_opaque_nsm_change (struct ospf_neighbor *nbr, int old_state)
1050{
1051 struct ospf *top;
paul87d6f872004-09-24 08:01:38 +00001052 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001053
1054 if ((top = oi_to_top (nbr->oi)) == NULL)
1055 goto out;
1056
1057 if (old_state != NSM_Full && nbr->state == NSM_Full)
1058 {
1059 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
1060 {
1061 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1062 {
1063 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001064 zlog_debug ("Opaque-LSA: Now get operational!");
paul718e3742002-12-13 20:15:29 +00001065
1066 SET_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT);
1067 }
1068
1069 ospf_opaque_lsa_originate_schedule (nbr->oi, NULL);
1070 }
1071 }
1072 else
1073 if (old_state == NSM_Full && nbr->state != NSM_Full)
1074 {
1075#ifdef NOTYET
1076 /*
1077 * If no more opaque-capable full-state neighbor remains in the
1078 * flooding scope which corresponds to Opaque-LSA type, periodic
1079 * LS flooding should be stopped.
1080 */
1081#endif /* NOTYET */
1082 ;
1083 }
1084
paul09e4efd2003-01-18 00:12:02 +00001085 funclist = ospf_opaque_wildcard_funclist;
1086 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1087
paul718e3742002-12-13 20:15:29 +00001088 funclist = ospf_opaque_type9_funclist;
1089 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1090
1091 funclist = ospf_opaque_type10_funclist;
1092 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1093
1094 funclist = ospf_opaque_type11_funclist;
1095 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1096
1097out:
1098 return;
1099}
1100
1101void
1102ospf_opaque_config_write_router (struct vty *vty, struct ospf *ospf)
1103{
paul87d6f872004-09-24 08:01:38 +00001104 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001105
1106 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
1107 vty_out (vty, " capability opaque%s", VTY_NEWLINE);
1108
paul09e4efd2003-01-18 00:12:02 +00001109 funclist = ospf_opaque_wildcard_funclist;
1110 opaque_lsa_config_write_router_callback (funclist, vty);
1111
paul718e3742002-12-13 20:15:29 +00001112 funclist = ospf_opaque_type9_funclist;
1113 opaque_lsa_config_write_router_callback (funclist, vty);
1114
1115 funclist = ospf_opaque_type10_funclist;
1116 opaque_lsa_config_write_router_callback (funclist, vty);
1117
1118 funclist = ospf_opaque_type11_funclist;
1119 opaque_lsa_config_write_router_callback (funclist, vty);
1120
1121 return;
1122}
1123
1124void
1125ospf_opaque_config_write_if (struct vty *vty, struct interface *ifp)
1126{
paul87d6f872004-09-24 08:01:38 +00001127 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001128
paul09e4efd2003-01-18 00:12:02 +00001129 funclist = ospf_opaque_wildcard_funclist;
1130 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1131
paul718e3742002-12-13 20:15:29 +00001132 funclist = ospf_opaque_type9_funclist;
1133 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1134
1135 funclist = ospf_opaque_type10_funclist;
1136 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1137
1138 funclist = ospf_opaque_type11_funclist;
1139 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1140
1141 return;
1142}
1143
1144void
1145ospf_opaque_config_write_debug (struct vty *vty)
1146{
paul87d6f872004-09-24 08:01:38 +00001147 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001148
paul09e4efd2003-01-18 00:12:02 +00001149 funclist = ospf_opaque_wildcard_funclist;
1150 opaque_lsa_config_write_debug_callback (funclist, vty);
1151
paul718e3742002-12-13 20:15:29 +00001152 funclist = ospf_opaque_type9_funclist;
1153 opaque_lsa_config_write_debug_callback (funclist, vty);
1154
1155 funclist = ospf_opaque_type10_funclist;
1156 opaque_lsa_config_write_debug_callback (funclist, vty);
1157
1158 funclist = ospf_opaque_type11_funclist;
1159 opaque_lsa_config_write_debug_callback (funclist, vty);
1160
1161 return;
1162}
1163
1164void
1165show_opaque_info_detail (struct vty *vty, struct ospf_lsa *lsa)
1166{
1167 struct lsa_header *lsah = (struct lsa_header *) lsa->data;
1168 u_int32_t lsid = ntohl (lsah->id.s_addr);
1169 u_char opaque_type = GET_OPAQUE_TYPE (lsid);
1170 u_int32_t opaque_id = GET_OPAQUE_ID (lsid);
1171 struct ospf_opaque_functab *functab;
1172
1173 /* Switch output functionality by vty address. */
1174 if (vty != NULL)
1175 {
paul020709f2003-04-04 02:44:16 +00001176 vty_out (vty, " Opaque-Type %u (%s)%s", opaque_type,
1177 ospf_opaque_type_name (opaque_type), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001178 vty_out (vty, " Opaque-ID 0x%x%s", opaque_id, VTY_NEWLINE);
1179
1180 vty_out (vty, " Opaque-Info: %u octets of data%s%s",
1181 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1182 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)",
1183 VTY_NEWLINE);
1184 }
1185 else
1186 {
ajs2a42e282004-12-08 18:43:03 +00001187 zlog_debug (" Opaque-Type %u (%s)", opaque_type,
paul020709f2003-04-04 02:44:16 +00001188 ospf_opaque_type_name (opaque_type));
ajs2a42e282004-12-08 18:43:03 +00001189 zlog_debug (" Opaque-ID 0x%x", opaque_id);
paul718e3742002-12-13 20:15:29 +00001190
ajs2a42e282004-12-08 18:43:03 +00001191 zlog_debug (" Opaque-Info: %u octets of data%s",
paul718e3742002-12-13 20:15:29 +00001192 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1193 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)");
1194 }
1195
1196 /* Call individual output functions. */
1197 if ((functab = ospf_opaque_functab_lookup (lsa)) != NULL)
1198 if (functab->show_opaque_info != NULL)
1199 (* functab->show_opaque_info)(vty, lsa);
1200
1201 return;
1202}
1203
1204void
1205ospf_opaque_lsa_dump (struct stream *s, u_int16_t length)
1206{
1207 struct ospf_lsa lsa;
1208
1209 lsa.data = (struct lsa_header *) STREAM_PNT (s);
1210 show_opaque_info_detail (NULL, &lsa);
1211 return;
1212}
1213
1214static int
1215ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa)
1216{
paul87d6f872004-09-24 08:01:38 +00001217 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001218 int rc = -1;
1219
1220 /*
1221 * Some Opaque-LSA user may want to monitor every LSA installation
1222 * into the LSDB, regardless with target LSA type.
1223 */
paul09e4efd2003-01-18 00:12:02 +00001224 funclist = ospf_opaque_wildcard_funclist;
1225 if (new_lsa_callback (funclist, lsa) != 0)
1226 goto out;
1227
paul718e3742002-12-13 20:15:29 +00001228 funclist = ospf_opaque_type9_funclist;
1229 if (new_lsa_callback (funclist, lsa) != 0)
1230 goto out;
1231
1232 funclist = ospf_opaque_type10_funclist;
1233 if (new_lsa_callback (funclist, lsa) != 0)
1234 goto out;
1235
1236 funclist = ospf_opaque_type11_funclist;
1237 if (new_lsa_callback (funclist, lsa) != 0)
1238 goto out;
1239
1240 rc = 0;
1241out:
1242 return rc;
1243}
1244
1245static int
1246ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa)
1247{
paul87d6f872004-09-24 08:01:38 +00001248 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001249 int rc = -1;
1250
1251 /*
1252 * Some Opaque-LSA user may want to monitor every LSA deletion
1253 * from the LSDB, regardless with target LSA type.
1254 */
paul09e4efd2003-01-18 00:12:02 +00001255 funclist = ospf_opaque_wildcard_funclist;
1256 if (del_lsa_callback (funclist, lsa) != 0)
1257 goto out;
1258
paul718e3742002-12-13 20:15:29 +00001259 funclist = ospf_opaque_type9_funclist;
1260 if (del_lsa_callback (funclist, lsa) != 0)
1261 goto out;
1262
1263 funclist = ospf_opaque_type10_funclist;
1264 if (del_lsa_callback (funclist, lsa) != 0)
1265 goto out;
1266
1267 funclist = ospf_opaque_type11_funclist;
1268 if (del_lsa_callback (funclist, lsa) != 0)
1269 goto out;
1270
1271 rc = 0;
1272out:
1273 return rc;
1274}
1275
1276/*------------------------------------------------------------------------*
1277 * Followings are Opaque-LSA origination/refresh management functions.
1278 *------------------------------------------------------------------------*/
1279
1280static int ospf_opaque_type9_lsa_originate (struct thread *t);
1281static int ospf_opaque_type10_lsa_originate (struct thread *t);
1282static int ospf_opaque_type11_lsa_originate (struct thread *t);
paul87d6f872004-09-24 08:01:38 +00001283static void ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg);
paul718e3742002-12-13 20:15:29 +00001284
1285void
1286ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0)
1287{
1288 struct ospf *top;
1289 struct ospf_area *area;
paul1eb8ef22005-04-07 07:30:20 +00001290 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001291 struct opaque_info_per_type *oipt;
1292 int delay = 0;
1293
1294 if ((top = oi_to_top (oi)) == NULL || (area = oi->area) == NULL)
1295 {
1296 zlog_warn ("ospf_opaque_lsa_originate_schedule: Invalid argument?");
1297 goto out;
1298 }
1299
1300 /* It may not a right time to schedule origination now. */
1301 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1302 {
1303 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001304 zlog_debug ("ospf_opaque_lsa_originate_schedule: Not operational.");
paul718e3742002-12-13 20:15:29 +00001305 goto out; /* This is not an error. */
1306 }
Paul Jakmae30677a2015-01-20 15:45:36 +00001307
paul718e3742002-12-13 20:15:29 +00001308 if (delay0 != NULL)
1309 delay = *delay0;
1310
1311 /*
1312 * There might be some entries that have been waiting for triggering
1313 * of per opaque-type re-origination get resumed.
1314 */
1315 ospf_opaque_lsa_reoriginate_resume ( oi->opaque_lsa_self, (void *) oi);
1316 ospf_opaque_lsa_reoriginate_resume (area->opaque_lsa_self, (void *) area);
1317 ospf_opaque_lsa_reoriginate_resume ( top->opaque_lsa_self, (void *) top);
1318
1319 /*
1320 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1321 */
1322 if (! list_isempty (ospf_opaque_type9_funclist)
1323 && list_isempty (oi->opaque_lsa_self)
1324 && oi->t_opaque_lsa_self == NULL)
1325 {
1326 if (IS_DEBUG_OSPF_EVENT)
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001327 zlog_debug ("Schedule Type-9 Opaque-LSA origination in %d ms later.", delay);
paul718e3742002-12-13 20:15:29 +00001328 oi->t_opaque_lsa_self =
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001329 thread_add_timer_msec (master, ospf_opaque_type9_lsa_originate, oi, delay);
1330 delay += top->min_ls_interval;
paul718e3742002-12-13 20:15:29 +00001331 }
1332
1333 if (! list_isempty (ospf_opaque_type10_funclist)
1334 && list_isempty (area->opaque_lsa_self)
1335 && area->t_opaque_lsa_self == NULL)
1336 {
1337 /*
1338 * One AREA may contain multiple OIs, but above 2nd and 3rd
1339 * conditions prevent from scheduling the originate function
1340 * again and again.
1341 */
1342 if (IS_DEBUG_OSPF_EVENT)
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001343 zlog_debug ("Schedule Type-10 Opaque-LSA origination in %d ms later.", delay);
paul718e3742002-12-13 20:15:29 +00001344 area->t_opaque_lsa_self =
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001345 thread_add_timer_msec (master, ospf_opaque_type10_lsa_originate,
paul718e3742002-12-13 20:15:29 +00001346 area, delay);
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001347 delay += top->min_ls_interval;
paul718e3742002-12-13 20:15:29 +00001348 }
1349
1350 if (! list_isempty (ospf_opaque_type11_funclist)
1351 && list_isempty (top->opaque_lsa_self)
1352 && top->t_opaque_lsa_self == NULL)
1353 {
1354 /*
1355 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1356 * conditions prevent from scheduling the originate function
1357 * again and again.
1358 */
1359 if (IS_DEBUG_OSPF_EVENT)
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001360 zlog_debug ("Schedule Type-11 Opaque-LSA origination in %d ms later.", delay);
paul718e3742002-12-13 20:15:29 +00001361 top->t_opaque_lsa_self =
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001362 thread_add_timer_msec (master, ospf_opaque_type11_lsa_originate,
paul718e3742002-12-13 20:15:29 +00001363 top, delay);
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001364 delay += top->min_ls_interval;
paul718e3742002-12-13 20:15:29 +00001365 }
1366
1367 /*
1368 * Following section treats a special situation that this node's
1369 * opaque capability has changed as "ON -> OFF -> ON".
1370 */
1371 if (! list_isempty (ospf_opaque_type9_funclist)
1372 && ! list_isempty (oi->opaque_lsa_self))
1373 {
paul1eb8ef22005-04-07 07:30:20 +00001374 for (ALL_LIST_ELEMENTS (oi->opaque_lsa_self, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001375 {
hasso0d85b992004-03-18 19:18:33 +00001376 /*
1377 * removed the test for
1378 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1379 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1380 * not being empty.
1381 */
paul1eb8ef22005-04-07 07:30:20 +00001382 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1383 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001384 continue;
1385
1386 ospf_opaque_lsa_reoriginate_schedule ((void *) oi,
1387 OSPF_OPAQUE_LINK_LSA, oipt->opaque_type);
1388 }
1389 }
1390
1391 if (! list_isempty (ospf_opaque_type10_funclist)
1392 && ! list_isempty (area->opaque_lsa_self))
1393 {
paul1eb8ef22005-04-07 07:30:20 +00001394 for (ALL_LIST_ELEMENTS (area->opaque_lsa_self, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001395 {
hasso0d85b992004-03-18 19:18:33 +00001396 /*
1397 * removed the test for
1398 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1399 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1400 * not being empty.
1401 */
paul1eb8ef22005-04-07 07:30:20 +00001402 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1403 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001404 continue;
1405
1406 ospf_opaque_lsa_reoriginate_schedule ((void *) area,
1407 OSPF_OPAQUE_AREA_LSA, oipt->opaque_type);
1408 }
1409 }
1410
1411 if (! list_isempty (ospf_opaque_type11_funclist)
1412 && ! list_isempty (top->opaque_lsa_self))
1413 {
paul1eb8ef22005-04-07 07:30:20 +00001414 for (ALL_LIST_ELEMENTS (top->opaque_lsa_self, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001415 {
hasso0d85b992004-03-18 19:18:33 +00001416 /*
1417 * removed the test for
1418 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1419 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1420 * not being empty.
1421 */
paul1eb8ef22005-04-07 07:30:20 +00001422 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1423 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001424 continue;
1425
1426 ospf_opaque_lsa_reoriginate_schedule ((void *) top,
1427 OSPF_OPAQUE_AS_LSA, oipt->opaque_type);
1428 }
1429 }
1430
1431 if (delay0 != NULL)
1432 *delay0 = delay;
1433
1434out:
1435 return;
1436}
1437
1438static int
1439ospf_opaque_type9_lsa_originate (struct thread *t)
1440{
1441 struct ospf_interface *oi;
1442 int rc;
1443
1444 oi = THREAD_ARG (t);
1445 oi->t_opaque_lsa_self = NULL;
1446
1447 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001448 zlog_debug ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
paul718e3742002-12-13 20:15:29 +00001449 IF_NAME (oi));
1450
1451 rc = opaque_lsa_originate_callback (ospf_opaque_type9_funclist, oi);
1452
1453 return rc;
1454}
1455
1456static int
1457ospf_opaque_type10_lsa_originate (struct thread *t)
1458{
1459 struct ospf_area *area;
1460 int rc;
1461
1462 area = THREAD_ARG (t);
1463 area->t_opaque_lsa_self = NULL;
1464
1465 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001466 zlog_debug ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
paul718e3742002-12-13 20:15:29 +00001467 inet_ntoa (area->area_id));
1468
1469 rc = opaque_lsa_originate_callback (ospf_opaque_type10_funclist, area);
1470
1471 return rc;
1472}
1473
1474static int
1475ospf_opaque_type11_lsa_originate (struct thread *t)
1476{
1477 struct ospf *top;
1478 int rc;
1479
1480 top = THREAD_ARG (t);
1481 top->t_opaque_lsa_self = NULL;
1482
1483 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001484 zlog_debug ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
paul718e3742002-12-13 20:15:29 +00001485
1486 rc = opaque_lsa_originate_callback (ospf_opaque_type11_funclist, top);
1487
1488 return rc;
1489}
1490
1491static void
paul87d6f872004-09-24 08:01:38 +00001492ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg)
paul718e3742002-12-13 20:15:29 +00001493{
paul1eb8ef22005-04-07 07:30:20 +00001494 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001495 struct opaque_info_per_type *oipt;
1496 struct ospf_opaque_functab *functab;
1497
1498 if (listtop == NULL)
1499 goto out;
1500
1501 /*
1502 * Pickup oipt entries those which in SUSPEND status, and give
1503 * them a chance to start re-origination now.
1504 */
paul1eb8ef22005-04-07 07:30:20 +00001505 for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001506 {
paul87d6f872004-09-24 08:01:38 +00001507 if (oipt->status != PROC_SUSPEND)
paul718e3742002-12-13 20:15:29 +00001508 continue;
1509
1510 oipt->status = PROC_NORMAL;
1511
1512 if ((functab = oipt->functab) == NULL
paul87d6f872004-09-24 08:01:38 +00001513 || functab->lsa_originator == NULL)
paul718e3742002-12-13 20:15:29 +00001514 continue;
1515
1516 if ((* functab->lsa_originator)(arg) != 0)
1517 {
1518 zlog_warn ("ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", oipt->opaque_type);
1519 continue;
1520 }
1521 }
1522
1523out:
1524 return;
1525}
1526
1527struct ospf_lsa *
1528ospf_opaque_lsa_install (struct ospf_lsa *lsa, int rt_recalc)
1529{
1530 struct ospf_lsa *new = NULL;
1531 struct opaque_info_per_type *oipt;
1532 struct opaque_info_per_id *oipi;
1533 struct ospf *top;
1534
1535 /* Don't take "rt_recalc" into consideration for now. *//* XXX */
1536
1537 if (! IS_LSA_SELF (lsa))
1538 {
1539 new = lsa; /* Don't touch this LSA. */
1540 goto out;
1541 }
1542
1543 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
ajs2a42e282004-12-08 18:43:03 +00001544 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 +00001545
1546 /* Replace the existing lsa with the new one. */
1547 if ((oipt = lookup_opaque_info_by_type (lsa)) != NULL
paul87d6f872004-09-24 08:01:38 +00001548 && (oipi = lookup_opaque_info_by_id (oipt, lsa)) != NULL)
paul718e3742002-12-13 20:15:29 +00001549 {
Paul Jakma1fe6ed32006-07-26 09:37:26 +00001550 ospf_lsa_unlock (&oipi->lsa);
paul718e3742002-12-13 20:15:29 +00001551 oipi->lsa = ospf_lsa_lock (lsa);
1552 }
1553 /* Register the new lsa entry and get its control info. */
1554 else
1555 if ((oipi = register_opaque_lsa (lsa)) == NULL)
1556 {
1557 zlog_warn ("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1558 goto out;
1559 }
1560
1561 /*
1562 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1563 * for periodic refresh of self-originated Opaque-LSAs.
1564 */
1565 switch (lsa->data->type)
1566 {
1567 case OSPF_OPAQUE_LINK_LSA:
paul09e4efd2003-01-18 00:12:02 +00001568 if ((top = oi_to_top (lsa->oi)) == NULL)
1569 {
1570 /* Above conditions must have passed. */
1571 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1572 goto out;
1573 }
1574 break;
paul718e3742002-12-13 20:15:29 +00001575 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00001576 if (lsa->area == NULL || (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001577 {
1578 /* Above conditions must have passed. */
1579 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1580 goto out;
1581 }
1582 break;
1583 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +00001584 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001585 if (lsa->area != NULL && (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001586 {
1587 /* Above conditions must have passed. */
1588 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1589 goto out;
1590 }
1591 break;
1592 default:
1593 zlog_warn ("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", lsa->data->type);
1594 goto out;
1595 }
1596
1597 ospf_refresher_register_lsa (top, lsa);
1598 new = lsa;
1599
1600out:
1601 return new;
1602}
1603
Paul Jakmad71ea652011-03-22 15:23:55 +00001604struct ospf_lsa *
paul718e3742002-12-13 20:15:29 +00001605ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
1606{
paul020709f2003-04-04 02:44:16 +00001607 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001608 struct ospf_opaque_functab *functab;
Paul Jakmad71ea652011-03-22 15:23:55 +00001609 struct ospf_lsa *new = NULL;
1610
paul020709f2003-04-04 02:44:16 +00001611 ospf = ospf_lookup ();
1612
paul718e3742002-12-13 20:15:29 +00001613 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL
paul87d6f872004-09-24 08:01:38 +00001614 || functab->lsa_refresher == NULL)
paul718e3742002-12-13 20:15:29 +00001615 {
1616 /*
1617 * Though this LSA seems to have originated on this node, the
1618 * handling module for this "lsa-type and opaque-type" was
1619 * already deleted sometime ago.
1620 * Anyway, this node still has a responsibility to flush this
1621 * LSA from the routing domain.
1622 */
1623 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001624 zlog_debug ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id));
paul718e3742002-12-13 20:15:29 +00001625
1626 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
Paul Jakma02d942c2010-01-24 23:36:20 +00001627 ospf_lsa_flush (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00001628 }
1629 else
Paul Jakmad71ea652011-03-22 15:23:55 +00001630 new = (* functab->lsa_refresher)(lsa);
paul718e3742002-12-13 20:15:29 +00001631
Paul Jakmad71ea652011-03-22 15:23:55 +00001632 return new;
paul718e3742002-12-13 20:15:29 +00001633}
1634
1635/*------------------------------------------------------------------------*
1636 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1637 * triggered by external interventions (vty session, signaling, etc).
1638 *------------------------------------------------------------------------*/
1639
1640#define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
1641 if (!(T)) \
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001642 (T) = thread_add_timer_msec (master, (F), (L), (V))
paul718e3742002-12-13 20:15:29 +00001643
1644static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type);
1645static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t);
1646static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t);
1647static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t);
1648static int ospf_opaque_lsa_refresh_timer (struct thread *t);
1649
1650void
1651ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
1652 u_char lsa_type, u_char opaque_type)
1653{
1654 struct ospf *top;
1655 struct ospf_area dummy, *area = NULL;
1656 struct ospf_interface *oi = NULL;
1657
1658 struct ospf_lsa *lsa;
1659 struct opaque_info_per_type *oipt;
paul87d6f872004-09-24 08:01:38 +00001660 int (*func) (struct thread * t) = NULL;
paul718e3742002-12-13 20:15:29 +00001661 int delay;
1662
1663 switch (lsa_type)
1664 {
1665 case OSPF_OPAQUE_LINK_LSA:
1666 if ((oi = (struct ospf_interface *) lsa_type_dependent) == NULL)
1667 {
paul87d6f872004-09-24 08:01:38 +00001668 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1669 " Type-9 Opaque-LSA: Invalid parameter?");
1670 goto out;
paul718e3742002-12-13 20:15:29 +00001671 }
1672 if ((top = oi_to_top (oi)) == NULL)
1673 {
paul87d6f872004-09-24 08:01:38 +00001674 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1675 IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001676 goto out;
1677 }
paul87d6f872004-09-24 08:01:38 +00001678 if (!list_isempty (ospf_opaque_type9_funclist)
1679 && list_isempty (oi->opaque_lsa_self)
1680 && oi->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001681 {
paul87d6f872004-09-24 08:01:38 +00001682 zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u):"
1683 " Common origination for OI(%s) has already started",
1684 opaque_type, IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001685 goto out;
1686 }
1687 func = ospf_opaque_type9_lsa_reoriginate_timer;
1688 break;
1689 case OSPF_OPAQUE_AREA_LSA:
1690 if ((area = (struct ospf_area *) lsa_type_dependent) == NULL)
1691 {
paul87d6f872004-09-24 08:01:38 +00001692 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1693 " Type-10 Opaque-LSA: Invalid parameter?");
paul718e3742002-12-13 20:15:29 +00001694 goto out;
1695 }
paul68980082003-03-25 05:07:42 +00001696 if ((top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001697 {
paul87d6f872004-09-24 08:01:38 +00001698 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1699 " AREA(%s) -> TOP?", inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001700 goto out;
1701 }
paul87d6f872004-09-24 08:01:38 +00001702 if (!list_isempty (ospf_opaque_type10_funclist)
1703 && list_isempty (area->opaque_lsa_self)
1704 && area->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001705 {
paul87d6f872004-09-24 08:01:38 +00001706 zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u):"
1707 " Common origination for AREA(%s) has already started",
1708 opaque_type, inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001709 goto out;
1710 }
1711 func = ospf_opaque_type10_lsa_reoriginate_timer;
1712 break;
1713 case OSPF_OPAQUE_AS_LSA:
1714 if ((top = (struct ospf *) lsa_type_dependent) == NULL)
1715 {
paul87d6f872004-09-24 08:01:38 +00001716 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1717 " Type-11 Opaque-LSA: Invalid parameter?");
1718 goto out;
paul718e3742002-12-13 20:15:29 +00001719 }
paul87d6f872004-09-24 08:01:38 +00001720 if (!list_isempty (ospf_opaque_type11_funclist)
1721 && list_isempty (top->opaque_lsa_self)
1722 && top->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001723 {
paul87d6f872004-09-24 08:01:38 +00001724 zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u):"
1725 " Common origination has already started", opaque_type);
paul718e3742002-12-13 20:15:29 +00001726 goto out;
1727 }
1728
1729 /* Fake "area" to pass "ospf" to a lookup function later. */
paul68980082003-03-25 05:07:42 +00001730 dummy.ospf = top;
paul718e3742002-12-13 20:15:29 +00001731 area = &dummy;
1732
1733 func = ospf_opaque_type11_lsa_reoriginate_timer;
1734 break;
1735 default:
paul87d6f872004-09-24 08:01:38 +00001736 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1737 " Unexpected LSA-type(%u)",
1738 lsa_type);
paul718e3742002-12-13 20:15:29 +00001739 goto out;
1740 }
1741
1742 /* It may not a right time to schedule reorigination now. */
paul87d6f872004-09-24 08:01:38 +00001743 if (!CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
paul718e3742002-12-13 20:15:29 +00001744 {
1745 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001746 zlog_debug ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
paul87d6f872004-09-24 08:01:38 +00001747 goto out; /* This is not an error. */
paul718e3742002-12-13 20:15:29 +00001748 }
Paul Jakmae30677a2015-01-20 15:45:36 +00001749
paul718e3742002-12-13 20:15:29 +00001750 /* Generate a dummy lsa to be passed for a lookup function. */
1751 lsa = pseudo_lsa (oi, area, lsa_type, opaque_type);
1752
1753 if ((oipt = lookup_opaque_info_by_type (lsa)) == NULL)
1754 {
1755 struct ospf_opaque_functab *functab;
1756 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL)
1757 {
paul87d6f872004-09-24 08:01:38 +00001758 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1759 " No associated function?: lsa_type(%u),"
1760 " opaque_type(%u)",
1761 lsa_type, opaque_type);
paul718e3742002-12-13 20:15:29 +00001762 goto out;
1763 }
1764 if ((oipt = register_opaque_info_per_type (functab, lsa)) == NULL)
1765 {
paul87d6f872004-09-24 08:01:38 +00001766 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1767 " Cannot get a control info?: lsa_type(%u),"
1768 " opaque_type(%u)",
1769 lsa_type, opaque_type);
paul718e3742002-12-13 20:15:29 +00001770 goto out;
1771 }
1772 }
1773
1774 if (oipt->t_opaque_lsa_self != NULL)
1775 {
1776 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001777 zlog_debug ("Type-%u Opaque-LSA has already scheduled to"
paul87d6f872004-09-24 08:01:38 +00001778 " RE-ORIGINATE: [opaque-type=%u]",
1779 lsa_type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
paul718e3742002-12-13 20:15:29 +00001780 goto out;
1781 }
1782
1783 /*
1784 * Different from initial origination time, in which various conditions
1785 * (opaque capability, neighbor status etc) are assured by caller of
1786 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1787 * it is highly possible that these conditions might not be satisfied
1788 * at the time of re-origination function is to be called.
1789 */
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001790 delay = top->min_ls_interval; /* XXX */
paul718e3742002-12-13 20:15:29 +00001791
1792 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001793 zlog_debug ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001794 " ms later: [opaque-type=%u]",
paul87d6f872004-09-24 08:01:38 +00001795 lsa_type, delay,
1796 GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
paul718e3742002-12-13 20:15:29 +00001797
1798 OSPF_OPAQUE_TIMER_ON (oipt->t_opaque_lsa_self, func, oipt, delay);
1799
1800out:
1801 return;
1802}
1803
1804static struct ospf_lsa *
1805pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area,
1806 u_char lsa_type, u_char opaque_type)
1807{
1808 static struct ospf_lsa lsa = { 0 };
1809 static struct lsa_header lsah = { 0 };
1810 u_int32_t tmp;
1811
1812 lsa.oi = oi;
1813 lsa.area = area;
1814 lsa.data = &lsah;
1815
1816 lsah.type = lsa_type;
1817 tmp = SET_OPAQUE_LSID (opaque_type, 0); /* Opaque-ID is unused here. */
1818 lsah.id.s_addr = htonl (tmp);
1819
1820 return &lsa;
1821}
1822
1823static int
1824ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t)
1825{
1826 struct opaque_info_per_type *oipt;
1827 struct ospf_opaque_functab *functab;
1828 struct ospf *top;
1829 struct ospf_interface *oi;
1830 int rc = -1;
1831
1832 oipt = THREAD_ARG (t);
1833 oipt->t_opaque_lsa_self = NULL;
1834
1835 if ((functab = oipt->functab) == NULL
1836 || functab->lsa_originator == NULL)
1837 {
1838 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1839 goto out;
1840 }
1841
1842 oi = (struct ospf_interface *) oipt->owner;
1843 if ((top = oi_to_top (oi)) == NULL)
1844 {
1845 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1846 goto out;
1847 }
1848
1849 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)
1850 || ! ospf_if_is_enable (oi)
paul68980082003-03-25 05:07:42 +00001851 || ospf_nbr_count_opaque_capable (oi) == 0)
paul718e3742002-12-13 20:15:29 +00001852 {
1853 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001854 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 +00001855
1856 oipt->status = PROC_SUSPEND;
1857 rc = 0;
1858 goto out;
1859 }
1860
1861 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001862 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 +00001863
1864 rc = (* functab->lsa_originator)(oi);
1865out:
1866 return rc;
1867}
1868
1869static int
1870ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t)
1871{
1872 struct opaque_info_per_type *oipt;
1873 struct ospf_opaque_functab *functab;
paul1eb8ef22005-04-07 07:30:20 +00001874 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001875 struct ospf *top;
1876 struct ospf_area *area;
1877 struct ospf_interface *oi;
1878 int n, rc = -1;
1879
1880 oipt = THREAD_ARG (t);
1881 oipt->t_opaque_lsa_self = NULL;
1882
1883 if ((functab = oipt->functab) == NULL
1884 || functab->lsa_originator == NULL)
1885 {
1886 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1887 goto out;
1888 }
1889
1890 area = (struct ospf_area *) oipt->owner;
paul68980082003-03-25 05:07:42 +00001891 if (area == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001892 {
1893 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1894 goto out;
1895 }
1896
1897 /* There must be at least one "opaque-capable, full-state" neighbor. */
1898 n = 0;
paul1eb8ef22005-04-07 07:30:20 +00001899 for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi))
paul718e3742002-12-13 20:15:29 +00001900 {
paul68980082003-03-25 05:07:42 +00001901 if ((n = ospf_nbr_count_opaque_capable (oi)) > 0)
paul718e3742002-12-13 20:15:29 +00001902 break;
1903 }
1904
1905 if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1906 {
1907 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001908 zlog_debug ("Suspend re-origination of Type-10 Opaque-LSAs"
paul87d6f872004-09-24 08:01:38 +00001909 " (opaque-type=%u) for a while...",
1910 oipt->opaque_type);
paul718e3742002-12-13 20:15:29 +00001911
1912 oipt->status = PROC_SUSPEND;
1913 rc = 0;
1914 goto out;
1915 }
1916
1917 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001918 zlog_debug ("Timer[Type10-LSA]: Re-originate Opaque-LSAs"
paul87d6f872004-09-24 08:01:38 +00001919 " (opaque-type=%u) for Area %s",
1920 oipt->opaque_type, inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001921
1922 rc = (* functab->lsa_originator)(area);
1923out:
1924 return rc;
1925}
1926
1927static int
1928ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t)
1929{
1930 struct opaque_info_per_type *oipt;
1931 struct ospf_opaque_functab *functab;
1932 struct ospf *top;
1933 int rc = -1;
1934
1935 oipt = THREAD_ARG (t);
1936 oipt->t_opaque_lsa_self = NULL;
1937
1938 if ((functab = oipt->functab) == NULL
paul87d6f872004-09-24 08:01:38 +00001939 || functab->lsa_originator == NULL)
paul718e3742002-12-13 20:15:29 +00001940 {
paul87d6f872004-09-24 08:01:38 +00001941 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer:"
1942 " No associated function?");
paul718e3742002-12-13 20:15:29 +00001943 goto out;
1944 }
1945
1946 if ((top = (struct ospf *) oipt->owner) == NULL)
1947 {
1948 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1949 goto out;
1950 }
1951
1952 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1953 {
1954 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001955 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 +00001956
1957 oipt->status = PROC_SUSPEND;
1958 rc = 0;
1959 goto out;
1960 }
1961
1962 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001963 zlog_debug ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type);
paul718e3742002-12-13 20:15:29 +00001964
1965 rc = (* functab->lsa_originator)(top);
1966out:
1967 return rc;
1968}
1969
paul718e3742002-12-13 20:15:29 +00001970void
1971ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
1972{
1973 struct opaque_info_per_type *oipt;
1974 struct opaque_info_per_id *oipi;
1975 struct ospf_lsa *lsa;
1976 int delay;
1977
1978 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
1979 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
1980 {
1981 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
1982 goto out;
1983 }
1984
1985 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
1986 if ((lsa = oipi->lsa) == NULL)
1987 {
1988 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
1989 goto out;
1990 }
1991
1992 if (oipi->t_opaque_lsa_self != NULL)
1993 {
1994 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001995 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 +00001996 goto out;
1997 }
1998
1999 /* Delete this lsa from neighbor retransmit-list. */
2000 switch (lsa->data->type)
2001 {
2002 case OSPF_OPAQUE_LINK_LSA:
2003 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002004 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002005 break;
2006 case OSPF_OPAQUE_AS_LSA:
ajse6a0bf92005-09-17 18:53:38 +00002007 ospf_ls_retransmit_delete_nbr_as (lsa0->area->ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002008 break;
2009 default:
2010 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2011 goto out;
2012 }
2013
2014 delay = ospf_lsa_refresh_delay (lsa);
2015
2016 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002017 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 +00002018
2019 OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self,
Michael Rossberg2ef762e2015-07-27 07:56:25 +02002020 ospf_opaque_lsa_refresh_timer, oipi, delay * 1000);
paul718e3742002-12-13 20:15:29 +00002021out:
2022 return;
2023}
2024
2025static int
2026ospf_opaque_lsa_refresh_timer (struct thread *t)
2027{
2028 struct opaque_info_per_id *oipi;
2029 struct ospf_opaque_functab *functab;
2030 struct ospf_lsa *lsa;
2031
2032 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002033 zlog_debug ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
paul718e3742002-12-13 20:15:29 +00002034
2035 oipi = THREAD_ARG (t);
2036 oipi->t_opaque_lsa_self = NULL;
2037
2038 if ((lsa = oipi->lsa) != NULL)
2039 if ((functab = oipi->opqctl_type->functab) != NULL)
2040 if (functab->lsa_refresher != NULL)
2041 (* functab->lsa_refresher)(lsa);
2042
2043 return 0;
2044}
2045
2046void
2047ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
2048{
2049 struct opaque_info_per_type *oipt;
2050 struct opaque_info_per_id *oipi;
2051 struct ospf_lsa *lsa;
2052
2053 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
2054 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
2055 {
2056 zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2057 goto out;
2058 }
2059
2060 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2061 if ((lsa = oipi->lsa) == NULL)
2062 {
2063 zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
2064 goto out;
2065 }
2066
2067 /* Delete this lsa from neighbor retransmit-list. */
2068 switch (lsa->data->type)
2069 {
2070 case OSPF_OPAQUE_LINK_LSA:
2071 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002072 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002073 break;
2074 case OSPF_OPAQUE_AS_LSA:
ajse6a0bf92005-09-17 18:53:38 +00002075 ospf_ls_retransmit_delete_nbr_as (lsa0->area->ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002076 break;
2077 default:
2078 zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2079 goto out;
2080 }
2081
2082 /* Dequeue listnode entry from the list. */
2083 listnode_delete (oipt->id_list, oipi);
2084
2085 /* Avoid misjudgement in the next lookup. */
2086 if (listcount (oipt->id_list) == 0)
2087 oipt->id_list->head = oipt->id_list->tail = NULL;
2088
2089 /* Disassociate internal control information with the given lsa. */
paul718e3742002-12-13 20:15:29 +00002090 free_opaque_info_per_id ((void *) oipi);
2091
2092 /* Force given lsa's age to MaxAge. */
2093 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2094
2095 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002096 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 +00002097
2098 /* This lsa will be flushed and removed eventually. */
Paul Jakma02d942c2010-01-24 23:36:20 +00002099 ospf_lsa_flush (lsa0->area->ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002100
2101out:
2102 return;
2103}
2104
paul718e3742002-12-13 20:15:29 +00002105void
paul87d6f872004-09-24 08:01:38 +00002106ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr,
paul69310a62005-05-11 18:09:59 +00002107 struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002108{
2109 struct ospf *top;
Paul Jakmae30677a2015-01-20 15:45:36 +00002110
paul718e3742002-12-13 20:15:29 +00002111 if ((top = oi_to_top (nbr->oi)) == NULL)
Paul Jakma1fe6ed32006-07-26 09:37:26 +00002112 return;
paul718e3742002-12-13 20:15:29 +00002113
paul69310a62005-05-11 18:09:59 +00002114 /*
2115 * Since these LSA entries are not yet installed into corresponding
2116 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2117 */
2118 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2119 switch (lsa->data->type)
paul718e3742002-12-13 20:15:29 +00002120 {
paul69310a62005-05-11 18:09:59 +00002121 case OSPF_OPAQUE_LINK_LSA:
paul69310a62005-05-11 18:09:59 +00002122 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2123 break;
2124 case OSPF_OPAQUE_AREA_LSA:
paul69310a62005-05-11 18:09:59 +00002125 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2126 break;
2127 case OSPF_OPAQUE_AS_LSA:
paul69310a62005-05-11 18:09:59 +00002128 ospf_flood_through_as (top, NULL/*inbr*/, lsa);
2129 break;
2130 default:
2131 zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
Paul Jakma1fe6ed32006-07-26 09:37:26 +00002132 return;
paul718e3742002-12-13 20:15:29 +00002133 }
Paul Jakmae30677a2015-01-20 15:45:36 +00002134 ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */
paul718e3742002-12-13 20:15:29 +00002135}
2136
paul718e3742002-12-13 20:15:29 +00002137/*------------------------------------------------------------------------*
2138 * Followings are util functions; probably be used by Opaque-LSAs only...
2139 *------------------------------------------------------------------------*/
2140
2141void
2142htonf (float *src, float *dst)
2143{
2144 u_int32_t lu1, lu2;
2145
2146 memcpy (&lu1, src, sizeof (u_int32_t));
2147 lu2 = htonl (lu1);
2148 memcpy (dst, &lu2, sizeof (u_int32_t));
2149 return;
2150}
2151
2152void
2153ntohf (float *src, float *dst)
2154{
2155 u_int32_t lu1, lu2;
2156
2157 memcpy (&lu1, src, sizeof (u_int32_t));
2158 lu2 = ntohl (lu1);
2159 memcpy (dst, &lu2, sizeof (u_int32_t));
2160 return;
2161}
2162
2163struct ospf *
2164oi_to_top (struct ospf_interface *oi)
2165{
2166 struct ospf *top = NULL;
2167 struct ospf_area *area;
2168
paul68980082003-03-25 05:07:42 +00002169 if (oi == NULL || (area = oi->area) == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00002170 zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");
2171
2172 return top;
2173}
2174