blob: 6b069c808ba7e9890caad28ff0534a763d0e9e7a [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. *****/
David Lamparter23757db2016-02-24 06:26:02 +010025#define MTYPE_OSPF_OPAQUE_FUNCTAB MTYPE_TMP
26#define MTYPE_OPAQUE_INFO_PER_TYPE MTYPE_TMP
27#define MTYPE_OPAQUE_INFO_PER_ID MTYPE_TMP
paul718e3742002-12-13 20:15:29 +000028
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;
Olivier Dugeon29a14012016-04-19 18:42:40 +0200216 case OPAQUE_TYPE_INTER_AS_LSA:
217 name = "Inter-AS TE-v2 LSA";
218 break;
paul718e3742002-12-13 20:15:29 +0000219 default:
220 if (OPAQUE_TYPE_RANGE_UNASSIGNED (opaque_type))
221 name = "Unassigned";
Andrew Certain0798cee2012-12-04 13:43:42 -0800222 else
223 {
224 u_int32_t bigger_range = opaque_type;
225 /*
226 * Get around type-limits warning: comparison is always true due to limited range of data type
227 */
228 if (OPAQUE_TYPE_RANGE_RESERVED (bigger_range))
229 name = "Private/Experimental";
230 }
paul718e3742002-12-13 20:15:29 +0000231 break;
232 }
233 return name;
234}
235
236/*------------------------------------------------------------------------*
237 * Followings are management functions to store user specified callbacks.
238 *------------------------------------------------------------------------*/
239
240struct opaque_info_per_type; /* Forward declaration. */
241
242struct ospf_opaque_functab
243{
244 u_char opaque_type;
245 struct opaque_info_per_type *oipt;
246
247 int (* new_if_hook)(struct interface *ifp);
248 int (* del_if_hook)(struct interface *ifp);
249 void (* ism_change_hook)(struct ospf_interface *oi, int old_status);
250 void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status);
251 void (* config_write_router)(struct vty *vty);
252 void (* config_write_if )(struct vty *vty, struct interface *ifp);
253 void (* config_write_debug )(struct vty *vty);
254 void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa);
255 int (* lsa_originator)(void *arg);
Paul Jakmad71ea652011-03-22 15:23:55 +0000256 struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa);
paul718e3742002-12-13 20:15:29 +0000257 int (* new_lsa_hook)(struct ospf_lsa *lsa);
258 int (* del_lsa_hook)(struct ospf_lsa *lsa);
259};
260
paul87d6f872004-09-24 08:01:38 +0000261/* Handle LSA-9/10/11 altogether. */
262static struct list *ospf_opaque_wildcard_funclist;
263static struct list *ospf_opaque_type9_funclist;
264static struct list *ospf_opaque_type10_funclist;
265static struct list *ospf_opaque_type11_funclist;
paul718e3742002-12-13 20:15:29 +0000266
267static void
268ospf_opaque_del_functab (void *val)
269{
270 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, val);
271 return;
272}
273
274static void
275ospf_opaque_funclist_init (void)
276{
paul87d6f872004-09-24 08:01:38 +0000277 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000278
paul09e4efd2003-01-18 00:12:02 +0000279 funclist = ospf_opaque_wildcard_funclist = list_new ();
280 funclist->del = ospf_opaque_del_functab;
281
paul718e3742002-12-13 20:15:29 +0000282 funclist = ospf_opaque_type9_funclist = list_new ();
283 funclist->del = ospf_opaque_del_functab;
284
285 funclist = ospf_opaque_type10_funclist = list_new ();
286 funclist->del = ospf_opaque_del_functab;
287
288 funclist = ospf_opaque_type11_funclist = list_new ();
289 funclist->del = ospf_opaque_del_functab;
290 return;
291}
292
293static void
294ospf_opaque_funclist_term (void)
295{
paul87d6f872004-09-24 08:01:38 +0000296 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000297
paul09e4efd2003-01-18 00:12:02 +0000298 funclist = ospf_opaque_wildcard_funclist;
299 list_delete (funclist);
300
paul718e3742002-12-13 20:15:29 +0000301 funclist = ospf_opaque_type9_funclist;
302 list_delete (funclist);
303
304 funclist = ospf_opaque_type10_funclist;
305 list_delete (funclist);
306
307 funclist = ospf_opaque_type11_funclist;
308 list_delete (funclist);
309 return;
310}
311
paul87d6f872004-09-24 08:01:38 +0000312static struct list *
paul718e3742002-12-13 20:15:29 +0000313ospf_get_opaque_funclist (u_char lsa_type)
314{
paul87d6f872004-09-24 08:01:38 +0000315 struct list *funclist = NULL;
paul718e3742002-12-13 20:15:29 +0000316
317 switch (lsa_type)
318 {
paul09e4efd2003-01-18 00:12:02 +0000319 case OPAQUE_TYPE_WILDCARD:
320 /* XXX
321 * This is an ugly trick to handle type-9/10/11 LSA altogether.
322 * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor
323 * an officially assigned opaque-type.
324 * Though it is possible that the value might be officially used
325 * in the future, we use it internally as a special label, for now.
326 */
327 funclist = ospf_opaque_wildcard_funclist;
328 break;
paul718e3742002-12-13 20:15:29 +0000329 case OSPF_OPAQUE_LINK_LSA:
330 funclist = ospf_opaque_type9_funclist;
331 break;
332 case OSPF_OPAQUE_AREA_LSA:
333 funclist = ospf_opaque_type10_funclist;
334 break;
335 case OSPF_OPAQUE_AS_LSA:
336 funclist = ospf_opaque_type11_funclist;
337 break;
338 default:
339 zlog_warn ("ospf_get_opaque_funclist: Unexpected LSA-type(%u)", lsa_type);
340 break;
341 }
342 return funclist;
343}
344
paul87d6f872004-09-24 08:01:38 +0000345/* XXX: such a huge argument list can /not/ be healthy... */
paul718e3742002-12-13 20:15:29 +0000346int
347ospf_register_opaque_functab (
348 u_char lsa_type,
349 u_char opaque_type,
350 int (* new_if_hook)(struct interface *ifp),
351 int (* del_if_hook)(struct interface *ifp),
352 void (* ism_change_hook)(struct ospf_interface *oi, int old_status),
353 void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status),
354 void (* config_write_router)(struct vty *vty),
355 void (* config_write_if )(struct vty *vty, struct interface *ifp),
356 void (* config_write_debug )(struct vty *vty),
357 void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa),
358 int (* lsa_originator)(void *arg),
Paul Jakmad71ea652011-03-22 15:23:55 +0000359 struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa),
paul718e3742002-12-13 20:15:29 +0000360 int (* new_lsa_hook)(struct ospf_lsa *lsa),
361 int (* del_lsa_hook)(struct ospf_lsa *lsa))
362{
paul87d6f872004-09-24 08:01:38 +0000363 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000364 struct ospf_opaque_functab *new;
365 int rc = -1;
366
367 if ((funclist = ospf_get_opaque_funclist (lsa_type)) == NULL)
368 {
paul87d6f872004-09-24 08:01:38 +0000369 zlog_warn ("ospf_register_opaque_functab: Cannot get funclist"
370 " for Type-%u LSAs?",
371 lsa_type);
paul718e3742002-12-13 20:15:29 +0000372 goto out;
373 }
374 else
375 {
paul1eb8ef22005-04-07 07:30:20 +0000376 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000377 struct ospf_opaque_functab *functab;
paul87d6f872004-09-24 08:01:38 +0000378
paul1eb8ef22005-04-07 07:30:20 +0000379 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000380 if (functab->opaque_type == opaque_type)
381 {
382 zlog_warn ("ospf_register_opaque_functab: Duplicated entry?:"
383 " lsa_type(%u), opaque_type(%u)",
384 lsa_type, opaque_type);
385 goto out;
386 }
paul718e3742002-12-13 20:15:29 +0000387 }
388
389 if ((new = XCALLOC (MTYPE_OSPF_OPAQUE_FUNCTAB,
390 sizeof (struct ospf_opaque_functab))) == NULL)
391 {
paul87d6f872004-09-24 08:01:38 +0000392 zlog_warn ("ospf_register_opaque_functab: XMALLOC: %s",
ajs6099b3b2004-11-20 02:06:59 +0000393 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000394 goto out;
395 }
396
397 new->opaque_type = opaque_type;
398 new->oipt = NULL;
399 new->new_if_hook = new_if_hook;
400 new->del_if_hook = del_if_hook;
401 new->ism_change_hook = ism_change_hook;
402 new->nsm_change_hook = nsm_change_hook;
403 new->config_write_router = config_write_router;
404 new->config_write_if = config_write_if;
405 new->config_write_debug = config_write_debug;
406 new->show_opaque_info = show_opaque_info;
407 new->lsa_originator = lsa_originator;
408 new->lsa_refresher = lsa_refresher;
409 new->new_lsa_hook = new_lsa_hook;
410 new->del_lsa_hook = del_lsa_hook;
411
412 listnode_add (funclist, new);
413 rc = 0;
414
415out:
416 return rc;
417}
418
419void
420ospf_delete_opaque_functab (u_char lsa_type, u_char opaque_type)
421{
paul87d6f872004-09-24 08:01:38 +0000422 struct list *funclist;
paul1eb8ef22005-04-07 07:30:20 +0000423 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000424 struct ospf_opaque_functab *functab;
425
426 if ((funclist = ospf_get_opaque_funclist (lsa_type)) != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000427 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul718e3742002-12-13 20:15:29 +0000428 {
paul1eb8ef22005-04-07 07:30:20 +0000429 if (functab->opaque_type == opaque_type)
paul718e3742002-12-13 20:15:29 +0000430 {
431 /* Cleanup internal control information, if it still remains. */
432 if (functab->oipt != NULL)
433 free_opaque_info_per_type (functab->oipt);
434
435 /* Dequeue listnode entry from the list. */
436 listnode_delete (funclist, functab);
437
438 /* Avoid misjudgement in the next lookup. */
439 if (listcount (funclist) == 0)
440 funclist->head = funclist->tail = NULL;
441
442 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, functab);
paul87d6f872004-09-24 08:01:38 +0000443 break;
paul718e3742002-12-13 20:15:29 +0000444 }
445 }
paul87d6f872004-09-24 08:01:38 +0000446
paul718e3742002-12-13 20:15:29 +0000447 return;
448}
449
450static struct ospf_opaque_functab *
451ospf_opaque_functab_lookup (struct ospf_lsa *lsa)
452{
paul87d6f872004-09-24 08:01:38 +0000453 struct list *funclist;
454 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000455 struct ospf_opaque_functab *functab;
456 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
457
458 if ((funclist = ospf_get_opaque_funclist (lsa->data->type)) != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000459 for (ALL_LIST_ELEMENTS_RO (funclist, node, functab))
paul87d6f872004-09-24 08:01:38 +0000460 if (functab->opaque_type == key)
461 return functab;
paul718e3742002-12-13 20:15:29 +0000462
463 return NULL;
464}
465
466/*------------------------------------------------------------------------*
467 * Followings are management functions for self-originated LSA entries.
468 *------------------------------------------------------------------------*/
469
470/*
471 * Opaque-LSA control information per opaque-type.
472 * Single Opaque-Type may have multiple instances; each of them will be
473 * identified by their opaque-id.
474 */
475struct opaque_info_per_type
476{
paul09e4efd2003-01-18 00:12:02 +0000477 u_char lsa_type;
paul718e3742002-12-13 20:15:29 +0000478 u_char opaque_type;
479
480 enum { PROC_NORMAL, PROC_SUSPEND } status;
481
482 /*
483 * Thread for (re-)origination scheduling for this opaque-type.
484 *
485 * Initial origination of Opaque-LSAs is controlled by generic
486 * Opaque-LSA handling module so that same opaque-type entries are
487 * called all at once when certain conditions are met.
488 * However, there might be cases that some Opaque-LSA clients need
489 * to (re-)originate their own Opaque-LSAs out-of-sync with others.
490 * This thread is prepared for that specific purpose.
491 */
492 struct thread *t_opaque_lsa_self;
493
494 /*
paul09e4efd2003-01-18 00:12:02 +0000495 * Backpointer to an "owner" which is LSA-type dependent.
paul718e3742002-12-13 20:15:29 +0000496 * type-9: struct ospf_interface
497 * type-10: struct ospf_area
498 * type-11: struct ospf
499 */
500 void *owner;
501
502 /* Collection of callback functions for this opaque-type. */
503 struct ospf_opaque_functab *functab;
504
505 /* List of Opaque-LSA control informations per opaque-id. */
paul87d6f872004-09-24 08:01:38 +0000506 struct list *id_list;
paul718e3742002-12-13 20:15:29 +0000507};
508
509/* Opaque-LSA control information per opaque-id. */
510struct opaque_info_per_id
511{
512 u_int32_t opaque_id;
513
514 /* Thread for refresh/flush scheduling for this opaque-type/id. */
515 struct thread *t_opaque_lsa_self;
516
517 /* Backpointer to Opaque-LSA control information per opaque-type. */
518 struct opaque_info_per_type *opqctl_type;
519
520 /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
521 struct ospf_lsa *lsa;
522};
523
524static struct opaque_info_per_type *register_opaque_info_per_type (struct ospf_opaque_functab *functab, struct ospf_lsa *new);
525static struct opaque_info_per_type *lookup_opaque_info_by_type (struct ospf_lsa *lsa);
526static struct opaque_info_per_id *register_opaque_info_per_id (struct opaque_info_per_type *oipt, struct ospf_lsa *new);
527static struct opaque_info_per_id *lookup_opaque_info_by_id (struct opaque_info_per_type *oipt, struct ospf_lsa *lsa);
528static struct opaque_info_per_id *register_opaque_lsa (struct ospf_lsa *new);
529
530
531static struct opaque_info_per_type *
532register_opaque_info_per_type (struct ospf_opaque_functab *functab,
533 struct ospf_lsa *new)
534{
535 struct ospf *top;
536 struct opaque_info_per_type *oipt;
537
538 if ((oipt = XCALLOC (MTYPE_OPAQUE_INFO_PER_TYPE,
539 sizeof (struct opaque_info_per_type))) == NULL)
540 {
ajs6099b3b2004-11-20 02:06:59 +0000541 zlog_warn ("register_opaque_info_per_type: XMALLOC: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000542 goto out;
543 }
544
545 switch (new->data->type)
546 {
547 case OSPF_OPAQUE_LINK_LSA:
548 oipt->owner = new->oi;
549 listnode_add (new->oi->opaque_lsa_self, oipt);
550 break;
551 case OSPF_OPAQUE_AREA_LSA:
552 oipt->owner = new->area;
553 listnode_add (new->area->opaque_lsa_self, oipt);
554 break;
555 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +0000556 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000557 if (new->area != NULL && (top = new->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +0000558 {
559 free_opaque_info_per_type ((void *) oipt);
560 oipt = NULL;
561 goto out; /* This case may not exist. */
562 }
563 oipt->owner = top;
564 listnode_add (top->opaque_lsa_self, oipt);
565 break;
566 default:
paul09e4efd2003-01-18 00:12:02 +0000567 zlog_warn ("register_opaque_info_per_type: Unexpected LSA-type(%u)", new->data->type);
paul718e3742002-12-13 20:15:29 +0000568 free_opaque_info_per_type ((void *) oipt);
569 oipt = NULL;
570 goto out; /* This case may not exist. */
571 }
572
paul09e4efd2003-01-18 00:12:02 +0000573 oipt->lsa_type = new->data->type;
paul718e3742002-12-13 20:15:29 +0000574 oipt->opaque_type = GET_OPAQUE_TYPE (ntohl (new->data->id.s_addr));
575 oipt->status = PROC_NORMAL;
576 oipt->t_opaque_lsa_self = NULL;
577 oipt->functab = functab;
578 functab->oipt = oipt;
579 oipt->id_list = list_new ();
580 oipt->id_list->del = free_opaque_info_per_id;
581
582out:
583 return oipt;
584}
585
586static void
587free_opaque_info_per_type (void *val)
588{
589 struct opaque_info_per_type *oipt = (struct opaque_info_per_type *) val;
590 struct opaque_info_per_id *oipi;
591 struct ospf_lsa *lsa;
paul1eb8ef22005-04-07 07:30:20 +0000592 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000593
594 /* Control information per opaque-id may still exist. */
paul1eb8ef22005-04-07 07:30:20 +0000595 for (ALL_LIST_ELEMENTS (oipt->id_list, node, nnode, oipi))
paul718e3742002-12-13 20:15:29 +0000596 {
paul718e3742002-12-13 20:15:29 +0000597 if ((lsa = oipi->lsa) == NULL)
598 continue;
599 if (IS_LSA_MAXAGE (lsa))
600 continue;
601 ospf_opaque_lsa_flush_schedule (lsa);
602 }
603
paul09e4efd2003-01-18 00:12:02 +0000604 /* Remove "oipt" from its owner's self-originated LSA list. */
605 switch (oipt->lsa_type)
606 {
607 case OSPF_OPAQUE_LINK_LSA:
608 {
609 struct ospf_interface *oi = (struct ospf_interface *)(oipt->owner);
610 listnode_delete (oi->opaque_lsa_self, oipt);
611 break;
612 }
613 case OSPF_OPAQUE_AREA_LSA:
614 {
615 struct ospf_area *area = (struct ospf_area *)(oipt->owner);
616 listnode_delete (area->opaque_lsa_self, oipt);
617 break;
618 }
619 case OSPF_OPAQUE_AS_LSA:
620 {
621 struct ospf *top = (struct ospf *)(oipt->owner);
622 listnode_delete (top->opaque_lsa_self, oipt);
623 break;
624 }
625 default:
626 zlog_warn ("free_opaque_info_per_type: Unexpected LSA-type(%u)", oipt->lsa_type);
627 break; /* This case may not exist. */
628 }
629
paul718e3742002-12-13 20:15:29 +0000630 OSPF_TIMER_OFF (oipt->t_opaque_lsa_self);
631 list_delete (oipt->id_list);
632 XFREE (MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
633 return;
634}
635
636static struct opaque_info_per_type *
637lookup_opaque_info_by_type (struct ospf_lsa *lsa)
638{
639 struct ospf *top;
640 struct ospf_area *area;
641 struct ospf_interface *oi;
paul87d6f872004-09-24 08:01:38 +0000642 struct list *listtop = NULL;
paul1eb8ef22005-04-07 07:30:20 +0000643 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000644 struct opaque_info_per_type *oipt = NULL;
645 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
646
647 switch (lsa->data->type)
648 {
649 case OSPF_OPAQUE_LINK_LSA:
650 if ((oi = lsa->oi) != NULL)
651 listtop = oi->opaque_lsa_self;
652 else
653 zlog_warn ("Type-9 Opaque-LSA: Reference to OI is missing?");
654 break;
655 case OSPF_OPAQUE_AREA_LSA:
656 if ((area = lsa->area) != NULL)
657 listtop = area->opaque_lsa_self;
658 else
659 zlog_warn ("Type-10 Opaque-LSA: Reference to AREA is missing?");
660 break;
661 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +0000662 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000663 if ((area = lsa->area) != NULL && (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +0000664 {
665 zlog_warn ("Type-11 Opaque-LSA: Reference to OSPF is missing?");
666 break; /* Unlikely to happen. */
667 }
668 listtop = top->opaque_lsa_self;
669 break;
670 default:
671 zlog_warn ("lookup_opaque_info_by_type: Unexpected LSA-type(%u)", lsa->data->type);
672 break;
673 }
674
675 if (listtop != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000676 for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt))
paul87d6f872004-09-24 08:01:38 +0000677 if (oipt->opaque_type == key)
678 return oipt;
paul718e3742002-12-13 20:15:29 +0000679
680 return NULL;
681}
682
683static struct opaque_info_per_id *
684register_opaque_info_per_id (struct opaque_info_per_type *oipt,
685 struct ospf_lsa *new)
686{
687 struct opaque_info_per_id *oipi;
688
689 if ((oipi = XCALLOC (MTYPE_OPAQUE_INFO_PER_ID,
690 sizeof (struct opaque_info_per_id))) == NULL)
691 {
ajs6099b3b2004-11-20 02:06:59 +0000692 zlog_warn ("register_opaque_info_per_id: XMALLOC: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000693 goto out;
694 }
695 oipi->opaque_id = GET_OPAQUE_ID (ntohl (new->data->id.s_addr));
696 oipi->t_opaque_lsa_self = NULL;
697 oipi->opqctl_type = oipt;
698 oipi->lsa = ospf_lsa_lock (new);
699
700 listnode_add (oipt->id_list, oipi);
701
702out:
703 return oipi;
704}
705
706static void
707free_opaque_info_per_id (void *val)
708{
709 struct opaque_info_per_id *oipi = (struct opaque_info_per_id *) val;
710
711 OSPF_TIMER_OFF (oipi->t_opaque_lsa_self);
712 if (oipi->lsa != NULL)
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000713 ospf_lsa_unlock (&oipi->lsa);
paul718e3742002-12-13 20:15:29 +0000714 XFREE (MTYPE_OPAQUE_INFO_PER_ID, oipi);
715 return;
716}
717
718static struct opaque_info_per_id *
719lookup_opaque_info_by_id (struct opaque_info_per_type *oipt,
720 struct ospf_lsa *lsa)
721{
paul1eb8ef22005-04-07 07:30:20 +0000722 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000723 struct opaque_info_per_id *oipi;
724 u_int32_t key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
725
paul1eb8ef22005-04-07 07:30:20 +0000726 for (ALL_LIST_ELEMENTS (oipt->id_list, node, nnode, oipi))
paul87d6f872004-09-24 08:01:38 +0000727 if (oipi->opaque_id == key)
728 return oipi;
paul718e3742002-12-13 20:15:29 +0000729
730 return NULL;
731}
732
733static struct opaque_info_per_id *
734register_opaque_lsa (struct ospf_lsa *new)
735{
736 struct ospf_opaque_functab *functab;
737 struct opaque_info_per_type *oipt;
738 struct opaque_info_per_id *oipi = NULL;
739
740 if ((functab = ospf_opaque_functab_lookup (new)) == NULL)
741 goto out;
742
743 if ((oipt = lookup_opaque_info_by_type (new)) == NULL
744 && (oipt = register_opaque_info_per_type (functab, new)) == NULL)
745 goto out;
746
747 if ((oipi = register_opaque_info_per_id (oipt, new)) == NULL)
748 goto out;
749
750out:
751 return oipi;
752}
753
754/*------------------------------------------------------------------------*
755 * Followings are (vty) configuration functions for Opaque-LSAs handling.
756 *------------------------------------------------------------------------*/
757
758DEFUN (capability_opaque,
759 capability_opaque_cmd,
760 "capability opaque",
761 "Enable specific OSPF feature\n"
762 "Opaque LSA\n")
763{
764 struct ospf *ospf = (struct ospf *) vty->index;
765
766 /* Turn on the "master switch" of opaque-lsa capability. */
767 if (!CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
768 {
769 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000770 zlog_debug ("Opaque capability: OFF -> ON");
paul718e3742002-12-13 20:15:29 +0000771
772 SET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
773 ospf_renegotiate_optional_capabilities (ospf);
774 }
775 return CMD_SUCCESS;
776}
777
778ALIAS (capability_opaque,
779 ospf_opaque_capable_cmd,
780 "ospf opaque-lsa",
781 "OSPF specific commands\n"
782 "Enable the Opaque-LSA capability (rfc2370)\n")
783
784DEFUN (no_capability_opaque,
785 no_capability_opaque_cmd,
786 "no capability opaque",
787 NO_STR
788 "Enable specific OSPF feature\n"
789 "Opaque LSA\n")
790{
791 struct ospf *ospf = (struct ospf *) vty->index;
792
793 /* Turn off the "master switch" of opaque-lsa capability. */
794 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
795 {
796 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000797 zlog_debug ("Opaque capability: ON -> OFF");
paul718e3742002-12-13 20:15:29 +0000798
799 UNSET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
800 ospf_renegotiate_optional_capabilities (ospf);
801 }
802 return CMD_SUCCESS;
803}
804
805ALIAS (no_capability_opaque,
806 no_ospf_opaque_capable_cmd,
807 "no ospf opaque-lsa",
808 NO_STR
809 "OSPF specific commands\n"
810 "Disable the Opaque-LSA capability (rfc2370)\n")
811
812static void
813ospf_opaque_register_vty (void)
814{
815 install_element (OSPF_NODE, &capability_opaque_cmd);
816 install_element (OSPF_NODE, &no_capability_opaque_cmd);
817 install_element (OSPF_NODE, &ospf_opaque_capable_cmd);
818 install_element (OSPF_NODE, &no_ospf_opaque_capable_cmd);
819 return;
820}
821
822/*------------------------------------------------------------------------*
823 * Followings are collection of user-registered function callers.
824 *------------------------------------------------------------------------*/
825
826static int
paul87d6f872004-09-24 08:01:38 +0000827opaque_lsa_new_if_callback (struct list *funclist, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000828{
paul1eb8ef22005-04-07 07:30:20 +0000829 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000830 struct ospf_opaque_functab *functab;
831 int rc = -1;
832
paul1eb8ef22005-04-07 07:30:20 +0000833 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000834 if (functab->new_if_hook != NULL)
835 if ((* functab->new_if_hook)(ifp) != 0)
836 goto out;
paul718e3742002-12-13 20:15:29 +0000837 rc = 0;
838out:
839 return rc;
840}
841
842static int
paul87d6f872004-09-24 08:01:38 +0000843opaque_lsa_del_if_callback (struct list *funclist, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000844{
paul1eb8ef22005-04-07 07:30:20 +0000845 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000846 struct ospf_opaque_functab *functab;
847 int rc = -1;
848
paul1eb8ef22005-04-07 07:30:20 +0000849 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000850 if (functab->del_if_hook != NULL)
851 if ((* functab->del_if_hook)(ifp) != 0)
852 goto out;
paul718e3742002-12-13 20:15:29 +0000853 rc = 0;
854out:
855 return rc;
856}
857
858static void
paul87d6f872004-09-24 08:01:38 +0000859opaque_lsa_ism_change_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000860 struct ospf_interface *oi, int old_status)
861{
paul1eb8ef22005-04-07 07:30:20 +0000862 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000863 struct ospf_opaque_functab *functab;
864
paul1eb8ef22005-04-07 07:30:20 +0000865 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000866 if (functab->ism_change_hook != NULL)
867 (* functab->ism_change_hook)(oi, old_status);
868
paul718e3742002-12-13 20:15:29 +0000869 return;
870}
871
872static void
paul87d6f872004-09-24 08:01:38 +0000873opaque_lsa_nsm_change_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000874 struct ospf_neighbor *nbr, int old_status)
875{
paul1eb8ef22005-04-07 07:30:20 +0000876 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000877 struct ospf_opaque_functab *functab;
878
paul1eb8ef22005-04-07 07:30:20 +0000879 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000880 if (functab->nsm_change_hook != NULL)
881 (* functab->nsm_change_hook)(nbr, old_status);
paul718e3742002-12-13 20:15:29 +0000882 return;
883}
884
885static void
paul87d6f872004-09-24 08:01:38 +0000886opaque_lsa_config_write_router_callback (struct list *funclist,
887 struct vty *vty)
paul718e3742002-12-13 20:15:29 +0000888{
paul1eb8ef22005-04-07 07:30:20 +0000889 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000890 struct ospf_opaque_functab *functab;
891
paul1eb8ef22005-04-07 07:30:20 +0000892 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000893 if (functab->config_write_router != NULL)
894 (* functab->config_write_router)(vty);
paul718e3742002-12-13 20:15:29 +0000895 return;
896}
897
898static void
paul87d6f872004-09-24 08:01:38 +0000899opaque_lsa_config_write_if_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000900 struct vty *vty, struct interface *ifp)
901{
paul1eb8ef22005-04-07 07:30:20 +0000902 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000903 struct ospf_opaque_functab *functab;
904
paul1eb8ef22005-04-07 07:30:20 +0000905 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000906 if (functab->config_write_if != NULL)
907 (* functab->config_write_if)(vty, ifp);
paul718e3742002-12-13 20:15:29 +0000908 return;
909}
910
911static void
paul87d6f872004-09-24 08:01:38 +0000912opaque_lsa_config_write_debug_callback (struct list *funclist, struct vty *vty)
paul718e3742002-12-13 20:15:29 +0000913{
paul1eb8ef22005-04-07 07:30:20 +0000914 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000915 struct ospf_opaque_functab *functab;
916
paul1eb8ef22005-04-07 07:30:20 +0000917 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000918 if (functab->config_write_debug != NULL)
919 (* functab->config_write_debug)(vty);
paul718e3742002-12-13 20:15:29 +0000920 return;
921}
922
923static int
paul87d6f872004-09-24 08:01:38 +0000924opaque_lsa_originate_callback (struct list *funclist, void *lsa_type_dependent)
paul718e3742002-12-13 20:15:29 +0000925{
paul1eb8ef22005-04-07 07:30:20 +0000926 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000927 struct ospf_opaque_functab *functab;
928 int rc = -1;
929
paul1eb8ef22005-04-07 07:30:20 +0000930 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000931 if (functab->lsa_originator != NULL)
932 if ((* functab->lsa_originator)(lsa_type_dependent) != 0)
933 goto out;
paul718e3742002-12-13 20:15:29 +0000934 rc = 0;
935out:
936 return rc;
937}
938
939static int
paul87d6f872004-09-24 08:01:38 +0000940new_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000941{
paul1eb8ef22005-04-07 07:30:20 +0000942 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000943 struct ospf_opaque_functab *functab;
944 int rc = -1;
945
946 /* This function handles ALL types of LSAs, not only opaque ones. */
paul1eb8ef22005-04-07 07:30:20 +0000947 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000948 if (functab->new_lsa_hook != NULL)
949 if ((* functab->new_lsa_hook)(lsa) != 0)
950 goto out;
paul718e3742002-12-13 20:15:29 +0000951 rc = 0;
952out:
953 return rc;
954}
955
956static int
paul87d6f872004-09-24 08:01:38 +0000957del_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000958{
paul1eb8ef22005-04-07 07:30:20 +0000959 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000960 struct ospf_opaque_functab *functab;
961 int rc = -1;
962
963 /* This function handles ALL types of LSAs, not only opaque ones. */
paul1eb8ef22005-04-07 07:30:20 +0000964 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000965 if (functab->del_lsa_hook != NULL)
966 if ((* functab->del_lsa_hook)(lsa) != 0)
967 goto out;
paul718e3742002-12-13 20:15:29 +0000968 rc = 0;
969out:
970 return rc;
971}
972
973/*------------------------------------------------------------------------*
974 * Followings are glue functions to call Opaque-LSA specific processing.
975 *------------------------------------------------------------------------*/
976
977int
978ospf_opaque_new_if (struct interface *ifp)
979{
paul87d6f872004-09-24 08:01:38 +0000980 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000981 int rc = -1;
982
paul09e4efd2003-01-18 00:12:02 +0000983 funclist = ospf_opaque_wildcard_funclist;
984 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
985 goto out;
986
paul718e3742002-12-13 20:15:29 +0000987 funclist = ospf_opaque_type9_funclist;
988 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
989 goto out;
990
991 funclist = ospf_opaque_type10_funclist;
992 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
993 goto out;
994
995 funclist = ospf_opaque_type11_funclist;
996 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
997 goto out;
998
999 rc = 0;
1000out:
1001 return rc;
1002}
1003
1004int
1005ospf_opaque_del_if (struct interface *ifp)
1006{
paul87d6f872004-09-24 08:01:38 +00001007 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001008 int rc = -1;
1009
paul09e4efd2003-01-18 00:12:02 +00001010 funclist = ospf_opaque_wildcard_funclist;
1011 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1012 goto out;
1013
paul718e3742002-12-13 20:15:29 +00001014 funclist = ospf_opaque_type9_funclist;
1015 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1016 goto out;
1017
1018 funclist = ospf_opaque_type10_funclist;
1019 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1020 goto out;
1021
1022 funclist = ospf_opaque_type11_funclist;
1023 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1024 goto out;
1025
1026 rc = 0;
1027out:
1028 return rc;
1029}
1030
1031void
1032ospf_opaque_ism_change (struct ospf_interface *oi, int old_status)
1033{
paul87d6f872004-09-24 08:01:38 +00001034 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001035
paul09e4efd2003-01-18 00:12:02 +00001036 funclist = ospf_opaque_wildcard_funclist;
1037 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1038
paul718e3742002-12-13 20:15:29 +00001039 funclist = ospf_opaque_type9_funclist;
1040 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1041
1042 funclist = ospf_opaque_type10_funclist;
1043 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1044
1045 funclist = ospf_opaque_type11_funclist;
1046 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1047
1048 return;
1049}
1050
1051void
1052ospf_opaque_nsm_change (struct ospf_neighbor *nbr, int old_state)
1053{
1054 struct ospf *top;
paul87d6f872004-09-24 08:01:38 +00001055 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001056
1057 if ((top = oi_to_top (nbr->oi)) == NULL)
1058 goto out;
1059
1060 if (old_state != NSM_Full && nbr->state == NSM_Full)
1061 {
1062 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
1063 {
1064 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1065 {
1066 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001067 zlog_debug ("Opaque-LSA: Now get operational!");
paul718e3742002-12-13 20:15:29 +00001068
1069 SET_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT);
1070 }
1071
1072 ospf_opaque_lsa_originate_schedule (nbr->oi, NULL);
1073 }
1074 }
1075 else
1076 if (old_state == NSM_Full && nbr->state != NSM_Full)
1077 {
1078#ifdef NOTYET
1079 /*
1080 * If no more opaque-capable full-state neighbor remains in the
1081 * flooding scope which corresponds to Opaque-LSA type, periodic
1082 * LS flooding should be stopped.
1083 */
1084#endif /* NOTYET */
1085 ;
1086 }
1087
paul09e4efd2003-01-18 00:12:02 +00001088 funclist = ospf_opaque_wildcard_funclist;
1089 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1090
paul718e3742002-12-13 20:15:29 +00001091 funclist = ospf_opaque_type9_funclist;
1092 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1093
1094 funclist = ospf_opaque_type10_funclist;
1095 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1096
1097 funclist = ospf_opaque_type11_funclist;
1098 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1099
1100out:
1101 return;
1102}
1103
1104void
1105ospf_opaque_config_write_router (struct vty *vty, struct ospf *ospf)
1106{
paul87d6f872004-09-24 08:01:38 +00001107 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001108
1109 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
1110 vty_out (vty, " capability opaque%s", VTY_NEWLINE);
1111
paul09e4efd2003-01-18 00:12:02 +00001112 funclist = ospf_opaque_wildcard_funclist;
1113 opaque_lsa_config_write_router_callback (funclist, vty);
1114
paul718e3742002-12-13 20:15:29 +00001115 funclist = ospf_opaque_type9_funclist;
1116 opaque_lsa_config_write_router_callback (funclist, vty);
1117
1118 funclist = ospf_opaque_type10_funclist;
1119 opaque_lsa_config_write_router_callback (funclist, vty);
1120
1121 funclist = ospf_opaque_type11_funclist;
1122 opaque_lsa_config_write_router_callback (funclist, vty);
1123
1124 return;
1125}
1126
1127void
1128ospf_opaque_config_write_if (struct vty *vty, struct interface *ifp)
1129{
paul87d6f872004-09-24 08:01:38 +00001130 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001131
paul09e4efd2003-01-18 00:12:02 +00001132 funclist = ospf_opaque_wildcard_funclist;
1133 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1134
paul718e3742002-12-13 20:15:29 +00001135 funclist = ospf_opaque_type9_funclist;
1136 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1137
1138 funclist = ospf_opaque_type10_funclist;
1139 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1140
1141 funclist = ospf_opaque_type11_funclist;
1142 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1143
1144 return;
1145}
1146
1147void
1148ospf_opaque_config_write_debug (struct vty *vty)
1149{
paul87d6f872004-09-24 08:01:38 +00001150 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001151
paul09e4efd2003-01-18 00:12:02 +00001152 funclist = ospf_opaque_wildcard_funclist;
1153 opaque_lsa_config_write_debug_callback (funclist, vty);
1154
paul718e3742002-12-13 20:15:29 +00001155 funclist = ospf_opaque_type9_funclist;
1156 opaque_lsa_config_write_debug_callback (funclist, vty);
1157
1158 funclist = ospf_opaque_type10_funclist;
1159 opaque_lsa_config_write_debug_callback (funclist, vty);
1160
1161 funclist = ospf_opaque_type11_funclist;
1162 opaque_lsa_config_write_debug_callback (funclist, vty);
1163
1164 return;
1165}
1166
1167void
1168show_opaque_info_detail (struct vty *vty, struct ospf_lsa *lsa)
1169{
1170 struct lsa_header *lsah = (struct lsa_header *) lsa->data;
1171 u_int32_t lsid = ntohl (lsah->id.s_addr);
1172 u_char opaque_type = GET_OPAQUE_TYPE (lsid);
1173 u_int32_t opaque_id = GET_OPAQUE_ID (lsid);
1174 struct ospf_opaque_functab *functab;
1175
1176 /* Switch output functionality by vty address. */
1177 if (vty != NULL)
1178 {
paul020709f2003-04-04 02:44:16 +00001179 vty_out (vty, " Opaque-Type %u (%s)%s", opaque_type,
1180 ospf_opaque_type_name (opaque_type), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001181 vty_out (vty, " Opaque-ID 0x%x%s", opaque_id, VTY_NEWLINE);
1182
1183 vty_out (vty, " Opaque-Info: %u octets of data%s%s",
1184 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1185 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)",
1186 VTY_NEWLINE);
1187 }
1188 else
1189 {
ajs2a42e282004-12-08 18:43:03 +00001190 zlog_debug (" Opaque-Type %u (%s)", opaque_type,
paul020709f2003-04-04 02:44:16 +00001191 ospf_opaque_type_name (opaque_type));
ajs2a42e282004-12-08 18:43:03 +00001192 zlog_debug (" Opaque-ID 0x%x", opaque_id);
paul718e3742002-12-13 20:15:29 +00001193
ajs2a42e282004-12-08 18:43:03 +00001194 zlog_debug (" Opaque-Info: %u octets of data%s",
paul718e3742002-12-13 20:15:29 +00001195 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1196 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)");
1197 }
1198
1199 /* Call individual output functions. */
1200 if ((functab = ospf_opaque_functab_lookup (lsa)) != NULL)
1201 if (functab->show_opaque_info != NULL)
1202 (* functab->show_opaque_info)(vty, lsa);
1203
1204 return;
1205}
1206
1207void
1208ospf_opaque_lsa_dump (struct stream *s, u_int16_t length)
1209{
1210 struct ospf_lsa lsa;
1211
1212 lsa.data = (struct lsa_header *) STREAM_PNT (s);
1213 show_opaque_info_detail (NULL, &lsa);
1214 return;
1215}
1216
1217static int
1218ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa)
1219{
paul87d6f872004-09-24 08:01:38 +00001220 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001221 int rc = -1;
1222
1223 /*
1224 * Some Opaque-LSA user may want to monitor every LSA installation
1225 * into the LSDB, regardless with target LSA type.
1226 */
paul09e4efd2003-01-18 00:12:02 +00001227 funclist = ospf_opaque_wildcard_funclist;
1228 if (new_lsa_callback (funclist, lsa) != 0)
1229 goto out;
1230
paul718e3742002-12-13 20:15:29 +00001231 funclist = ospf_opaque_type9_funclist;
1232 if (new_lsa_callback (funclist, lsa) != 0)
1233 goto out;
1234
1235 funclist = ospf_opaque_type10_funclist;
1236 if (new_lsa_callback (funclist, lsa) != 0)
1237 goto out;
1238
1239 funclist = ospf_opaque_type11_funclist;
1240 if (new_lsa_callback (funclist, lsa) != 0)
1241 goto out;
1242
1243 rc = 0;
1244out:
1245 return rc;
1246}
1247
1248static int
1249ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa)
1250{
paul87d6f872004-09-24 08:01:38 +00001251 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001252 int rc = -1;
1253
1254 /*
1255 * Some Opaque-LSA user may want to monitor every LSA deletion
1256 * from the LSDB, regardless with target LSA type.
1257 */
paul09e4efd2003-01-18 00:12:02 +00001258 funclist = ospf_opaque_wildcard_funclist;
1259 if (del_lsa_callback (funclist, lsa) != 0)
1260 goto out;
1261
paul718e3742002-12-13 20:15:29 +00001262 funclist = ospf_opaque_type9_funclist;
1263 if (del_lsa_callback (funclist, lsa) != 0)
1264 goto out;
1265
1266 funclist = ospf_opaque_type10_funclist;
1267 if (del_lsa_callback (funclist, lsa) != 0)
1268 goto out;
1269
1270 funclist = ospf_opaque_type11_funclist;
1271 if (del_lsa_callback (funclist, lsa) != 0)
1272 goto out;
1273
1274 rc = 0;
1275out:
1276 return rc;
1277}
1278
1279/*------------------------------------------------------------------------*
1280 * Followings are Opaque-LSA origination/refresh management functions.
1281 *------------------------------------------------------------------------*/
1282
1283static int ospf_opaque_type9_lsa_originate (struct thread *t);
1284static int ospf_opaque_type10_lsa_originate (struct thread *t);
1285static int ospf_opaque_type11_lsa_originate (struct thread *t);
paul87d6f872004-09-24 08:01:38 +00001286static void ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg);
paul718e3742002-12-13 20:15:29 +00001287
1288void
1289ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0)
1290{
1291 struct ospf *top;
1292 struct ospf_area *area;
paul1eb8ef22005-04-07 07:30:20 +00001293 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001294 struct opaque_info_per_type *oipt;
1295 int delay = 0;
1296
1297 if ((top = oi_to_top (oi)) == NULL || (area = oi->area) == NULL)
1298 {
1299 zlog_warn ("ospf_opaque_lsa_originate_schedule: Invalid argument?");
1300 goto out;
1301 }
1302
1303 /* It may not a right time to schedule origination now. */
1304 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1305 {
1306 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001307 zlog_debug ("ospf_opaque_lsa_originate_schedule: Not operational.");
paul718e3742002-12-13 20:15:29 +00001308 goto out; /* This is not an error. */
1309 }
Paul Jakmae30677a2015-01-20 15:45:36 +00001310
paul718e3742002-12-13 20:15:29 +00001311 if (delay0 != NULL)
1312 delay = *delay0;
1313
1314 /*
1315 * There might be some entries that have been waiting for triggering
1316 * of per opaque-type re-origination get resumed.
1317 */
1318 ospf_opaque_lsa_reoriginate_resume ( oi->opaque_lsa_self, (void *) oi);
1319 ospf_opaque_lsa_reoriginate_resume (area->opaque_lsa_self, (void *) area);
1320 ospf_opaque_lsa_reoriginate_resume ( top->opaque_lsa_self, (void *) top);
1321
1322 /*
1323 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1324 */
1325 if (! list_isempty (ospf_opaque_type9_funclist)
1326 && list_isempty (oi->opaque_lsa_self)
1327 && oi->t_opaque_lsa_self == NULL)
1328 {
1329 if (IS_DEBUG_OSPF_EVENT)
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001330 zlog_debug ("Schedule Type-9 Opaque-LSA origination in %d ms later.", delay);
paul718e3742002-12-13 20:15:29 +00001331 oi->t_opaque_lsa_self =
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001332 thread_add_timer_msec (master, ospf_opaque_type9_lsa_originate, oi, delay);
1333 delay += top->min_ls_interval;
paul718e3742002-12-13 20:15:29 +00001334 }
1335
1336 if (! list_isempty (ospf_opaque_type10_funclist)
1337 && list_isempty (area->opaque_lsa_self)
1338 && area->t_opaque_lsa_self == NULL)
1339 {
1340 /*
1341 * One AREA may contain multiple OIs, but above 2nd and 3rd
1342 * conditions prevent from scheduling the originate function
1343 * again and again.
1344 */
1345 if (IS_DEBUG_OSPF_EVENT)
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001346 zlog_debug ("Schedule Type-10 Opaque-LSA origination in %d ms later.", delay);
paul718e3742002-12-13 20:15:29 +00001347 area->t_opaque_lsa_self =
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001348 thread_add_timer_msec (master, ospf_opaque_type10_lsa_originate,
paul718e3742002-12-13 20:15:29 +00001349 area, delay);
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001350 delay += top->min_ls_interval;
paul718e3742002-12-13 20:15:29 +00001351 }
1352
1353 if (! list_isempty (ospf_opaque_type11_funclist)
1354 && list_isempty (top->opaque_lsa_self)
1355 && top->t_opaque_lsa_self == NULL)
1356 {
1357 /*
1358 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1359 * conditions prevent from scheduling the originate function
1360 * again and again.
1361 */
1362 if (IS_DEBUG_OSPF_EVENT)
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001363 zlog_debug ("Schedule Type-11 Opaque-LSA origination in %d ms later.", delay);
paul718e3742002-12-13 20:15:29 +00001364 top->t_opaque_lsa_self =
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001365 thread_add_timer_msec (master, ospf_opaque_type11_lsa_originate,
paul718e3742002-12-13 20:15:29 +00001366 top, delay);
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001367 delay += top->min_ls_interval;
paul718e3742002-12-13 20:15:29 +00001368 }
1369
1370 /*
1371 * Following section treats a special situation that this node's
1372 * opaque capability has changed as "ON -> OFF -> ON".
1373 */
1374 if (! list_isempty (ospf_opaque_type9_funclist)
1375 && ! list_isempty (oi->opaque_lsa_self))
1376 {
paul1eb8ef22005-04-07 07:30:20 +00001377 for (ALL_LIST_ELEMENTS (oi->opaque_lsa_self, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001378 {
hasso0d85b992004-03-18 19:18:33 +00001379 /*
1380 * removed the test for
1381 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1382 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1383 * not being empty.
1384 */
paul1eb8ef22005-04-07 07:30:20 +00001385 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1386 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001387 continue;
1388
1389 ospf_opaque_lsa_reoriginate_schedule ((void *) oi,
1390 OSPF_OPAQUE_LINK_LSA, oipt->opaque_type);
1391 }
1392 }
1393
1394 if (! list_isempty (ospf_opaque_type10_funclist)
1395 && ! list_isempty (area->opaque_lsa_self))
1396 {
paul1eb8ef22005-04-07 07:30:20 +00001397 for (ALL_LIST_ELEMENTS (area->opaque_lsa_self, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001398 {
hasso0d85b992004-03-18 19:18:33 +00001399 /*
1400 * removed the test for
1401 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1402 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1403 * not being empty.
1404 */
paul1eb8ef22005-04-07 07:30:20 +00001405 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1406 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001407 continue;
1408
1409 ospf_opaque_lsa_reoriginate_schedule ((void *) area,
1410 OSPF_OPAQUE_AREA_LSA, oipt->opaque_type);
1411 }
1412 }
1413
1414 if (! list_isempty (ospf_opaque_type11_funclist)
1415 && ! list_isempty (top->opaque_lsa_self))
1416 {
paul1eb8ef22005-04-07 07:30:20 +00001417 for (ALL_LIST_ELEMENTS (top->opaque_lsa_self, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001418 {
hasso0d85b992004-03-18 19:18:33 +00001419 /*
1420 * removed the test for
1421 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1422 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1423 * not being empty.
1424 */
paul1eb8ef22005-04-07 07:30:20 +00001425 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1426 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001427 continue;
1428
1429 ospf_opaque_lsa_reoriginate_schedule ((void *) top,
1430 OSPF_OPAQUE_AS_LSA, oipt->opaque_type);
1431 }
1432 }
1433
1434 if (delay0 != NULL)
1435 *delay0 = delay;
1436
1437out:
1438 return;
1439}
1440
1441static int
1442ospf_opaque_type9_lsa_originate (struct thread *t)
1443{
1444 struct ospf_interface *oi;
1445 int rc;
1446
1447 oi = THREAD_ARG (t);
1448 oi->t_opaque_lsa_self = NULL;
1449
1450 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001451 zlog_debug ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
paul718e3742002-12-13 20:15:29 +00001452 IF_NAME (oi));
1453
1454 rc = opaque_lsa_originate_callback (ospf_opaque_type9_funclist, oi);
1455
1456 return rc;
1457}
1458
1459static int
1460ospf_opaque_type10_lsa_originate (struct thread *t)
1461{
1462 struct ospf_area *area;
1463 int rc;
1464
1465 area = THREAD_ARG (t);
1466 area->t_opaque_lsa_self = NULL;
1467
1468 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001469 zlog_debug ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
paul718e3742002-12-13 20:15:29 +00001470 inet_ntoa (area->area_id));
1471
1472 rc = opaque_lsa_originate_callback (ospf_opaque_type10_funclist, area);
1473
1474 return rc;
1475}
1476
1477static int
1478ospf_opaque_type11_lsa_originate (struct thread *t)
1479{
1480 struct ospf *top;
1481 int rc;
1482
1483 top = THREAD_ARG (t);
1484 top->t_opaque_lsa_self = NULL;
1485
1486 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001487 zlog_debug ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
paul718e3742002-12-13 20:15:29 +00001488
1489 rc = opaque_lsa_originate_callback (ospf_opaque_type11_funclist, top);
1490
1491 return rc;
1492}
1493
1494static void
paul87d6f872004-09-24 08:01:38 +00001495ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg)
paul718e3742002-12-13 20:15:29 +00001496{
paul1eb8ef22005-04-07 07:30:20 +00001497 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001498 struct opaque_info_per_type *oipt;
1499 struct ospf_opaque_functab *functab;
1500
1501 if (listtop == NULL)
1502 goto out;
1503
1504 /*
1505 * Pickup oipt entries those which in SUSPEND status, and give
1506 * them a chance to start re-origination now.
1507 */
paul1eb8ef22005-04-07 07:30:20 +00001508 for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001509 {
paul87d6f872004-09-24 08:01:38 +00001510 if (oipt->status != PROC_SUSPEND)
paul718e3742002-12-13 20:15:29 +00001511 continue;
1512
1513 oipt->status = PROC_NORMAL;
1514
1515 if ((functab = oipt->functab) == NULL
paul87d6f872004-09-24 08:01:38 +00001516 || functab->lsa_originator == NULL)
paul718e3742002-12-13 20:15:29 +00001517 continue;
1518
1519 if ((* functab->lsa_originator)(arg) != 0)
1520 {
1521 zlog_warn ("ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", oipt->opaque_type);
1522 continue;
1523 }
1524 }
1525
1526out:
1527 return;
1528}
1529
1530struct ospf_lsa *
1531ospf_opaque_lsa_install (struct ospf_lsa *lsa, int rt_recalc)
1532{
1533 struct ospf_lsa *new = NULL;
1534 struct opaque_info_per_type *oipt;
1535 struct opaque_info_per_id *oipi;
1536 struct ospf *top;
1537
1538 /* Don't take "rt_recalc" into consideration for now. *//* XXX */
1539
1540 if (! IS_LSA_SELF (lsa))
1541 {
1542 new = lsa; /* Don't touch this LSA. */
1543 goto out;
1544 }
1545
1546 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
ajs2a42e282004-12-08 18:43:03 +00001547 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 +00001548
1549 /* Replace the existing lsa with the new one. */
1550 if ((oipt = lookup_opaque_info_by_type (lsa)) != NULL
paul87d6f872004-09-24 08:01:38 +00001551 && (oipi = lookup_opaque_info_by_id (oipt, lsa)) != NULL)
paul718e3742002-12-13 20:15:29 +00001552 {
Paul Jakma1fe6ed32006-07-26 09:37:26 +00001553 ospf_lsa_unlock (&oipi->lsa);
paul718e3742002-12-13 20:15:29 +00001554 oipi->lsa = ospf_lsa_lock (lsa);
1555 }
1556 /* Register the new lsa entry and get its control info. */
1557 else
1558 if ((oipi = register_opaque_lsa (lsa)) == NULL)
1559 {
1560 zlog_warn ("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1561 goto out;
1562 }
1563
1564 /*
1565 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1566 * for periodic refresh of self-originated Opaque-LSAs.
1567 */
1568 switch (lsa->data->type)
1569 {
1570 case OSPF_OPAQUE_LINK_LSA:
paul09e4efd2003-01-18 00:12:02 +00001571 if ((top = oi_to_top (lsa->oi)) == NULL)
1572 {
1573 /* Above conditions must have passed. */
1574 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1575 goto out;
1576 }
1577 break;
paul718e3742002-12-13 20:15:29 +00001578 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00001579 if (lsa->area == NULL || (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001580 {
1581 /* Above conditions must have passed. */
1582 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1583 goto out;
1584 }
1585 break;
1586 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +00001587 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001588 if (lsa->area != NULL && (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001589 {
1590 /* Above conditions must have passed. */
1591 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1592 goto out;
1593 }
1594 break;
1595 default:
1596 zlog_warn ("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", lsa->data->type);
1597 goto out;
1598 }
1599
1600 ospf_refresher_register_lsa (top, lsa);
1601 new = lsa;
1602
1603out:
1604 return new;
1605}
1606
Paul Jakmad71ea652011-03-22 15:23:55 +00001607struct ospf_lsa *
paul718e3742002-12-13 20:15:29 +00001608ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
1609{
paul020709f2003-04-04 02:44:16 +00001610 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001611 struct ospf_opaque_functab *functab;
Paul Jakmad71ea652011-03-22 15:23:55 +00001612 struct ospf_lsa *new = NULL;
1613
paul020709f2003-04-04 02:44:16 +00001614 ospf = ospf_lookup ();
1615
paul718e3742002-12-13 20:15:29 +00001616 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL
paul87d6f872004-09-24 08:01:38 +00001617 || functab->lsa_refresher == NULL)
paul718e3742002-12-13 20:15:29 +00001618 {
1619 /*
1620 * Though this LSA seems to have originated on this node, the
1621 * handling module for this "lsa-type and opaque-type" was
1622 * already deleted sometime ago.
1623 * Anyway, this node still has a responsibility to flush this
1624 * LSA from the routing domain.
1625 */
1626 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001627 zlog_debug ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id));
paul718e3742002-12-13 20:15:29 +00001628
1629 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
Paul Jakma02d942c2010-01-24 23:36:20 +00001630 ospf_lsa_flush (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00001631 }
1632 else
Paul Jakmad71ea652011-03-22 15:23:55 +00001633 new = (* functab->lsa_refresher)(lsa);
paul718e3742002-12-13 20:15:29 +00001634
Paul Jakmad71ea652011-03-22 15:23:55 +00001635 return new;
paul718e3742002-12-13 20:15:29 +00001636}
1637
1638/*------------------------------------------------------------------------*
1639 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1640 * triggered by external interventions (vty session, signaling, etc).
1641 *------------------------------------------------------------------------*/
1642
1643#define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
1644 if (!(T)) \
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001645 (T) = thread_add_timer_msec (master, (F), (L), (V))
paul718e3742002-12-13 20:15:29 +00001646
1647static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type);
1648static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t);
1649static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t);
1650static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t);
1651static int ospf_opaque_lsa_refresh_timer (struct thread *t);
1652
1653void
1654ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
1655 u_char lsa_type, u_char opaque_type)
1656{
1657 struct ospf *top;
1658 struct ospf_area dummy, *area = NULL;
1659 struct ospf_interface *oi = NULL;
1660
1661 struct ospf_lsa *lsa;
1662 struct opaque_info_per_type *oipt;
paul87d6f872004-09-24 08:01:38 +00001663 int (*func) (struct thread * t) = NULL;
paul718e3742002-12-13 20:15:29 +00001664 int delay;
1665
1666 switch (lsa_type)
1667 {
1668 case OSPF_OPAQUE_LINK_LSA:
1669 if ((oi = (struct ospf_interface *) lsa_type_dependent) == NULL)
1670 {
paul87d6f872004-09-24 08:01:38 +00001671 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1672 " Type-9 Opaque-LSA: Invalid parameter?");
1673 goto out;
paul718e3742002-12-13 20:15:29 +00001674 }
1675 if ((top = oi_to_top (oi)) == NULL)
1676 {
paul87d6f872004-09-24 08:01:38 +00001677 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1678 IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001679 goto out;
1680 }
paul87d6f872004-09-24 08:01:38 +00001681 if (!list_isempty (ospf_opaque_type9_funclist)
1682 && list_isempty (oi->opaque_lsa_self)
1683 && oi->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001684 {
paul87d6f872004-09-24 08:01:38 +00001685 zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u):"
1686 " Common origination for OI(%s) has already started",
1687 opaque_type, IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001688 goto out;
1689 }
1690 func = ospf_opaque_type9_lsa_reoriginate_timer;
1691 break;
1692 case OSPF_OPAQUE_AREA_LSA:
1693 if ((area = (struct ospf_area *) lsa_type_dependent) == NULL)
1694 {
paul87d6f872004-09-24 08:01:38 +00001695 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1696 " Type-10 Opaque-LSA: Invalid parameter?");
paul718e3742002-12-13 20:15:29 +00001697 goto out;
1698 }
paul68980082003-03-25 05:07:42 +00001699 if ((top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001700 {
paul87d6f872004-09-24 08:01:38 +00001701 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1702 " AREA(%s) -> TOP?", inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001703 goto out;
1704 }
paul87d6f872004-09-24 08:01:38 +00001705 if (!list_isempty (ospf_opaque_type10_funclist)
1706 && list_isempty (area->opaque_lsa_self)
1707 && area->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001708 {
paul87d6f872004-09-24 08:01:38 +00001709 zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u):"
1710 " Common origination for AREA(%s) has already started",
1711 opaque_type, inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001712 goto out;
1713 }
1714 func = ospf_opaque_type10_lsa_reoriginate_timer;
1715 break;
1716 case OSPF_OPAQUE_AS_LSA:
1717 if ((top = (struct ospf *) lsa_type_dependent) == NULL)
1718 {
paul87d6f872004-09-24 08:01:38 +00001719 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1720 " Type-11 Opaque-LSA: Invalid parameter?");
1721 goto out;
paul718e3742002-12-13 20:15:29 +00001722 }
paul87d6f872004-09-24 08:01:38 +00001723 if (!list_isempty (ospf_opaque_type11_funclist)
1724 && list_isempty (top->opaque_lsa_self)
1725 && top->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001726 {
paul87d6f872004-09-24 08:01:38 +00001727 zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u):"
1728 " Common origination has already started", opaque_type);
paul718e3742002-12-13 20:15:29 +00001729 goto out;
1730 }
1731
1732 /* Fake "area" to pass "ospf" to a lookup function later. */
paul68980082003-03-25 05:07:42 +00001733 dummy.ospf = top;
paul718e3742002-12-13 20:15:29 +00001734 area = &dummy;
1735
1736 func = ospf_opaque_type11_lsa_reoriginate_timer;
1737 break;
1738 default:
paul87d6f872004-09-24 08:01:38 +00001739 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1740 " Unexpected LSA-type(%u)",
1741 lsa_type);
paul718e3742002-12-13 20:15:29 +00001742 goto out;
1743 }
1744
1745 /* It may not a right time to schedule reorigination now. */
paul87d6f872004-09-24 08:01:38 +00001746 if (!CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
paul718e3742002-12-13 20:15:29 +00001747 {
1748 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001749 zlog_debug ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
paul87d6f872004-09-24 08:01:38 +00001750 goto out; /* This is not an error. */
paul718e3742002-12-13 20:15:29 +00001751 }
Paul Jakmae30677a2015-01-20 15:45:36 +00001752
paul718e3742002-12-13 20:15:29 +00001753 /* Generate a dummy lsa to be passed for a lookup function. */
1754 lsa = pseudo_lsa (oi, area, lsa_type, opaque_type);
1755
1756 if ((oipt = lookup_opaque_info_by_type (lsa)) == NULL)
1757 {
1758 struct ospf_opaque_functab *functab;
1759 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL)
1760 {
paul87d6f872004-09-24 08:01:38 +00001761 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1762 " No associated function?: lsa_type(%u),"
1763 " opaque_type(%u)",
1764 lsa_type, opaque_type);
paul718e3742002-12-13 20:15:29 +00001765 goto out;
1766 }
1767 if ((oipt = register_opaque_info_per_type (functab, lsa)) == NULL)
1768 {
paul87d6f872004-09-24 08:01:38 +00001769 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1770 " Cannot get a control info?: lsa_type(%u),"
1771 " opaque_type(%u)",
1772 lsa_type, opaque_type);
paul718e3742002-12-13 20:15:29 +00001773 goto out;
1774 }
1775 }
1776
1777 if (oipt->t_opaque_lsa_self != NULL)
1778 {
1779 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001780 zlog_debug ("Type-%u Opaque-LSA has already scheduled to"
paul87d6f872004-09-24 08:01:38 +00001781 " RE-ORIGINATE: [opaque-type=%u]",
1782 lsa_type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
paul718e3742002-12-13 20:15:29 +00001783 goto out;
1784 }
1785
1786 /*
1787 * Different from initial origination time, in which various conditions
1788 * (opaque capability, neighbor status etc) are assured by caller of
1789 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1790 * it is highly possible that these conditions might not be satisfied
1791 * at the time of re-origination function is to be called.
1792 */
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001793 delay = top->min_ls_interval; /* XXX */
paul718e3742002-12-13 20:15:29 +00001794
1795 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001796 zlog_debug ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001797 " ms later: [opaque-type=%u]",
paul87d6f872004-09-24 08:01:38 +00001798 lsa_type, delay,
1799 GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
paul718e3742002-12-13 20:15:29 +00001800
1801 OSPF_OPAQUE_TIMER_ON (oipt->t_opaque_lsa_self, func, oipt, delay);
1802
1803out:
1804 return;
1805}
1806
1807static struct ospf_lsa *
1808pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area,
1809 u_char lsa_type, u_char opaque_type)
1810{
1811 static struct ospf_lsa lsa = { 0 };
1812 static struct lsa_header lsah = { 0 };
1813 u_int32_t tmp;
1814
1815 lsa.oi = oi;
1816 lsa.area = area;
1817 lsa.data = &lsah;
1818
1819 lsah.type = lsa_type;
1820 tmp = SET_OPAQUE_LSID (opaque_type, 0); /* Opaque-ID is unused here. */
1821 lsah.id.s_addr = htonl (tmp);
1822
1823 return &lsa;
1824}
1825
1826static int
1827ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t)
1828{
1829 struct opaque_info_per_type *oipt;
1830 struct ospf_opaque_functab *functab;
1831 struct ospf *top;
1832 struct ospf_interface *oi;
1833 int rc = -1;
1834
1835 oipt = THREAD_ARG (t);
1836 oipt->t_opaque_lsa_self = NULL;
1837
1838 if ((functab = oipt->functab) == NULL
1839 || functab->lsa_originator == NULL)
1840 {
1841 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1842 goto out;
1843 }
1844
1845 oi = (struct ospf_interface *) oipt->owner;
1846 if ((top = oi_to_top (oi)) == NULL)
1847 {
1848 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1849 goto out;
1850 }
1851
1852 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)
1853 || ! ospf_if_is_enable (oi)
paul68980082003-03-25 05:07:42 +00001854 || ospf_nbr_count_opaque_capable (oi) == 0)
paul718e3742002-12-13 20:15:29 +00001855 {
1856 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001857 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 +00001858
1859 oipt->status = PROC_SUSPEND;
1860 rc = 0;
1861 goto out;
1862 }
1863
1864 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001865 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 +00001866
1867 rc = (* functab->lsa_originator)(oi);
1868out:
1869 return rc;
1870}
1871
1872static int
1873ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t)
1874{
1875 struct opaque_info_per_type *oipt;
1876 struct ospf_opaque_functab *functab;
paul1eb8ef22005-04-07 07:30:20 +00001877 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001878 struct ospf *top;
1879 struct ospf_area *area;
1880 struct ospf_interface *oi;
1881 int n, rc = -1;
1882
1883 oipt = THREAD_ARG (t);
1884 oipt->t_opaque_lsa_self = NULL;
1885
1886 if ((functab = oipt->functab) == NULL
1887 || functab->lsa_originator == NULL)
1888 {
1889 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1890 goto out;
1891 }
1892
1893 area = (struct ospf_area *) oipt->owner;
paul68980082003-03-25 05:07:42 +00001894 if (area == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001895 {
1896 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1897 goto out;
1898 }
1899
1900 /* There must be at least one "opaque-capable, full-state" neighbor. */
1901 n = 0;
paul1eb8ef22005-04-07 07:30:20 +00001902 for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi))
paul718e3742002-12-13 20:15:29 +00001903 {
paul68980082003-03-25 05:07:42 +00001904 if ((n = ospf_nbr_count_opaque_capable (oi)) > 0)
paul718e3742002-12-13 20:15:29 +00001905 break;
1906 }
1907
1908 if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1909 {
1910 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001911 zlog_debug ("Suspend re-origination of Type-10 Opaque-LSAs"
paul87d6f872004-09-24 08:01:38 +00001912 " (opaque-type=%u) for a while...",
1913 oipt->opaque_type);
paul718e3742002-12-13 20:15:29 +00001914
1915 oipt->status = PROC_SUSPEND;
1916 rc = 0;
1917 goto out;
1918 }
1919
1920 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001921 zlog_debug ("Timer[Type10-LSA]: Re-originate Opaque-LSAs"
paul87d6f872004-09-24 08:01:38 +00001922 " (opaque-type=%u) for Area %s",
1923 oipt->opaque_type, inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001924
1925 rc = (* functab->lsa_originator)(area);
1926out:
1927 return rc;
1928}
1929
1930static int
1931ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t)
1932{
1933 struct opaque_info_per_type *oipt;
1934 struct ospf_opaque_functab *functab;
1935 struct ospf *top;
1936 int rc = -1;
1937
1938 oipt = THREAD_ARG (t);
1939 oipt->t_opaque_lsa_self = NULL;
1940
1941 if ((functab = oipt->functab) == NULL
paul87d6f872004-09-24 08:01:38 +00001942 || functab->lsa_originator == NULL)
paul718e3742002-12-13 20:15:29 +00001943 {
paul87d6f872004-09-24 08:01:38 +00001944 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer:"
1945 " No associated function?");
paul718e3742002-12-13 20:15:29 +00001946 goto out;
1947 }
1948
1949 if ((top = (struct ospf *) oipt->owner) == NULL)
1950 {
1951 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1952 goto out;
1953 }
1954
1955 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1956 {
1957 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001958 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 +00001959
1960 oipt->status = PROC_SUSPEND;
1961 rc = 0;
1962 goto out;
1963 }
1964
1965 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001966 zlog_debug ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type);
paul718e3742002-12-13 20:15:29 +00001967
1968 rc = (* functab->lsa_originator)(top);
1969out:
1970 return rc;
1971}
1972
paul718e3742002-12-13 20:15:29 +00001973void
1974ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
1975{
1976 struct opaque_info_per_type *oipt;
1977 struct opaque_info_per_id *oipi;
1978 struct ospf_lsa *lsa;
Olivier Dugeon29a14012016-04-19 18:42:40 +02001979 struct ospf *top;
paul718e3742002-12-13 20:15:29 +00001980 int delay;
1981
1982 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
1983 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
1984 {
1985 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
1986 goto out;
1987 }
1988
1989 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
1990 if ((lsa = oipi->lsa) == NULL)
1991 {
1992 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
1993 goto out;
1994 }
1995
1996 if (oipi->t_opaque_lsa_self != NULL)
1997 {
1998 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001999 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 +00002000 goto out;
2001 }
2002
2003 /* Delete this lsa from neighbor retransmit-list. */
2004 switch (lsa->data->type)
2005 {
2006 case OSPF_OPAQUE_LINK_LSA:
2007 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002008 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002009 break;
2010 case OSPF_OPAQUE_AS_LSA:
Olivier Dugeon29a14012016-04-19 18:42:40 +02002011 top = ospf_lookup ();
2012 if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
2013 top = lsa0->area->ospf;
2014 ospf_ls_retransmit_delete_nbr_as (top, lsa);
paul718e3742002-12-13 20:15:29 +00002015 break;
2016 default:
2017 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2018 goto out;
2019 }
2020
2021 delay = ospf_lsa_refresh_delay (lsa);
2022
2023 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002024 zlog_debug ("Schedule Type-%u Opaque-LSA to REFRESH in %d sec later: [opaque-type=%u, opaque-id=%x]", lsa->data->type, delay, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)));
paul718e3742002-12-13 20:15:29 +00002025
2026 OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self,
Michael Rossberg2ef762e2015-07-27 07:56:25 +02002027 ospf_opaque_lsa_refresh_timer, oipi, delay * 1000);
paul718e3742002-12-13 20:15:29 +00002028out:
2029 return;
2030}
2031
2032static int
2033ospf_opaque_lsa_refresh_timer (struct thread *t)
2034{
2035 struct opaque_info_per_id *oipi;
2036 struct ospf_opaque_functab *functab;
2037 struct ospf_lsa *lsa;
2038
2039 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002040 zlog_debug ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
paul718e3742002-12-13 20:15:29 +00002041
2042 oipi = THREAD_ARG (t);
2043 oipi->t_opaque_lsa_self = NULL;
2044
2045 if ((lsa = oipi->lsa) != NULL)
2046 if ((functab = oipi->opqctl_type->functab) != NULL)
2047 if (functab->lsa_refresher != NULL)
2048 (* functab->lsa_refresher)(lsa);
2049
2050 return 0;
2051}
2052
2053void
2054ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
2055{
2056 struct opaque_info_per_type *oipt;
2057 struct opaque_info_per_id *oipi;
2058 struct ospf_lsa *lsa;
Olivier Dugeon29a14012016-04-19 18:42:40 +02002059 struct ospf *top;
2060
2061 top = ospf_lookup ();
paul718e3742002-12-13 20:15:29 +00002062
2063 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
2064 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
2065 {
2066 zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2067 goto out;
2068 }
2069
2070 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2071 if ((lsa = oipi->lsa) == NULL)
2072 {
2073 zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
2074 goto out;
2075 }
2076
2077 /* Delete this lsa from neighbor retransmit-list. */
2078 switch (lsa->data->type)
2079 {
2080 case OSPF_OPAQUE_LINK_LSA:
2081 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002082 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002083 break;
2084 case OSPF_OPAQUE_AS_LSA:
Olivier Dugeon29a14012016-04-19 18:42:40 +02002085 if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
2086 top = lsa0->area->ospf;
2087 ospf_ls_retransmit_delete_nbr_as (top, lsa);
paul718e3742002-12-13 20:15:29 +00002088 break;
2089 default:
2090 zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2091 goto out;
2092 }
2093
2094 /* Dequeue listnode entry from the list. */
2095 listnode_delete (oipt->id_list, oipi);
2096
2097 /* Avoid misjudgement in the next lookup. */
2098 if (listcount (oipt->id_list) == 0)
2099 oipt->id_list->head = oipt->id_list->tail = NULL;
2100
2101 /* Disassociate internal control information with the given lsa. */
paul718e3742002-12-13 20:15:29 +00002102 free_opaque_info_per_id ((void *) oipi);
2103
2104 /* Force given lsa's age to MaxAge. */
2105 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2106
2107 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002108 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 +00002109
2110 /* This lsa will be flushed and removed eventually. */
Olivier Dugeon29a14012016-04-19 18:42:40 +02002111 ospf_lsa_flush (top, lsa);
paul718e3742002-12-13 20:15:29 +00002112
2113out:
2114 return;
2115}
2116
paul718e3742002-12-13 20:15:29 +00002117void
paul87d6f872004-09-24 08:01:38 +00002118ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr,
paul69310a62005-05-11 18:09:59 +00002119 struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002120{
2121 struct ospf *top;
Paul Jakmae30677a2015-01-20 15:45:36 +00002122
paul718e3742002-12-13 20:15:29 +00002123 if ((top = oi_to_top (nbr->oi)) == NULL)
Paul Jakma1fe6ed32006-07-26 09:37:26 +00002124 return;
paul718e3742002-12-13 20:15:29 +00002125
paul69310a62005-05-11 18:09:59 +00002126 /*
2127 * Since these LSA entries are not yet installed into corresponding
2128 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2129 */
2130 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2131 switch (lsa->data->type)
paul718e3742002-12-13 20:15:29 +00002132 {
paul69310a62005-05-11 18:09:59 +00002133 case OSPF_OPAQUE_LINK_LSA:
paul69310a62005-05-11 18:09:59 +00002134 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2135 break;
2136 case OSPF_OPAQUE_AREA_LSA:
paul69310a62005-05-11 18:09:59 +00002137 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2138 break;
2139 case OSPF_OPAQUE_AS_LSA:
paul69310a62005-05-11 18:09:59 +00002140 ospf_flood_through_as (top, NULL/*inbr*/, lsa);
2141 break;
2142 default:
2143 zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
Paul Jakma1fe6ed32006-07-26 09:37:26 +00002144 return;
paul718e3742002-12-13 20:15:29 +00002145 }
Paul Jakmae30677a2015-01-20 15:45:36 +00002146 ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */
paul718e3742002-12-13 20:15:29 +00002147}
2148
paul718e3742002-12-13 20:15:29 +00002149/*------------------------------------------------------------------------*
2150 * Followings are util functions; probably be used by Opaque-LSAs only...
2151 *------------------------------------------------------------------------*/
2152
paul718e3742002-12-13 20:15:29 +00002153struct ospf *
2154oi_to_top (struct ospf_interface *oi)
2155{
2156 struct ospf *top = NULL;
2157 struct ospf_area *area;
2158
paul68980082003-03-25 05:07:42 +00002159 if (oi == NULL || (area = oi->area) == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00002160 zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");
2161
2162 return top;
2163}
2164