blob: 39465c15a721d94a2132e55455f51db83fb7ddf9 [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"
Olivier Dugeon48198692016-04-19 19:21:17 +020065#include "ospfd/ospf_ri.h"
paul718e3742002-12-13 20:15:29 +000066
paul283ae332003-03-17 01:16:55 +000067#ifdef SUPPORT_OSPF_API
68int ospf_apiserver_init (void);
69void ospf_apiserver_term (void);
hassof4d58ce2004-10-12 06:13:54 +000070/* Init apiserver? It's disabled by default. */
71int ospf_apiserver_enable;
paul283ae332003-03-17 01:16:55 +000072#endif /* SUPPORT_OSPF_API */
73
paul718e3742002-12-13 20:15:29 +000074static void ospf_opaque_register_vty (void);
75static void ospf_opaque_funclist_init (void);
76static void ospf_opaque_funclist_term (void);
77static void free_opaque_info_per_type (void *val);
78static void free_opaque_info_per_id (void *val);
79static int ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa);
80static int ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa);
81
82void
83ospf_opaque_init (void)
84{
85 ospf_opaque_register_vty ();
86 ospf_opaque_funclist_init ();
87
paul718e3742002-12-13 20:15:29 +000088 if (ospf_mpls_te_init () != 0)
89 exit (1);
paul718e3742002-12-13 20:15:29 +000090
Olivier Dugeon48198692016-04-19 19:21:17 +020091 if (ospf_router_info_init () != 0)
92 exit (1);
93
paul283ae332003-03-17 01:16:55 +000094#ifdef SUPPORT_OSPF_API
hassoc3abdb72004-10-11 16:27:03 +000095 if ((ospf_apiserver_enable) && (ospf_apiserver_init () != 0))
paul283ae332003-03-17 01:16:55 +000096 exit (1);
97#endif /* SUPPORT_OSPF_API */
98
paul718e3742002-12-13 20:15:29 +000099 return;
100}
101
102void
103ospf_opaque_term (void)
104{
paul718e3742002-12-13 20:15:29 +0000105 ospf_mpls_te_term ();
paul718e3742002-12-13 20:15:29 +0000106
Olivier Dugeon48198692016-04-19 19:21:17 +0200107 ospf_router_info_term ();
108
paul283ae332003-03-17 01:16:55 +0000109#ifdef SUPPORT_OSPF_API
110 ospf_apiserver_term ();
111#endif /* SUPPORT_OSPF_API */
112
paul718e3742002-12-13 20:15:29 +0000113 ospf_opaque_funclist_term ();
114 return;
115}
116
117int
118ospf_opaque_type9_lsa_init (struct ospf_interface *oi)
119{
120 if (oi->opaque_lsa_self != NULL)
121 list_delete (oi->opaque_lsa_self);
122
123 oi->opaque_lsa_self = list_new ();
124 oi->opaque_lsa_self->del = free_opaque_info_per_type;
125 oi->t_opaque_lsa_self = NULL;
126 return 0;
127}
128
129void
130ospf_opaque_type9_lsa_term (struct ospf_interface *oi)
131{
132 OSPF_TIMER_OFF (oi->t_opaque_lsa_self);
133 if (oi->opaque_lsa_self != NULL)
134 list_delete (oi->opaque_lsa_self);
135 oi->opaque_lsa_self = NULL;
136 return;
137}
138
139int
140ospf_opaque_type10_lsa_init (struct ospf_area *area)
141{
142 if (area->opaque_lsa_self != NULL)
143 list_delete (area->opaque_lsa_self);
144
145 area->opaque_lsa_self = list_new ();
146 area->opaque_lsa_self->del = free_opaque_info_per_type;
147 area->t_opaque_lsa_self = NULL;
148
149#ifdef MONITOR_LSDB_CHANGE
150 area->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
151 area->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
152#endif /* MONITOR_LSDB_CHANGE */
153 return 0;
154}
155
156void
157ospf_opaque_type10_lsa_term (struct ospf_area *area)
158{
159#ifdef MONITOR_LSDB_CHANGE
160 area->lsdb->new_lsa_hook =
161 area->lsdb->del_lsa_hook = NULL;
162#endif /* MONITOR_LSDB_CHANGE */
163
164 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
165 if (area->opaque_lsa_self != NULL)
166 list_delete (area->opaque_lsa_self);
167 area->opaque_lsa_self = NULL;
168 return;
169}
170
171int
172ospf_opaque_type11_lsa_init (struct ospf *top)
173{
174 if (top->opaque_lsa_self != NULL)
175 list_delete (top->opaque_lsa_self);
176
177 top->opaque_lsa_self = list_new ();
178 top->opaque_lsa_self->del = free_opaque_info_per_type;
179 top->t_opaque_lsa_self = NULL;
180
181#ifdef MONITOR_LSDB_CHANGE
182 top->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
183 top->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
184#endif /* MONITOR_LSDB_CHANGE */
185 return 0;
186}
187
188void
189ospf_opaque_type11_lsa_term (struct ospf *top)
190{
191#ifdef MONITOR_LSDB_CHANGE
192 top->lsdb->new_lsa_hook =
193 top->lsdb->del_lsa_hook = NULL;
194#endif /* MONITOR_LSDB_CHANGE */
195
196 OSPF_TIMER_OFF (top->t_opaque_lsa_self);
197 if (top->opaque_lsa_self != NULL)
198 list_delete (top->opaque_lsa_self);
199 top->opaque_lsa_self = NULL;
200 return;
201}
202
203static const char *
204ospf_opaque_type_name (u_char opaque_type)
205{
206 const char *name = "Unknown";
207
208 switch (opaque_type)
209 {
210 case OPAQUE_TYPE_WILDCARD: /* This is a special assignment! */
211 name = "Wildcard";
212 break;
213 case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA:
214 name = "Traffic Engineering LSA";
215 break;
216 case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC:
217 name = "Sycamore optical topology description";
218 break;
219 case OPAQUE_TYPE_GRACE_LSA:
220 name = "Grace-LSA";
221 break;
Olivier Dugeon29a14012016-04-19 18:42:40 +0200222 case OPAQUE_TYPE_INTER_AS_LSA:
223 name = "Inter-AS TE-v2 LSA";
224 break;
Olivier Dugeon48198692016-04-19 19:21:17 +0200225 case OPAQUE_TYPE_ROUTER_INFORMATION_LSA:
226 name = "Router Information LSA";
227 break;
paul718e3742002-12-13 20:15:29 +0000228 default:
229 if (OPAQUE_TYPE_RANGE_UNASSIGNED (opaque_type))
230 name = "Unassigned";
Andrew Certain0798cee2012-12-04 13:43:42 -0800231 else
232 {
233 u_int32_t bigger_range = opaque_type;
234 /*
235 * Get around type-limits warning: comparison is always true due to limited range of data type
236 */
237 if (OPAQUE_TYPE_RANGE_RESERVED (bigger_range))
238 name = "Private/Experimental";
239 }
paul718e3742002-12-13 20:15:29 +0000240 break;
241 }
242 return name;
243}
244
245/*------------------------------------------------------------------------*
246 * Followings are management functions to store user specified callbacks.
247 *------------------------------------------------------------------------*/
248
249struct opaque_info_per_type; /* Forward declaration. */
250
251struct ospf_opaque_functab
252{
253 u_char opaque_type;
254 struct opaque_info_per_type *oipt;
255
256 int (* new_if_hook)(struct interface *ifp);
257 int (* del_if_hook)(struct interface *ifp);
258 void (* ism_change_hook)(struct ospf_interface *oi, int old_status);
259 void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status);
260 void (* config_write_router)(struct vty *vty);
261 void (* config_write_if )(struct vty *vty, struct interface *ifp);
262 void (* config_write_debug )(struct vty *vty);
263 void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa);
264 int (* lsa_originator)(void *arg);
Paul Jakmad71ea652011-03-22 15:23:55 +0000265 struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa);
paul718e3742002-12-13 20:15:29 +0000266 int (* new_lsa_hook)(struct ospf_lsa *lsa);
267 int (* del_lsa_hook)(struct ospf_lsa *lsa);
268};
269
paul87d6f872004-09-24 08:01:38 +0000270/* Handle LSA-9/10/11 altogether. */
271static struct list *ospf_opaque_wildcard_funclist;
272static struct list *ospf_opaque_type9_funclist;
273static struct list *ospf_opaque_type10_funclist;
274static struct list *ospf_opaque_type11_funclist;
paul718e3742002-12-13 20:15:29 +0000275
276static void
277ospf_opaque_del_functab (void *val)
278{
279 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, val);
280 return;
281}
282
283static void
284ospf_opaque_funclist_init (void)
285{
paul87d6f872004-09-24 08:01:38 +0000286 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000287
paul09e4efd2003-01-18 00:12:02 +0000288 funclist = ospf_opaque_wildcard_funclist = list_new ();
289 funclist->del = ospf_opaque_del_functab;
290
paul718e3742002-12-13 20:15:29 +0000291 funclist = ospf_opaque_type9_funclist = list_new ();
292 funclist->del = ospf_opaque_del_functab;
293
294 funclist = ospf_opaque_type10_funclist = list_new ();
295 funclist->del = ospf_opaque_del_functab;
296
297 funclist = ospf_opaque_type11_funclist = list_new ();
298 funclist->del = ospf_opaque_del_functab;
299 return;
300}
301
302static void
303ospf_opaque_funclist_term (void)
304{
paul87d6f872004-09-24 08:01:38 +0000305 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000306
paul09e4efd2003-01-18 00:12:02 +0000307 funclist = ospf_opaque_wildcard_funclist;
308 list_delete (funclist);
309
paul718e3742002-12-13 20:15:29 +0000310 funclist = ospf_opaque_type9_funclist;
311 list_delete (funclist);
312
313 funclist = ospf_opaque_type10_funclist;
314 list_delete (funclist);
315
316 funclist = ospf_opaque_type11_funclist;
317 list_delete (funclist);
318 return;
319}
320
paul87d6f872004-09-24 08:01:38 +0000321static struct list *
paul718e3742002-12-13 20:15:29 +0000322ospf_get_opaque_funclist (u_char lsa_type)
323{
paul87d6f872004-09-24 08:01:38 +0000324 struct list *funclist = NULL;
paul718e3742002-12-13 20:15:29 +0000325
326 switch (lsa_type)
327 {
paul09e4efd2003-01-18 00:12:02 +0000328 case OPAQUE_TYPE_WILDCARD:
329 /* XXX
330 * This is an ugly trick to handle type-9/10/11 LSA altogether.
331 * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor
332 * an officially assigned opaque-type.
333 * Though it is possible that the value might be officially used
334 * in the future, we use it internally as a special label, for now.
335 */
336 funclist = ospf_opaque_wildcard_funclist;
337 break;
paul718e3742002-12-13 20:15:29 +0000338 case OSPF_OPAQUE_LINK_LSA:
339 funclist = ospf_opaque_type9_funclist;
340 break;
341 case OSPF_OPAQUE_AREA_LSA:
342 funclist = ospf_opaque_type10_funclist;
343 break;
344 case OSPF_OPAQUE_AS_LSA:
345 funclist = ospf_opaque_type11_funclist;
346 break;
347 default:
348 zlog_warn ("ospf_get_opaque_funclist: Unexpected LSA-type(%u)", lsa_type);
349 break;
350 }
351 return funclist;
352}
353
paul87d6f872004-09-24 08:01:38 +0000354/* XXX: such a huge argument list can /not/ be healthy... */
paul718e3742002-12-13 20:15:29 +0000355int
356ospf_register_opaque_functab (
357 u_char lsa_type,
358 u_char opaque_type,
359 int (* new_if_hook)(struct interface *ifp),
360 int (* del_if_hook)(struct interface *ifp),
361 void (* ism_change_hook)(struct ospf_interface *oi, int old_status),
362 void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status),
363 void (* config_write_router)(struct vty *vty),
364 void (* config_write_if )(struct vty *vty, struct interface *ifp),
365 void (* config_write_debug )(struct vty *vty),
366 void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa),
367 int (* lsa_originator)(void *arg),
Paul Jakmad71ea652011-03-22 15:23:55 +0000368 struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa),
paul718e3742002-12-13 20:15:29 +0000369 int (* new_lsa_hook)(struct ospf_lsa *lsa),
370 int (* del_lsa_hook)(struct ospf_lsa *lsa))
371{
paul87d6f872004-09-24 08:01:38 +0000372 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000373 struct ospf_opaque_functab *new;
374 int rc = -1;
375
376 if ((funclist = ospf_get_opaque_funclist (lsa_type)) == NULL)
377 {
paul87d6f872004-09-24 08:01:38 +0000378 zlog_warn ("ospf_register_opaque_functab: Cannot get funclist"
379 " for Type-%u LSAs?",
380 lsa_type);
paul718e3742002-12-13 20:15:29 +0000381 goto out;
382 }
383 else
384 {
paul1eb8ef22005-04-07 07:30:20 +0000385 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000386 struct ospf_opaque_functab *functab;
paul87d6f872004-09-24 08:01:38 +0000387
paul1eb8ef22005-04-07 07:30:20 +0000388 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000389 if (functab->opaque_type == opaque_type)
390 {
391 zlog_warn ("ospf_register_opaque_functab: Duplicated entry?:"
392 " lsa_type(%u), opaque_type(%u)",
393 lsa_type, opaque_type);
394 goto out;
395 }
paul718e3742002-12-13 20:15:29 +0000396 }
397
398 if ((new = XCALLOC (MTYPE_OSPF_OPAQUE_FUNCTAB,
399 sizeof (struct ospf_opaque_functab))) == NULL)
400 {
paul87d6f872004-09-24 08:01:38 +0000401 zlog_warn ("ospf_register_opaque_functab: XMALLOC: %s",
ajs6099b3b2004-11-20 02:06:59 +0000402 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000403 goto out;
404 }
405
406 new->opaque_type = opaque_type;
407 new->oipt = NULL;
408 new->new_if_hook = new_if_hook;
409 new->del_if_hook = del_if_hook;
410 new->ism_change_hook = ism_change_hook;
411 new->nsm_change_hook = nsm_change_hook;
412 new->config_write_router = config_write_router;
413 new->config_write_if = config_write_if;
414 new->config_write_debug = config_write_debug;
415 new->show_opaque_info = show_opaque_info;
416 new->lsa_originator = lsa_originator;
417 new->lsa_refresher = lsa_refresher;
418 new->new_lsa_hook = new_lsa_hook;
419 new->del_lsa_hook = del_lsa_hook;
420
421 listnode_add (funclist, new);
422 rc = 0;
423
424out:
425 return rc;
426}
427
428void
429ospf_delete_opaque_functab (u_char lsa_type, u_char opaque_type)
430{
paul87d6f872004-09-24 08:01:38 +0000431 struct list *funclist;
paul1eb8ef22005-04-07 07:30:20 +0000432 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000433 struct ospf_opaque_functab *functab;
434
435 if ((funclist = ospf_get_opaque_funclist (lsa_type)) != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000436 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul718e3742002-12-13 20:15:29 +0000437 {
paul1eb8ef22005-04-07 07:30:20 +0000438 if (functab->opaque_type == opaque_type)
paul718e3742002-12-13 20:15:29 +0000439 {
440 /* Cleanup internal control information, if it still remains. */
441 if (functab->oipt != NULL)
442 free_opaque_info_per_type (functab->oipt);
443
444 /* Dequeue listnode entry from the list. */
445 listnode_delete (funclist, functab);
446
447 /* Avoid misjudgement in the next lookup. */
448 if (listcount (funclist) == 0)
449 funclist->head = funclist->tail = NULL;
450
451 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, functab);
paul87d6f872004-09-24 08:01:38 +0000452 break;
paul718e3742002-12-13 20:15:29 +0000453 }
454 }
paul87d6f872004-09-24 08:01:38 +0000455
paul718e3742002-12-13 20:15:29 +0000456 return;
457}
458
459static struct ospf_opaque_functab *
460ospf_opaque_functab_lookup (struct ospf_lsa *lsa)
461{
paul87d6f872004-09-24 08:01:38 +0000462 struct list *funclist;
463 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000464 struct ospf_opaque_functab *functab;
465 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
466
467 if ((funclist = ospf_get_opaque_funclist (lsa->data->type)) != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000468 for (ALL_LIST_ELEMENTS_RO (funclist, node, functab))
paul87d6f872004-09-24 08:01:38 +0000469 if (functab->opaque_type == key)
470 return functab;
paul718e3742002-12-13 20:15:29 +0000471
472 return NULL;
473}
474
475/*------------------------------------------------------------------------*
476 * Followings are management functions for self-originated LSA entries.
477 *------------------------------------------------------------------------*/
478
479/*
480 * Opaque-LSA control information per opaque-type.
481 * Single Opaque-Type may have multiple instances; each of them will be
482 * identified by their opaque-id.
483 */
484struct opaque_info_per_type
485{
paul09e4efd2003-01-18 00:12:02 +0000486 u_char lsa_type;
paul718e3742002-12-13 20:15:29 +0000487 u_char opaque_type;
488
489 enum { PROC_NORMAL, PROC_SUSPEND } status;
490
491 /*
492 * Thread for (re-)origination scheduling for this opaque-type.
493 *
494 * Initial origination of Opaque-LSAs is controlled by generic
495 * Opaque-LSA handling module so that same opaque-type entries are
496 * called all at once when certain conditions are met.
497 * However, there might be cases that some Opaque-LSA clients need
498 * to (re-)originate their own Opaque-LSAs out-of-sync with others.
499 * This thread is prepared for that specific purpose.
500 */
501 struct thread *t_opaque_lsa_self;
502
503 /*
paul09e4efd2003-01-18 00:12:02 +0000504 * Backpointer to an "owner" which is LSA-type dependent.
paul718e3742002-12-13 20:15:29 +0000505 * type-9: struct ospf_interface
506 * type-10: struct ospf_area
507 * type-11: struct ospf
508 */
509 void *owner;
510
511 /* Collection of callback functions for this opaque-type. */
512 struct ospf_opaque_functab *functab;
513
514 /* List of Opaque-LSA control informations per opaque-id. */
paul87d6f872004-09-24 08:01:38 +0000515 struct list *id_list;
paul718e3742002-12-13 20:15:29 +0000516};
517
518/* Opaque-LSA control information per opaque-id. */
519struct opaque_info_per_id
520{
521 u_int32_t opaque_id;
522
523 /* Thread for refresh/flush scheduling for this opaque-type/id. */
524 struct thread *t_opaque_lsa_self;
525
526 /* Backpointer to Opaque-LSA control information per opaque-type. */
527 struct opaque_info_per_type *opqctl_type;
528
529 /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
530 struct ospf_lsa *lsa;
531};
532
533static struct opaque_info_per_type *register_opaque_info_per_type (struct ospf_opaque_functab *functab, struct ospf_lsa *new);
534static struct opaque_info_per_type *lookup_opaque_info_by_type (struct ospf_lsa *lsa);
535static struct opaque_info_per_id *register_opaque_info_per_id (struct opaque_info_per_type *oipt, struct ospf_lsa *new);
536static struct opaque_info_per_id *lookup_opaque_info_by_id (struct opaque_info_per_type *oipt, struct ospf_lsa *lsa);
537static struct opaque_info_per_id *register_opaque_lsa (struct ospf_lsa *new);
538
539
540static struct opaque_info_per_type *
541register_opaque_info_per_type (struct ospf_opaque_functab *functab,
542 struct ospf_lsa *new)
543{
544 struct ospf *top;
545 struct opaque_info_per_type *oipt;
546
547 if ((oipt = XCALLOC (MTYPE_OPAQUE_INFO_PER_TYPE,
548 sizeof (struct opaque_info_per_type))) == NULL)
549 {
ajs6099b3b2004-11-20 02:06:59 +0000550 zlog_warn ("register_opaque_info_per_type: XMALLOC: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000551 goto out;
552 }
553
554 switch (new->data->type)
555 {
556 case OSPF_OPAQUE_LINK_LSA:
557 oipt->owner = new->oi;
558 listnode_add (new->oi->opaque_lsa_self, oipt);
559 break;
560 case OSPF_OPAQUE_AREA_LSA:
561 oipt->owner = new->area;
562 listnode_add (new->area->opaque_lsa_self, oipt);
563 break;
564 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +0000565 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000566 if (new->area != NULL && (top = new->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +0000567 {
568 free_opaque_info_per_type ((void *) oipt);
569 oipt = NULL;
570 goto out; /* This case may not exist. */
571 }
572 oipt->owner = top;
573 listnode_add (top->opaque_lsa_self, oipt);
574 break;
575 default:
paul09e4efd2003-01-18 00:12:02 +0000576 zlog_warn ("register_opaque_info_per_type: Unexpected LSA-type(%u)", new->data->type);
paul718e3742002-12-13 20:15:29 +0000577 free_opaque_info_per_type ((void *) oipt);
578 oipt = NULL;
579 goto out; /* This case may not exist. */
580 }
581
paul09e4efd2003-01-18 00:12:02 +0000582 oipt->lsa_type = new->data->type;
paul718e3742002-12-13 20:15:29 +0000583 oipt->opaque_type = GET_OPAQUE_TYPE (ntohl (new->data->id.s_addr));
584 oipt->status = PROC_NORMAL;
585 oipt->t_opaque_lsa_self = NULL;
586 oipt->functab = functab;
587 functab->oipt = oipt;
588 oipt->id_list = list_new ();
589 oipt->id_list->del = free_opaque_info_per_id;
590
591out:
592 return oipt;
593}
594
595static void
596free_opaque_info_per_type (void *val)
597{
598 struct opaque_info_per_type *oipt = (struct opaque_info_per_type *) val;
599 struct opaque_info_per_id *oipi;
600 struct ospf_lsa *lsa;
paul1eb8ef22005-04-07 07:30:20 +0000601 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000602
603 /* Control information per opaque-id may still exist. */
paul1eb8ef22005-04-07 07:30:20 +0000604 for (ALL_LIST_ELEMENTS (oipt->id_list, node, nnode, oipi))
paul718e3742002-12-13 20:15:29 +0000605 {
paul718e3742002-12-13 20:15:29 +0000606 if ((lsa = oipi->lsa) == NULL)
607 continue;
608 if (IS_LSA_MAXAGE (lsa))
609 continue;
610 ospf_opaque_lsa_flush_schedule (lsa);
611 }
612
paul09e4efd2003-01-18 00:12:02 +0000613 /* Remove "oipt" from its owner's self-originated LSA list. */
614 switch (oipt->lsa_type)
615 {
616 case OSPF_OPAQUE_LINK_LSA:
617 {
618 struct ospf_interface *oi = (struct ospf_interface *)(oipt->owner);
619 listnode_delete (oi->opaque_lsa_self, oipt);
620 break;
621 }
622 case OSPF_OPAQUE_AREA_LSA:
623 {
624 struct ospf_area *area = (struct ospf_area *)(oipt->owner);
625 listnode_delete (area->opaque_lsa_self, oipt);
626 break;
627 }
628 case OSPF_OPAQUE_AS_LSA:
629 {
630 struct ospf *top = (struct ospf *)(oipt->owner);
631 listnode_delete (top->opaque_lsa_self, oipt);
632 break;
633 }
634 default:
635 zlog_warn ("free_opaque_info_per_type: Unexpected LSA-type(%u)", oipt->lsa_type);
636 break; /* This case may not exist. */
637 }
638
paul718e3742002-12-13 20:15:29 +0000639 OSPF_TIMER_OFF (oipt->t_opaque_lsa_self);
640 list_delete (oipt->id_list);
641 XFREE (MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
642 return;
643}
644
645static struct opaque_info_per_type *
646lookup_opaque_info_by_type (struct ospf_lsa *lsa)
647{
648 struct ospf *top;
649 struct ospf_area *area;
650 struct ospf_interface *oi;
paul87d6f872004-09-24 08:01:38 +0000651 struct list *listtop = NULL;
paul1eb8ef22005-04-07 07:30:20 +0000652 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000653 struct opaque_info_per_type *oipt = NULL;
654 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
655
656 switch (lsa->data->type)
657 {
658 case OSPF_OPAQUE_LINK_LSA:
659 if ((oi = lsa->oi) != NULL)
660 listtop = oi->opaque_lsa_self;
661 else
662 zlog_warn ("Type-9 Opaque-LSA: Reference to OI is missing?");
663 break;
664 case OSPF_OPAQUE_AREA_LSA:
665 if ((area = lsa->area) != NULL)
666 listtop = area->opaque_lsa_self;
667 else
668 zlog_warn ("Type-10 Opaque-LSA: Reference to AREA is missing?");
669 break;
670 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +0000671 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000672 if ((area = lsa->area) != NULL && (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +0000673 {
674 zlog_warn ("Type-11 Opaque-LSA: Reference to OSPF is missing?");
675 break; /* Unlikely to happen. */
676 }
677 listtop = top->opaque_lsa_self;
678 break;
679 default:
680 zlog_warn ("lookup_opaque_info_by_type: Unexpected LSA-type(%u)", lsa->data->type);
681 break;
682 }
683
684 if (listtop != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000685 for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt))
paul87d6f872004-09-24 08:01:38 +0000686 if (oipt->opaque_type == key)
687 return oipt;
paul718e3742002-12-13 20:15:29 +0000688
689 return NULL;
690}
691
692static struct opaque_info_per_id *
693register_opaque_info_per_id (struct opaque_info_per_type *oipt,
694 struct ospf_lsa *new)
695{
696 struct opaque_info_per_id *oipi;
697
698 if ((oipi = XCALLOC (MTYPE_OPAQUE_INFO_PER_ID,
699 sizeof (struct opaque_info_per_id))) == NULL)
700 {
ajs6099b3b2004-11-20 02:06:59 +0000701 zlog_warn ("register_opaque_info_per_id: XMALLOC: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000702 goto out;
703 }
704 oipi->opaque_id = GET_OPAQUE_ID (ntohl (new->data->id.s_addr));
705 oipi->t_opaque_lsa_self = NULL;
706 oipi->opqctl_type = oipt;
707 oipi->lsa = ospf_lsa_lock (new);
708
709 listnode_add (oipt->id_list, oipi);
710
711out:
712 return oipi;
713}
714
715static void
716free_opaque_info_per_id (void *val)
717{
718 struct opaque_info_per_id *oipi = (struct opaque_info_per_id *) val;
719
720 OSPF_TIMER_OFF (oipi->t_opaque_lsa_self);
721 if (oipi->lsa != NULL)
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000722 ospf_lsa_unlock (&oipi->lsa);
paul718e3742002-12-13 20:15:29 +0000723 XFREE (MTYPE_OPAQUE_INFO_PER_ID, oipi);
724 return;
725}
726
727static struct opaque_info_per_id *
728lookup_opaque_info_by_id (struct opaque_info_per_type *oipt,
729 struct ospf_lsa *lsa)
730{
paul1eb8ef22005-04-07 07:30:20 +0000731 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000732 struct opaque_info_per_id *oipi;
733 u_int32_t key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
734
paul1eb8ef22005-04-07 07:30:20 +0000735 for (ALL_LIST_ELEMENTS (oipt->id_list, node, nnode, oipi))
paul87d6f872004-09-24 08:01:38 +0000736 if (oipi->opaque_id == key)
737 return oipi;
paul718e3742002-12-13 20:15:29 +0000738
739 return NULL;
740}
741
742static struct opaque_info_per_id *
743register_opaque_lsa (struct ospf_lsa *new)
744{
745 struct ospf_opaque_functab *functab;
746 struct opaque_info_per_type *oipt;
747 struct opaque_info_per_id *oipi = NULL;
748
749 if ((functab = ospf_opaque_functab_lookup (new)) == NULL)
750 goto out;
751
752 if ((oipt = lookup_opaque_info_by_type (new)) == NULL
753 && (oipt = register_opaque_info_per_type (functab, new)) == NULL)
754 goto out;
755
756 if ((oipi = register_opaque_info_per_id (oipt, new)) == NULL)
757 goto out;
758
759out:
760 return oipi;
761}
762
763/*------------------------------------------------------------------------*
764 * Followings are (vty) configuration functions for Opaque-LSAs handling.
765 *------------------------------------------------------------------------*/
766
767DEFUN (capability_opaque,
768 capability_opaque_cmd,
769 "capability opaque",
770 "Enable specific OSPF feature\n"
771 "Opaque LSA\n")
772{
773 struct ospf *ospf = (struct ospf *) vty->index;
774
775 /* Turn on the "master switch" of opaque-lsa capability. */
776 if (!CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
777 {
778 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000779 zlog_debug ("Opaque capability: OFF -> ON");
paul718e3742002-12-13 20:15:29 +0000780
781 SET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
782 ospf_renegotiate_optional_capabilities (ospf);
783 }
784 return CMD_SUCCESS;
785}
786
787ALIAS (capability_opaque,
788 ospf_opaque_capable_cmd,
789 "ospf opaque-lsa",
790 "OSPF specific commands\n"
791 "Enable the Opaque-LSA capability (rfc2370)\n")
792
793DEFUN (no_capability_opaque,
794 no_capability_opaque_cmd,
795 "no capability opaque",
796 NO_STR
797 "Enable specific OSPF feature\n"
798 "Opaque LSA\n")
799{
800 struct ospf *ospf = (struct ospf *) vty->index;
801
802 /* Turn off the "master switch" of opaque-lsa capability. */
803 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
804 {
805 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000806 zlog_debug ("Opaque capability: ON -> OFF");
paul718e3742002-12-13 20:15:29 +0000807
808 UNSET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
809 ospf_renegotiate_optional_capabilities (ospf);
810 }
811 return CMD_SUCCESS;
812}
813
814ALIAS (no_capability_opaque,
815 no_ospf_opaque_capable_cmd,
816 "no ospf opaque-lsa",
817 NO_STR
818 "OSPF specific commands\n"
819 "Disable the Opaque-LSA capability (rfc2370)\n")
820
821static void
822ospf_opaque_register_vty (void)
823{
824 install_element (OSPF_NODE, &capability_opaque_cmd);
825 install_element (OSPF_NODE, &no_capability_opaque_cmd);
826 install_element (OSPF_NODE, &ospf_opaque_capable_cmd);
827 install_element (OSPF_NODE, &no_ospf_opaque_capable_cmd);
828 return;
829}
830
831/*------------------------------------------------------------------------*
832 * Followings are collection of user-registered function callers.
833 *------------------------------------------------------------------------*/
834
835static int
paul87d6f872004-09-24 08:01:38 +0000836opaque_lsa_new_if_callback (struct list *funclist, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000837{
paul1eb8ef22005-04-07 07:30:20 +0000838 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000839 struct ospf_opaque_functab *functab;
840 int rc = -1;
841
paul1eb8ef22005-04-07 07:30:20 +0000842 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000843 if (functab->new_if_hook != NULL)
844 if ((* functab->new_if_hook)(ifp) != 0)
845 goto out;
paul718e3742002-12-13 20:15:29 +0000846 rc = 0;
847out:
848 return rc;
849}
850
851static int
paul87d6f872004-09-24 08:01:38 +0000852opaque_lsa_del_if_callback (struct list *funclist, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000853{
paul1eb8ef22005-04-07 07:30:20 +0000854 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000855 struct ospf_opaque_functab *functab;
856 int rc = -1;
857
paul1eb8ef22005-04-07 07:30:20 +0000858 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000859 if (functab->del_if_hook != NULL)
860 if ((* functab->del_if_hook)(ifp) != 0)
861 goto out;
paul718e3742002-12-13 20:15:29 +0000862 rc = 0;
863out:
864 return rc;
865}
866
867static void
paul87d6f872004-09-24 08:01:38 +0000868opaque_lsa_ism_change_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000869 struct ospf_interface *oi, int old_status)
870{
paul1eb8ef22005-04-07 07:30:20 +0000871 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000872 struct ospf_opaque_functab *functab;
873
paul1eb8ef22005-04-07 07:30:20 +0000874 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000875 if (functab->ism_change_hook != NULL)
876 (* functab->ism_change_hook)(oi, old_status);
877
paul718e3742002-12-13 20:15:29 +0000878 return;
879}
880
881static void
paul87d6f872004-09-24 08:01:38 +0000882opaque_lsa_nsm_change_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000883 struct ospf_neighbor *nbr, int old_status)
884{
paul1eb8ef22005-04-07 07:30:20 +0000885 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000886 struct ospf_opaque_functab *functab;
887
paul1eb8ef22005-04-07 07:30:20 +0000888 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000889 if (functab->nsm_change_hook != NULL)
890 (* functab->nsm_change_hook)(nbr, old_status);
paul718e3742002-12-13 20:15:29 +0000891 return;
892}
893
894static void
paul87d6f872004-09-24 08:01:38 +0000895opaque_lsa_config_write_router_callback (struct list *funclist,
896 struct vty *vty)
paul718e3742002-12-13 20:15:29 +0000897{
paul1eb8ef22005-04-07 07:30:20 +0000898 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000899 struct ospf_opaque_functab *functab;
900
paul1eb8ef22005-04-07 07:30:20 +0000901 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000902 if (functab->config_write_router != NULL)
903 (* functab->config_write_router)(vty);
paul718e3742002-12-13 20:15:29 +0000904 return;
905}
906
907static void
paul87d6f872004-09-24 08:01:38 +0000908opaque_lsa_config_write_if_callback (struct list *funclist,
paul718e3742002-12-13 20:15:29 +0000909 struct vty *vty, struct interface *ifp)
910{
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_if != NULL)
916 (* functab->config_write_if)(vty, ifp);
paul718e3742002-12-13 20:15:29 +0000917 return;
918}
919
920static void
paul87d6f872004-09-24 08:01:38 +0000921opaque_lsa_config_write_debug_callback (struct list *funclist, struct vty *vty)
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
paul1eb8ef22005-04-07 07:30:20 +0000926 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000927 if (functab->config_write_debug != NULL)
928 (* functab->config_write_debug)(vty);
paul718e3742002-12-13 20:15:29 +0000929 return;
930}
931
932static int
paul87d6f872004-09-24 08:01:38 +0000933opaque_lsa_originate_callback (struct list *funclist, void *lsa_type_dependent)
paul718e3742002-12-13 20:15:29 +0000934{
paul1eb8ef22005-04-07 07:30:20 +0000935 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000936 struct ospf_opaque_functab *functab;
937 int rc = -1;
938
paul1eb8ef22005-04-07 07:30:20 +0000939 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000940 if (functab->lsa_originator != NULL)
941 if ((* functab->lsa_originator)(lsa_type_dependent) != 0)
942 goto out;
paul718e3742002-12-13 20:15:29 +0000943 rc = 0;
944out:
945 return rc;
946}
947
948static int
paul87d6f872004-09-24 08:01:38 +0000949new_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000950{
paul1eb8ef22005-04-07 07:30:20 +0000951 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000952 struct ospf_opaque_functab *functab;
953 int rc = -1;
954
955 /* This function handles ALL types of LSAs, not only opaque ones. */
paul1eb8ef22005-04-07 07:30:20 +0000956 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000957 if (functab->new_lsa_hook != NULL)
958 if ((* functab->new_lsa_hook)(lsa) != 0)
959 goto out;
paul718e3742002-12-13 20:15:29 +0000960 rc = 0;
961out:
962 return rc;
963}
964
965static int
paul87d6f872004-09-24 08:01:38 +0000966del_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000967{
paul1eb8ef22005-04-07 07:30:20 +0000968 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000969 struct ospf_opaque_functab *functab;
970 int rc = -1;
971
972 /* This function handles ALL types of LSAs, not only opaque ones. */
paul1eb8ef22005-04-07 07:30:20 +0000973 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
paul87d6f872004-09-24 08:01:38 +0000974 if (functab->del_lsa_hook != NULL)
975 if ((* functab->del_lsa_hook)(lsa) != 0)
976 goto out;
paul718e3742002-12-13 20:15:29 +0000977 rc = 0;
978out:
979 return rc;
980}
981
982/*------------------------------------------------------------------------*
983 * Followings are glue functions to call Opaque-LSA specific processing.
984 *------------------------------------------------------------------------*/
985
986int
987ospf_opaque_new_if (struct interface *ifp)
988{
paul87d6f872004-09-24 08:01:38 +0000989 struct list *funclist;
paul718e3742002-12-13 20:15:29 +0000990 int rc = -1;
991
paul09e4efd2003-01-18 00:12:02 +0000992 funclist = ospf_opaque_wildcard_funclist;
993 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
994 goto out;
995
paul718e3742002-12-13 20:15:29 +0000996 funclist = ospf_opaque_type9_funclist;
997 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
998 goto out;
999
1000 funclist = ospf_opaque_type10_funclist;
1001 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
1002 goto out;
1003
1004 funclist = ospf_opaque_type11_funclist;
1005 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
1006 goto out;
1007
1008 rc = 0;
1009out:
1010 return rc;
1011}
1012
1013int
1014ospf_opaque_del_if (struct interface *ifp)
1015{
paul87d6f872004-09-24 08:01:38 +00001016 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001017 int rc = -1;
1018
paul09e4efd2003-01-18 00:12:02 +00001019 funclist = ospf_opaque_wildcard_funclist;
1020 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1021 goto out;
1022
paul718e3742002-12-13 20:15:29 +00001023 funclist = ospf_opaque_type9_funclist;
1024 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1025 goto out;
1026
1027 funclist = ospf_opaque_type10_funclist;
1028 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1029 goto out;
1030
1031 funclist = ospf_opaque_type11_funclist;
1032 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1033 goto out;
1034
1035 rc = 0;
1036out:
1037 return rc;
1038}
1039
1040void
1041ospf_opaque_ism_change (struct ospf_interface *oi, int old_status)
1042{
paul87d6f872004-09-24 08:01:38 +00001043 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001044
paul09e4efd2003-01-18 00:12:02 +00001045 funclist = ospf_opaque_wildcard_funclist;
1046 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1047
paul718e3742002-12-13 20:15:29 +00001048 funclist = ospf_opaque_type9_funclist;
1049 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1050
1051 funclist = ospf_opaque_type10_funclist;
1052 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1053
1054 funclist = ospf_opaque_type11_funclist;
1055 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1056
1057 return;
1058}
1059
1060void
1061ospf_opaque_nsm_change (struct ospf_neighbor *nbr, int old_state)
1062{
1063 struct ospf *top;
paul87d6f872004-09-24 08:01:38 +00001064 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001065
1066 if ((top = oi_to_top (nbr->oi)) == NULL)
1067 goto out;
1068
1069 if (old_state != NSM_Full && nbr->state == NSM_Full)
1070 {
1071 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
1072 {
1073 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1074 {
1075 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001076 zlog_debug ("Opaque-LSA: Now get operational!");
paul718e3742002-12-13 20:15:29 +00001077
1078 SET_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT);
1079 }
1080
1081 ospf_opaque_lsa_originate_schedule (nbr->oi, NULL);
1082 }
1083 }
1084 else
1085 if (old_state == NSM_Full && nbr->state != NSM_Full)
1086 {
1087#ifdef NOTYET
1088 /*
1089 * If no more opaque-capable full-state neighbor remains in the
1090 * flooding scope which corresponds to Opaque-LSA type, periodic
1091 * LS flooding should be stopped.
1092 */
1093#endif /* NOTYET */
1094 ;
1095 }
1096
paul09e4efd2003-01-18 00:12:02 +00001097 funclist = ospf_opaque_wildcard_funclist;
1098 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1099
paul718e3742002-12-13 20:15:29 +00001100 funclist = ospf_opaque_type9_funclist;
1101 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1102
1103 funclist = ospf_opaque_type10_funclist;
1104 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1105
1106 funclist = ospf_opaque_type11_funclist;
1107 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1108
1109out:
1110 return;
1111}
1112
1113void
1114ospf_opaque_config_write_router (struct vty *vty, struct ospf *ospf)
1115{
paul87d6f872004-09-24 08:01:38 +00001116 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001117
1118 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
1119 vty_out (vty, " capability opaque%s", VTY_NEWLINE);
1120
paul09e4efd2003-01-18 00:12:02 +00001121 funclist = ospf_opaque_wildcard_funclist;
1122 opaque_lsa_config_write_router_callback (funclist, vty);
1123
paul718e3742002-12-13 20:15:29 +00001124 funclist = ospf_opaque_type9_funclist;
1125 opaque_lsa_config_write_router_callback (funclist, vty);
1126
1127 funclist = ospf_opaque_type10_funclist;
1128 opaque_lsa_config_write_router_callback (funclist, vty);
1129
1130 funclist = ospf_opaque_type11_funclist;
1131 opaque_lsa_config_write_router_callback (funclist, vty);
1132
1133 return;
1134}
1135
1136void
1137ospf_opaque_config_write_if (struct vty *vty, struct interface *ifp)
1138{
paul87d6f872004-09-24 08:01:38 +00001139 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001140
paul09e4efd2003-01-18 00:12:02 +00001141 funclist = ospf_opaque_wildcard_funclist;
1142 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1143
paul718e3742002-12-13 20:15:29 +00001144 funclist = ospf_opaque_type9_funclist;
1145 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1146
1147 funclist = ospf_opaque_type10_funclist;
1148 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1149
1150 funclist = ospf_opaque_type11_funclist;
1151 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1152
1153 return;
1154}
1155
1156void
1157ospf_opaque_config_write_debug (struct vty *vty)
1158{
paul87d6f872004-09-24 08:01:38 +00001159 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001160
paul09e4efd2003-01-18 00:12:02 +00001161 funclist = ospf_opaque_wildcard_funclist;
1162 opaque_lsa_config_write_debug_callback (funclist, vty);
1163
paul718e3742002-12-13 20:15:29 +00001164 funclist = ospf_opaque_type9_funclist;
1165 opaque_lsa_config_write_debug_callback (funclist, vty);
1166
1167 funclist = ospf_opaque_type10_funclist;
1168 opaque_lsa_config_write_debug_callback (funclist, vty);
1169
1170 funclist = ospf_opaque_type11_funclist;
1171 opaque_lsa_config_write_debug_callback (funclist, vty);
1172
1173 return;
1174}
1175
1176void
1177show_opaque_info_detail (struct vty *vty, struct ospf_lsa *lsa)
1178{
1179 struct lsa_header *lsah = (struct lsa_header *) lsa->data;
1180 u_int32_t lsid = ntohl (lsah->id.s_addr);
1181 u_char opaque_type = GET_OPAQUE_TYPE (lsid);
1182 u_int32_t opaque_id = GET_OPAQUE_ID (lsid);
1183 struct ospf_opaque_functab *functab;
1184
1185 /* Switch output functionality by vty address. */
1186 if (vty != NULL)
1187 {
paul020709f2003-04-04 02:44:16 +00001188 vty_out (vty, " Opaque-Type %u (%s)%s", opaque_type,
1189 ospf_opaque_type_name (opaque_type), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001190 vty_out (vty, " Opaque-ID 0x%x%s", opaque_id, VTY_NEWLINE);
1191
1192 vty_out (vty, " Opaque-Info: %u octets of data%s%s",
1193 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1194 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)",
1195 VTY_NEWLINE);
1196 }
1197 else
1198 {
ajs2a42e282004-12-08 18:43:03 +00001199 zlog_debug (" Opaque-Type %u (%s)", opaque_type,
paul020709f2003-04-04 02:44:16 +00001200 ospf_opaque_type_name (opaque_type));
ajs2a42e282004-12-08 18:43:03 +00001201 zlog_debug (" Opaque-ID 0x%x", opaque_id);
paul718e3742002-12-13 20:15:29 +00001202
ajs2a42e282004-12-08 18:43:03 +00001203 zlog_debug (" Opaque-Info: %u octets of data%s",
paul718e3742002-12-13 20:15:29 +00001204 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1205 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)");
1206 }
1207
1208 /* Call individual output functions. */
1209 if ((functab = ospf_opaque_functab_lookup (lsa)) != NULL)
1210 if (functab->show_opaque_info != NULL)
1211 (* functab->show_opaque_info)(vty, lsa);
1212
1213 return;
1214}
1215
1216void
1217ospf_opaque_lsa_dump (struct stream *s, u_int16_t length)
1218{
1219 struct ospf_lsa lsa;
1220
1221 lsa.data = (struct lsa_header *) STREAM_PNT (s);
1222 show_opaque_info_detail (NULL, &lsa);
1223 return;
1224}
1225
1226static int
1227ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa)
1228{
paul87d6f872004-09-24 08:01:38 +00001229 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001230 int rc = -1;
1231
1232 /*
1233 * Some Opaque-LSA user may want to monitor every LSA installation
1234 * into the LSDB, regardless with target LSA type.
1235 */
paul09e4efd2003-01-18 00:12:02 +00001236 funclist = ospf_opaque_wildcard_funclist;
1237 if (new_lsa_callback (funclist, lsa) != 0)
1238 goto out;
1239
paul718e3742002-12-13 20:15:29 +00001240 funclist = ospf_opaque_type9_funclist;
1241 if (new_lsa_callback (funclist, lsa) != 0)
1242 goto out;
1243
1244 funclist = ospf_opaque_type10_funclist;
1245 if (new_lsa_callback (funclist, lsa) != 0)
1246 goto out;
1247
1248 funclist = ospf_opaque_type11_funclist;
1249 if (new_lsa_callback (funclist, lsa) != 0)
1250 goto out;
1251
1252 rc = 0;
1253out:
1254 return rc;
1255}
1256
1257static int
1258ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa)
1259{
paul87d6f872004-09-24 08:01:38 +00001260 struct list *funclist;
paul718e3742002-12-13 20:15:29 +00001261 int rc = -1;
1262
1263 /*
1264 * Some Opaque-LSA user may want to monitor every LSA deletion
1265 * from the LSDB, regardless with target LSA type.
1266 */
paul09e4efd2003-01-18 00:12:02 +00001267 funclist = ospf_opaque_wildcard_funclist;
1268 if (del_lsa_callback (funclist, lsa) != 0)
1269 goto out;
1270
paul718e3742002-12-13 20:15:29 +00001271 funclist = ospf_opaque_type9_funclist;
1272 if (del_lsa_callback (funclist, lsa) != 0)
1273 goto out;
1274
1275 funclist = ospf_opaque_type10_funclist;
1276 if (del_lsa_callback (funclist, lsa) != 0)
1277 goto out;
1278
1279 funclist = ospf_opaque_type11_funclist;
1280 if (del_lsa_callback (funclist, lsa) != 0)
1281 goto out;
1282
1283 rc = 0;
1284out:
1285 return rc;
1286}
1287
1288/*------------------------------------------------------------------------*
1289 * Followings are Opaque-LSA origination/refresh management functions.
1290 *------------------------------------------------------------------------*/
1291
1292static int ospf_opaque_type9_lsa_originate (struct thread *t);
1293static int ospf_opaque_type10_lsa_originate (struct thread *t);
1294static int ospf_opaque_type11_lsa_originate (struct thread *t);
paul87d6f872004-09-24 08:01:38 +00001295static void ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg);
paul718e3742002-12-13 20:15:29 +00001296
1297void
1298ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0)
1299{
1300 struct ospf *top;
1301 struct ospf_area *area;
paul1eb8ef22005-04-07 07:30:20 +00001302 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001303 struct opaque_info_per_type *oipt;
1304 int delay = 0;
1305
1306 if ((top = oi_to_top (oi)) == NULL || (area = oi->area) == NULL)
1307 {
1308 zlog_warn ("ospf_opaque_lsa_originate_schedule: Invalid argument?");
1309 goto out;
1310 }
1311
1312 /* It may not a right time to schedule origination now. */
1313 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1314 {
1315 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001316 zlog_debug ("ospf_opaque_lsa_originate_schedule: Not operational.");
paul718e3742002-12-13 20:15:29 +00001317 goto out; /* This is not an error. */
1318 }
Paul Jakmae30677a2015-01-20 15:45:36 +00001319
paul718e3742002-12-13 20:15:29 +00001320 if (delay0 != NULL)
1321 delay = *delay0;
1322
1323 /*
1324 * There might be some entries that have been waiting for triggering
1325 * of per opaque-type re-origination get resumed.
1326 */
1327 ospf_opaque_lsa_reoriginate_resume ( oi->opaque_lsa_self, (void *) oi);
1328 ospf_opaque_lsa_reoriginate_resume (area->opaque_lsa_self, (void *) area);
1329 ospf_opaque_lsa_reoriginate_resume ( top->opaque_lsa_self, (void *) top);
1330
1331 /*
1332 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1333 */
1334 if (! list_isempty (ospf_opaque_type9_funclist)
1335 && list_isempty (oi->opaque_lsa_self)
1336 && oi->t_opaque_lsa_self == NULL)
1337 {
1338 if (IS_DEBUG_OSPF_EVENT)
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001339 zlog_debug ("Schedule Type-9 Opaque-LSA origination in %d ms later.", delay);
paul718e3742002-12-13 20:15:29 +00001340 oi->t_opaque_lsa_self =
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001341 thread_add_timer_msec (master, ospf_opaque_type9_lsa_originate, oi, delay);
1342 delay += top->min_ls_interval;
paul718e3742002-12-13 20:15:29 +00001343 }
1344
1345 if (! list_isempty (ospf_opaque_type10_funclist)
1346 && list_isempty (area->opaque_lsa_self)
1347 && area->t_opaque_lsa_self == NULL)
1348 {
1349 /*
1350 * One AREA may contain multiple OIs, but above 2nd and 3rd
1351 * conditions prevent from scheduling the originate function
1352 * again and again.
1353 */
1354 if (IS_DEBUG_OSPF_EVENT)
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001355 zlog_debug ("Schedule Type-10 Opaque-LSA origination in %d ms later.", delay);
paul718e3742002-12-13 20:15:29 +00001356 area->t_opaque_lsa_self =
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001357 thread_add_timer_msec (master, ospf_opaque_type10_lsa_originate,
paul718e3742002-12-13 20:15:29 +00001358 area, delay);
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001359 delay += top->min_ls_interval;
paul718e3742002-12-13 20:15:29 +00001360 }
1361
1362 if (! list_isempty (ospf_opaque_type11_funclist)
1363 && list_isempty (top->opaque_lsa_self)
1364 && top->t_opaque_lsa_self == NULL)
1365 {
1366 /*
1367 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1368 * conditions prevent from scheduling the originate function
1369 * again and again.
1370 */
1371 if (IS_DEBUG_OSPF_EVENT)
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001372 zlog_debug ("Schedule Type-11 Opaque-LSA origination in %d ms later.", delay);
paul718e3742002-12-13 20:15:29 +00001373 top->t_opaque_lsa_self =
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001374 thread_add_timer_msec (master, ospf_opaque_type11_lsa_originate,
paul718e3742002-12-13 20:15:29 +00001375 top, delay);
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001376 delay += top->min_ls_interval;
paul718e3742002-12-13 20:15:29 +00001377 }
1378
1379 /*
1380 * Following section treats a special situation that this node's
1381 * opaque capability has changed as "ON -> OFF -> ON".
1382 */
1383 if (! list_isempty (ospf_opaque_type9_funclist)
1384 && ! list_isempty (oi->opaque_lsa_self))
1385 {
paul1eb8ef22005-04-07 07:30:20 +00001386 for (ALL_LIST_ELEMENTS (oi->opaque_lsa_self, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001387 {
hasso0d85b992004-03-18 19:18:33 +00001388 /*
1389 * removed the test for
1390 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1391 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1392 * not being empty.
1393 */
paul1eb8ef22005-04-07 07:30:20 +00001394 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1395 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001396 continue;
1397
1398 ospf_opaque_lsa_reoriginate_schedule ((void *) oi,
1399 OSPF_OPAQUE_LINK_LSA, oipt->opaque_type);
1400 }
1401 }
1402
1403 if (! list_isempty (ospf_opaque_type10_funclist)
1404 && ! list_isempty (area->opaque_lsa_self))
1405 {
paul1eb8ef22005-04-07 07:30:20 +00001406 for (ALL_LIST_ELEMENTS (area->opaque_lsa_self, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001407 {
hasso0d85b992004-03-18 19:18:33 +00001408 /*
1409 * removed the test for
1410 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1411 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1412 * not being empty.
1413 */
paul1eb8ef22005-04-07 07:30:20 +00001414 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1415 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001416 continue;
1417
1418 ospf_opaque_lsa_reoriginate_schedule ((void *) area,
1419 OSPF_OPAQUE_AREA_LSA, oipt->opaque_type);
1420 }
1421 }
1422
1423 if (! list_isempty (ospf_opaque_type11_funclist)
1424 && ! list_isempty (top->opaque_lsa_self))
1425 {
paul1eb8ef22005-04-07 07:30:20 +00001426 for (ALL_LIST_ELEMENTS (top->opaque_lsa_self, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001427 {
hasso0d85b992004-03-18 19:18:33 +00001428 /*
1429 * removed the test for
1430 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1431 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1432 * not being empty.
1433 */
paul1eb8ef22005-04-07 07:30:20 +00001434 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1435 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
paul718e3742002-12-13 20:15:29 +00001436 continue;
1437
1438 ospf_opaque_lsa_reoriginate_schedule ((void *) top,
1439 OSPF_OPAQUE_AS_LSA, oipt->opaque_type);
1440 }
1441 }
1442
1443 if (delay0 != NULL)
1444 *delay0 = delay;
1445
1446out:
1447 return;
1448}
1449
1450static int
1451ospf_opaque_type9_lsa_originate (struct thread *t)
1452{
1453 struct ospf_interface *oi;
1454 int rc;
1455
1456 oi = THREAD_ARG (t);
1457 oi->t_opaque_lsa_self = NULL;
1458
1459 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001460 zlog_debug ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
paul718e3742002-12-13 20:15:29 +00001461 IF_NAME (oi));
1462
1463 rc = opaque_lsa_originate_callback (ospf_opaque_type9_funclist, oi);
1464
1465 return rc;
1466}
1467
1468static int
1469ospf_opaque_type10_lsa_originate (struct thread *t)
1470{
1471 struct ospf_area *area;
1472 int rc;
1473
1474 area = THREAD_ARG (t);
1475 area->t_opaque_lsa_self = NULL;
1476
1477 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001478 zlog_debug ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
paul718e3742002-12-13 20:15:29 +00001479 inet_ntoa (area->area_id));
1480
1481 rc = opaque_lsa_originate_callback (ospf_opaque_type10_funclist, area);
1482
1483 return rc;
1484}
1485
1486static int
1487ospf_opaque_type11_lsa_originate (struct thread *t)
1488{
1489 struct ospf *top;
1490 int rc;
1491
1492 top = THREAD_ARG (t);
1493 top->t_opaque_lsa_self = NULL;
1494
1495 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001496 zlog_debug ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
paul718e3742002-12-13 20:15:29 +00001497
1498 rc = opaque_lsa_originate_callback (ospf_opaque_type11_funclist, top);
1499
1500 return rc;
1501}
1502
1503static void
paul87d6f872004-09-24 08:01:38 +00001504ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg)
paul718e3742002-12-13 20:15:29 +00001505{
paul1eb8ef22005-04-07 07:30:20 +00001506 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001507 struct opaque_info_per_type *oipt;
1508 struct ospf_opaque_functab *functab;
1509
1510 if (listtop == NULL)
1511 goto out;
1512
1513 /*
1514 * Pickup oipt entries those which in SUSPEND status, and give
1515 * them a chance to start re-origination now.
1516 */
paul1eb8ef22005-04-07 07:30:20 +00001517 for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt))
paul718e3742002-12-13 20:15:29 +00001518 {
paul87d6f872004-09-24 08:01:38 +00001519 if (oipt->status != PROC_SUSPEND)
paul718e3742002-12-13 20:15:29 +00001520 continue;
1521
1522 oipt->status = PROC_NORMAL;
1523
1524 if ((functab = oipt->functab) == NULL
paul87d6f872004-09-24 08:01:38 +00001525 || functab->lsa_originator == NULL)
paul718e3742002-12-13 20:15:29 +00001526 continue;
1527
1528 if ((* functab->lsa_originator)(arg) != 0)
1529 {
1530 zlog_warn ("ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", oipt->opaque_type);
1531 continue;
1532 }
1533 }
1534
1535out:
1536 return;
1537}
1538
1539struct ospf_lsa *
1540ospf_opaque_lsa_install (struct ospf_lsa *lsa, int rt_recalc)
1541{
1542 struct ospf_lsa *new = NULL;
1543 struct opaque_info_per_type *oipt;
1544 struct opaque_info_per_id *oipi;
1545 struct ospf *top;
1546
1547 /* Don't take "rt_recalc" into consideration for now. *//* XXX */
1548
1549 if (! IS_LSA_SELF (lsa))
1550 {
1551 new = lsa; /* Don't touch this LSA. */
1552 goto out;
1553 }
1554
1555 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
ajs2a42e282004-12-08 18:43:03 +00001556 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 +00001557
1558 /* Replace the existing lsa with the new one. */
1559 if ((oipt = lookup_opaque_info_by_type (lsa)) != NULL
paul87d6f872004-09-24 08:01:38 +00001560 && (oipi = lookup_opaque_info_by_id (oipt, lsa)) != NULL)
paul718e3742002-12-13 20:15:29 +00001561 {
Paul Jakma1fe6ed32006-07-26 09:37:26 +00001562 ospf_lsa_unlock (&oipi->lsa);
paul718e3742002-12-13 20:15:29 +00001563 oipi->lsa = ospf_lsa_lock (lsa);
1564 }
1565 /* Register the new lsa entry and get its control info. */
1566 else
1567 if ((oipi = register_opaque_lsa (lsa)) == NULL)
1568 {
1569 zlog_warn ("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1570 goto out;
1571 }
1572
1573 /*
1574 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1575 * for periodic refresh of self-originated Opaque-LSAs.
1576 */
1577 switch (lsa->data->type)
1578 {
1579 case OSPF_OPAQUE_LINK_LSA:
paul09e4efd2003-01-18 00:12:02 +00001580 if ((top = oi_to_top (lsa->oi)) == NULL)
1581 {
1582 /* Above conditions must have passed. */
1583 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1584 goto out;
1585 }
1586 break;
paul718e3742002-12-13 20:15:29 +00001587 case OSPF_OPAQUE_AREA_LSA:
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 case OSPF_OPAQUE_AS_LSA:
paul020709f2003-04-04 02:44:16 +00001596 top = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001597 if (lsa->area != NULL && (top = lsa->area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001598 {
1599 /* Above conditions must have passed. */
1600 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1601 goto out;
1602 }
1603 break;
1604 default:
1605 zlog_warn ("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", lsa->data->type);
1606 goto out;
1607 }
1608
1609 ospf_refresher_register_lsa (top, lsa);
1610 new = lsa;
1611
1612out:
1613 return new;
1614}
1615
Paul Jakmad71ea652011-03-22 15:23:55 +00001616struct ospf_lsa *
paul718e3742002-12-13 20:15:29 +00001617ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
1618{
paul020709f2003-04-04 02:44:16 +00001619 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001620 struct ospf_opaque_functab *functab;
Paul Jakmad71ea652011-03-22 15:23:55 +00001621 struct ospf_lsa *new = NULL;
1622
paul020709f2003-04-04 02:44:16 +00001623 ospf = ospf_lookup ();
1624
paul718e3742002-12-13 20:15:29 +00001625 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL
paul87d6f872004-09-24 08:01:38 +00001626 || functab->lsa_refresher == NULL)
paul718e3742002-12-13 20:15:29 +00001627 {
1628 /*
1629 * Though this LSA seems to have originated on this node, the
1630 * handling module for this "lsa-type and opaque-type" was
1631 * already deleted sometime ago.
1632 * Anyway, this node still has a responsibility to flush this
1633 * LSA from the routing domain.
1634 */
1635 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001636 zlog_debug ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id));
paul718e3742002-12-13 20:15:29 +00001637
1638 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
Paul Jakma02d942c2010-01-24 23:36:20 +00001639 ospf_lsa_flush (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00001640 }
1641 else
Paul Jakmad71ea652011-03-22 15:23:55 +00001642 new = (* functab->lsa_refresher)(lsa);
paul718e3742002-12-13 20:15:29 +00001643
Paul Jakmad71ea652011-03-22 15:23:55 +00001644 return new;
paul718e3742002-12-13 20:15:29 +00001645}
1646
1647/*------------------------------------------------------------------------*
1648 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1649 * triggered by external interventions (vty session, signaling, etc).
1650 *------------------------------------------------------------------------*/
1651
1652#define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
1653 if (!(T)) \
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001654 (T) = thread_add_timer_msec (master, (F), (L), (V))
paul718e3742002-12-13 20:15:29 +00001655
1656static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type);
1657static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t);
1658static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t);
1659static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t);
1660static int ospf_opaque_lsa_refresh_timer (struct thread *t);
1661
1662void
1663ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
1664 u_char lsa_type, u_char opaque_type)
1665{
1666 struct ospf *top;
1667 struct ospf_area dummy, *area = NULL;
1668 struct ospf_interface *oi = NULL;
1669
1670 struct ospf_lsa *lsa;
1671 struct opaque_info_per_type *oipt;
paul87d6f872004-09-24 08:01:38 +00001672 int (*func) (struct thread * t) = NULL;
paul718e3742002-12-13 20:15:29 +00001673 int delay;
1674
1675 switch (lsa_type)
1676 {
1677 case OSPF_OPAQUE_LINK_LSA:
1678 if ((oi = (struct ospf_interface *) lsa_type_dependent) == NULL)
1679 {
paul87d6f872004-09-24 08:01:38 +00001680 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1681 " Type-9 Opaque-LSA: Invalid parameter?");
1682 goto out;
paul718e3742002-12-13 20:15:29 +00001683 }
1684 if ((top = oi_to_top (oi)) == NULL)
1685 {
paul87d6f872004-09-24 08:01:38 +00001686 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1687 IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001688 goto out;
1689 }
paul87d6f872004-09-24 08:01:38 +00001690 if (!list_isempty (ospf_opaque_type9_funclist)
1691 && list_isempty (oi->opaque_lsa_self)
1692 && oi->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001693 {
paul87d6f872004-09-24 08:01:38 +00001694 zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u):"
1695 " Common origination for OI(%s) has already started",
1696 opaque_type, IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001697 goto out;
1698 }
1699 func = ospf_opaque_type9_lsa_reoriginate_timer;
1700 break;
1701 case OSPF_OPAQUE_AREA_LSA:
1702 if ((area = (struct ospf_area *) lsa_type_dependent) == NULL)
1703 {
paul87d6f872004-09-24 08:01:38 +00001704 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1705 " Type-10 Opaque-LSA: Invalid parameter?");
paul718e3742002-12-13 20:15:29 +00001706 goto out;
1707 }
paul68980082003-03-25 05:07:42 +00001708 if ((top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001709 {
paul87d6f872004-09-24 08:01:38 +00001710 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1711 " AREA(%s) -> TOP?", inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001712 goto out;
1713 }
paul87d6f872004-09-24 08:01:38 +00001714 if (!list_isempty (ospf_opaque_type10_funclist)
1715 && list_isempty (area->opaque_lsa_self)
1716 && area->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001717 {
paul87d6f872004-09-24 08:01:38 +00001718 zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u):"
1719 " Common origination for AREA(%s) has already started",
1720 opaque_type, inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001721 goto out;
1722 }
1723 func = ospf_opaque_type10_lsa_reoriginate_timer;
1724 break;
1725 case OSPF_OPAQUE_AS_LSA:
1726 if ((top = (struct ospf *) lsa_type_dependent) == NULL)
1727 {
paul87d6f872004-09-24 08:01:38 +00001728 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1729 " Type-11 Opaque-LSA: Invalid parameter?");
1730 goto out;
paul718e3742002-12-13 20:15:29 +00001731 }
paul87d6f872004-09-24 08:01:38 +00001732 if (!list_isempty (ospf_opaque_type11_funclist)
1733 && list_isempty (top->opaque_lsa_self)
1734 && top->t_opaque_lsa_self != NULL)
paul718e3742002-12-13 20:15:29 +00001735 {
paul87d6f872004-09-24 08:01:38 +00001736 zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u):"
1737 " Common origination has already started", opaque_type);
paul718e3742002-12-13 20:15:29 +00001738 goto out;
1739 }
1740
1741 /* Fake "area" to pass "ospf" to a lookup function later. */
paul68980082003-03-25 05:07:42 +00001742 dummy.ospf = top;
paul718e3742002-12-13 20:15:29 +00001743 area = &dummy;
1744
1745 func = ospf_opaque_type11_lsa_reoriginate_timer;
1746 break;
1747 default:
paul87d6f872004-09-24 08:01:38 +00001748 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1749 " Unexpected LSA-type(%u)",
1750 lsa_type);
paul718e3742002-12-13 20:15:29 +00001751 goto out;
1752 }
1753
1754 /* It may not a right time to schedule reorigination now. */
paul87d6f872004-09-24 08:01:38 +00001755 if (!CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
paul718e3742002-12-13 20:15:29 +00001756 {
1757 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001758 zlog_debug ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
paul87d6f872004-09-24 08:01:38 +00001759 goto out; /* This is not an error. */
paul718e3742002-12-13 20:15:29 +00001760 }
Paul Jakmae30677a2015-01-20 15:45:36 +00001761
paul718e3742002-12-13 20:15:29 +00001762 /* Generate a dummy lsa to be passed for a lookup function. */
1763 lsa = pseudo_lsa (oi, area, lsa_type, opaque_type);
1764
1765 if ((oipt = lookup_opaque_info_by_type (lsa)) == NULL)
1766 {
1767 struct ospf_opaque_functab *functab;
1768 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL)
1769 {
paul87d6f872004-09-24 08:01:38 +00001770 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1771 " No associated function?: lsa_type(%u),"
1772 " opaque_type(%u)",
1773 lsa_type, opaque_type);
paul718e3742002-12-13 20:15:29 +00001774 goto out;
1775 }
1776 if ((oipt = register_opaque_info_per_type (functab, lsa)) == NULL)
1777 {
paul87d6f872004-09-24 08:01:38 +00001778 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1779 " Cannot get a control info?: lsa_type(%u),"
1780 " opaque_type(%u)",
1781 lsa_type, opaque_type);
paul718e3742002-12-13 20:15:29 +00001782 goto out;
1783 }
1784 }
1785
1786 if (oipt->t_opaque_lsa_self != NULL)
1787 {
1788 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001789 zlog_debug ("Type-%u Opaque-LSA has already scheduled to"
paul87d6f872004-09-24 08:01:38 +00001790 " RE-ORIGINATE: [opaque-type=%u]",
1791 lsa_type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
paul718e3742002-12-13 20:15:29 +00001792 goto out;
1793 }
1794
1795 /*
1796 * Different from initial origination time, in which various conditions
1797 * (opaque capability, neighbor status etc) are assured by caller of
1798 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1799 * it is highly possible that these conditions might not be satisfied
1800 * at the time of re-origination function is to be called.
1801 */
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001802 delay = top->min_ls_interval; /* XXX */
paul718e3742002-12-13 20:15:29 +00001803
1804 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001805 zlog_debug ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001806 " ms later: [opaque-type=%u]",
paul87d6f872004-09-24 08:01:38 +00001807 lsa_type, delay,
1808 GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
paul718e3742002-12-13 20:15:29 +00001809
1810 OSPF_OPAQUE_TIMER_ON (oipt->t_opaque_lsa_self, func, oipt, delay);
1811
1812out:
1813 return;
1814}
1815
1816static struct ospf_lsa *
1817pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area,
1818 u_char lsa_type, u_char opaque_type)
1819{
1820 static struct ospf_lsa lsa = { 0 };
1821 static struct lsa_header lsah = { 0 };
1822 u_int32_t tmp;
1823
1824 lsa.oi = oi;
1825 lsa.area = area;
1826 lsa.data = &lsah;
1827
1828 lsah.type = lsa_type;
1829 tmp = SET_OPAQUE_LSID (opaque_type, 0); /* Opaque-ID is unused here. */
1830 lsah.id.s_addr = htonl (tmp);
1831
1832 return &lsa;
1833}
1834
1835static int
1836ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t)
1837{
1838 struct opaque_info_per_type *oipt;
1839 struct ospf_opaque_functab *functab;
1840 struct ospf *top;
1841 struct ospf_interface *oi;
1842 int rc = -1;
1843
1844 oipt = THREAD_ARG (t);
1845 oipt->t_opaque_lsa_self = NULL;
1846
1847 if ((functab = oipt->functab) == NULL
1848 || functab->lsa_originator == NULL)
1849 {
1850 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1851 goto out;
1852 }
1853
1854 oi = (struct ospf_interface *) oipt->owner;
1855 if ((top = oi_to_top (oi)) == NULL)
1856 {
1857 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1858 goto out;
1859 }
1860
1861 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)
1862 || ! ospf_if_is_enable (oi)
paul68980082003-03-25 05:07:42 +00001863 || ospf_nbr_count_opaque_capable (oi) == 0)
paul718e3742002-12-13 20:15:29 +00001864 {
1865 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001866 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 +00001867
1868 oipt->status = PROC_SUSPEND;
1869 rc = 0;
1870 goto out;
1871 }
1872
1873 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001874 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 +00001875
1876 rc = (* functab->lsa_originator)(oi);
1877out:
1878 return rc;
1879}
1880
1881static int
1882ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t)
1883{
1884 struct opaque_info_per_type *oipt;
1885 struct ospf_opaque_functab *functab;
paul1eb8ef22005-04-07 07:30:20 +00001886 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001887 struct ospf *top;
1888 struct ospf_area *area;
1889 struct ospf_interface *oi;
1890 int n, rc = -1;
1891
1892 oipt = THREAD_ARG (t);
1893 oipt->t_opaque_lsa_self = NULL;
1894
1895 if ((functab = oipt->functab) == NULL
1896 || functab->lsa_originator == NULL)
1897 {
1898 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1899 goto out;
1900 }
1901
1902 area = (struct ospf_area *) oipt->owner;
paul68980082003-03-25 05:07:42 +00001903 if (area == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00001904 {
1905 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1906 goto out;
1907 }
1908
1909 /* There must be at least one "opaque-capable, full-state" neighbor. */
1910 n = 0;
paul1eb8ef22005-04-07 07:30:20 +00001911 for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi))
paul718e3742002-12-13 20:15:29 +00001912 {
paul68980082003-03-25 05:07:42 +00001913 if ((n = ospf_nbr_count_opaque_capable (oi)) > 0)
paul718e3742002-12-13 20:15:29 +00001914 break;
1915 }
1916
1917 if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1918 {
1919 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001920 zlog_debug ("Suspend re-origination of Type-10 Opaque-LSAs"
paul87d6f872004-09-24 08:01:38 +00001921 " (opaque-type=%u) for a while...",
1922 oipt->opaque_type);
paul718e3742002-12-13 20:15:29 +00001923
1924 oipt->status = PROC_SUSPEND;
1925 rc = 0;
1926 goto out;
1927 }
1928
1929 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001930 zlog_debug ("Timer[Type10-LSA]: Re-originate Opaque-LSAs"
paul87d6f872004-09-24 08:01:38 +00001931 " (opaque-type=%u) for Area %s",
1932 oipt->opaque_type, inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001933
1934 rc = (* functab->lsa_originator)(area);
1935out:
1936 return rc;
1937}
1938
1939static int
1940ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t)
1941{
1942 struct opaque_info_per_type *oipt;
1943 struct ospf_opaque_functab *functab;
1944 struct ospf *top;
1945 int rc = -1;
1946
1947 oipt = THREAD_ARG (t);
1948 oipt->t_opaque_lsa_self = NULL;
1949
1950 if ((functab = oipt->functab) == NULL
paul87d6f872004-09-24 08:01:38 +00001951 || functab->lsa_originator == NULL)
paul718e3742002-12-13 20:15:29 +00001952 {
paul87d6f872004-09-24 08:01:38 +00001953 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer:"
1954 " No associated function?");
paul718e3742002-12-13 20:15:29 +00001955 goto out;
1956 }
1957
1958 if ((top = (struct ospf *) oipt->owner) == NULL)
1959 {
1960 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1961 goto out;
1962 }
1963
1964 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1965 {
1966 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001967 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 +00001968
1969 oipt->status = PROC_SUSPEND;
1970 rc = 0;
1971 goto out;
1972 }
1973
1974 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001975 zlog_debug ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type);
paul718e3742002-12-13 20:15:29 +00001976
1977 rc = (* functab->lsa_originator)(top);
1978out:
1979 return rc;
1980}
1981
paul718e3742002-12-13 20:15:29 +00001982void
1983ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
1984{
1985 struct opaque_info_per_type *oipt;
1986 struct opaque_info_per_id *oipi;
1987 struct ospf_lsa *lsa;
Olivier Dugeon29a14012016-04-19 18:42:40 +02001988 struct ospf *top;
paul718e3742002-12-13 20:15:29 +00001989 int delay;
1990
1991 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
1992 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
1993 {
1994 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
1995 goto out;
1996 }
1997
1998 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
1999 if ((lsa = oipi->lsa) == NULL)
2000 {
2001 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
2002 goto out;
2003 }
2004
2005 if (oipi->t_opaque_lsa_self != NULL)
2006 {
2007 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002008 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 +00002009 goto out;
2010 }
2011
2012 /* Delete this lsa from neighbor retransmit-list. */
2013 switch (lsa->data->type)
2014 {
2015 case OSPF_OPAQUE_LINK_LSA:
2016 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002017 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002018 break;
2019 case OSPF_OPAQUE_AS_LSA:
Olivier Dugeon29a14012016-04-19 18:42:40 +02002020 top = ospf_lookup ();
2021 if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
2022 top = lsa0->area->ospf;
2023 ospf_ls_retransmit_delete_nbr_as (top, lsa);
paul718e3742002-12-13 20:15:29 +00002024 break;
2025 default:
2026 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2027 goto out;
2028 }
2029
2030 delay = ospf_lsa_refresh_delay (lsa);
2031
2032 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002033 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 +00002034
2035 OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self,
Michael Rossberg2ef762e2015-07-27 07:56:25 +02002036 ospf_opaque_lsa_refresh_timer, oipi, delay * 1000);
paul718e3742002-12-13 20:15:29 +00002037out:
2038 return;
2039}
2040
2041static int
2042ospf_opaque_lsa_refresh_timer (struct thread *t)
2043{
2044 struct opaque_info_per_id *oipi;
2045 struct ospf_opaque_functab *functab;
2046 struct ospf_lsa *lsa;
2047
2048 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002049 zlog_debug ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
paul718e3742002-12-13 20:15:29 +00002050
2051 oipi = THREAD_ARG (t);
2052 oipi->t_opaque_lsa_self = NULL;
2053
2054 if ((lsa = oipi->lsa) != NULL)
2055 if ((functab = oipi->opqctl_type->functab) != NULL)
2056 if (functab->lsa_refresher != NULL)
2057 (* functab->lsa_refresher)(lsa);
2058
2059 return 0;
2060}
2061
2062void
2063ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
2064{
2065 struct opaque_info_per_type *oipt;
2066 struct opaque_info_per_id *oipi;
2067 struct ospf_lsa *lsa;
Olivier Dugeon29a14012016-04-19 18:42:40 +02002068 struct ospf *top;
2069
2070 top = ospf_lookup ();
paul718e3742002-12-13 20:15:29 +00002071
2072 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
2073 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
2074 {
2075 zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2076 goto out;
2077 }
2078
2079 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2080 if ((lsa = oipi->lsa) == NULL)
2081 {
2082 zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
2083 goto out;
2084 }
2085
2086 /* Delete this lsa from neighbor retransmit-list. */
2087 switch (lsa->data->type)
2088 {
2089 case OSPF_OPAQUE_LINK_LSA:
2090 case OSPF_OPAQUE_AREA_LSA:
paul68980082003-03-25 05:07:42 +00002091 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
paul718e3742002-12-13 20:15:29 +00002092 break;
2093 case OSPF_OPAQUE_AS_LSA:
Olivier Dugeon29a14012016-04-19 18:42:40 +02002094 if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
2095 top = lsa0->area->ospf;
2096 ospf_ls_retransmit_delete_nbr_as (top, lsa);
paul718e3742002-12-13 20:15:29 +00002097 break;
2098 default:
2099 zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2100 goto out;
2101 }
2102
2103 /* Dequeue listnode entry from the list. */
2104 listnode_delete (oipt->id_list, oipi);
2105
2106 /* Avoid misjudgement in the next lookup. */
2107 if (listcount (oipt->id_list) == 0)
2108 oipt->id_list->head = oipt->id_list->tail = NULL;
2109
2110 /* Disassociate internal control information with the given lsa. */
paul718e3742002-12-13 20:15:29 +00002111 free_opaque_info_per_id ((void *) oipi);
2112
2113 /* Force given lsa's age to MaxAge. */
2114 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2115
2116 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002117 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 +00002118
2119 /* This lsa will be flushed and removed eventually. */
Olivier Dugeon29a14012016-04-19 18:42:40 +02002120 ospf_lsa_flush (top, lsa);
paul718e3742002-12-13 20:15:29 +00002121
2122out:
2123 return;
2124}
2125
paul718e3742002-12-13 20:15:29 +00002126void
paul87d6f872004-09-24 08:01:38 +00002127ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr,
paul69310a62005-05-11 18:09:59 +00002128 struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002129{
2130 struct ospf *top;
Paul Jakmae30677a2015-01-20 15:45:36 +00002131
paul718e3742002-12-13 20:15:29 +00002132 if ((top = oi_to_top (nbr->oi)) == NULL)
Paul Jakma1fe6ed32006-07-26 09:37:26 +00002133 return;
paul718e3742002-12-13 20:15:29 +00002134
paul69310a62005-05-11 18:09:59 +00002135 /*
2136 * Since these LSA entries are not yet installed into corresponding
2137 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2138 */
2139 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2140 switch (lsa->data->type)
paul718e3742002-12-13 20:15:29 +00002141 {
paul69310a62005-05-11 18:09:59 +00002142 case OSPF_OPAQUE_LINK_LSA:
paul69310a62005-05-11 18:09:59 +00002143 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2144 break;
2145 case OSPF_OPAQUE_AREA_LSA:
paul69310a62005-05-11 18:09:59 +00002146 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2147 break;
2148 case OSPF_OPAQUE_AS_LSA:
paul69310a62005-05-11 18:09:59 +00002149 ospf_flood_through_as (top, NULL/*inbr*/, lsa);
2150 break;
2151 default:
2152 zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
Paul Jakma1fe6ed32006-07-26 09:37:26 +00002153 return;
paul718e3742002-12-13 20:15:29 +00002154 }
Paul Jakmae30677a2015-01-20 15:45:36 +00002155 ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */
paul718e3742002-12-13 20:15:29 +00002156}
2157
paul718e3742002-12-13 20:15:29 +00002158/*------------------------------------------------------------------------*
2159 * Followings are util functions; probably be used by Opaque-LSAs only...
2160 *------------------------------------------------------------------------*/
2161
paul718e3742002-12-13 20:15:29 +00002162struct ospf *
2163oi_to_top (struct ospf_interface *oi)
2164{
2165 struct ospf *top = NULL;
2166 struct ospf_area *area;
2167
paul68980082003-03-25 05:07:42 +00002168 if (oi == NULL || (area = oi->area) == NULL || (top = area->ospf) == NULL)
paul718e3742002-12-13 20:15:29 +00002169 zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");
2170
2171 return top;
2172}
2173