]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_opaque.c
Merge pull request #478 from opensourcerouting/test-extension
[mirror_frr.git] / ospfd / ospf_opaque.c
CommitLineData
718e3744 1/*
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
718e3744 24#include <zebra.h>
718e3744 25
26#include "linklist.h"
27#include "prefix.h"
28#include "if.h"
29#include "table.h"
30#include "memory.h"
31#include "command.h"
32#include "vty.h"
33#include "stream.h"
34#include "log.h"
35#include "thread.h"
36#include "hash.h"
37#include "sockunion.h" /* for inet_aton() */
38
39#include "ospfd/ospfd.h"
40#include "ospfd/ospf_interface.h"
41#include "ospfd/ospf_ism.h"
42#include "ospfd/ospf_asbr.h"
43#include "ospfd/ospf_lsa.h"
44#include "ospfd/ospf_lsdb.h"
45#include "ospfd/ospf_neighbor.h"
46#include "ospfd/ospf_nsm.h"
47#include "ospfd/ospf_flood.h"
48#include "ospfd/ospf_packet.h"
49#include "ospfd/ospf_spf.h"
50#include "ospfd/ospf_dump.h"
51#include "ospfd/ospf_route.h"
52#include "ospfd/ospf_ase.h"
53#include "ospfd/ospf_zebra.h"
54
fc7948fa
DL
55DEFINE_MTYPE_STATIC(OSPFD, OSPF_OPAQUE_FUNCTAB, "OSPF opaque function table")
56DEFINE_MTYPE_STATIC(OSPFD, OPAQUE_INFO_PER_TYPE, "OSPF opaque per-type info")
57DEFINE_MTYPE_STATIC(OSPFD, OPAQUE_INFO_PER_ID, "OSPF opaque per-ID info")
58
718e3744 59/*------------------------------------------------------------------------*
60 * Followings are initialize/terminate functions for Opaque-LSAs handling.
61 *------------------------------------------------------------------------*/
62
718e3744 63#include "ospfd/ospf_te.h"
0ef4bcdc 64#include "ospfd/ospf_ri.h"
718e3744 65
283ae334 66#ifdef SUPPORT_OSPF_API
67int ospf_apiserver_init (void);
68void ospf_apiserver_term (void);
f4d58ce5 69/* Init apiserver? It's disabled by default. */
70int ospf_apiserver_enable;
283ae334 71#endif /* SUPPORT_OSPF_API */
72
718e3744 73static 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
718e3744 87 if (ospf_mpls_te_init () != 0)
88 exit (1);
718e3744 89
0ef4bcdc
OD
90 if (ospf_router_info_init () != 0)
91 exit (1);
92
283ae334 93#ifdef SUPPORT_OSPF_API
c3abdb72 94 if ((ospf_apiserver_enable) && (ospf_apiserver_init () != 0))
283ae334 95 exit (1);
96#endif /* SUPPORT_OSPF_API */
97
718e3744 98 return;
99}
100
101void
102ospf_opaque_term (void)
103{
718e3744 104 ospf_mpls_te_term ();
718e3744 105
0ef4bcdc
OD
106 ospf_router_info_term ();
107
283ae334 108#ifdef SUPPORT_OSPF_API
109 ospf_apiserver_term ();
110#endif /* SUPPORT_OSPF_API */
111
718e3744 112 ospf_opaque_funclist_term ();
113 return;
114}
115
116int
117ospf_opaque_type9_lsa_init (struct ospf_interface *oi)
118{
119 if (oi->opaque_lsa_self != NULL)
120 list_delete (oi->opaque_lsa_self);
121
122 oi->opaque_lsa_self = list_new ();
123 oi->opaque_lsa_self->del = free_opaque_info_per_type;
124 oi->t_opaque_lsa_self = NULL;
125 return 0;
126}
127
128void
129ospf_opaque_type9_lsa_term (struct ospf_interface *oi)
130{
131 OSPF_TIMER_OFF (oi->t_opaque_lsa_self);
132 if (oi->opaque_lsa_self != NULL)
133 list_delete (oi->opaque_lsa_self);
134 oi->opaque_lsa_self = NULL;
135 return;
136}
137
138int
139ospf_opaque_type10_lsa_init (struct ospf_area *area)
140{
141 if (area->opaque_lsa_self != NULL)
142 list_delete (area->opaque_lsa_self);
143
144 area->opaque_lsa_self = list_new ();
145 area->opaque_lsa_self->del = free_opaque_info_per_type;
146 area->t_opaque_lsa_self = NULL;
147
148#ifdef MONITOR_LSDB_CHANGE
149 area->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
150 area->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
151#endif /* MONITOR_LSDB_CHANGE */
152 return 0;
153}
154
155void
156ospf_opaque_type10_lsa_term (struct ospf_area *area)
157{
158#ifdef MONITOR_LSDB_CHANGE
159 area->lsdb->new_lsa_hook =
160 area->lsdb->del_lsa_hook = NULL;
161#endif /* MONITOR_LSDB_CHANGE */
162
163 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
164 if (area->opaque_lsa_self != NULL)
165 list_delete (area->opaque_lsa_self);
166 area->opaque_lsa_self = NULL;
167 return;
168}
169
170int
171ospf_opaque_type11_lsa_init (struct ospf *top)
172{
173 if (top->opaque_lsa_self != NULL)
174 list_delete (top->opaque_lsa_self);
175
176 top->opaque_lsa_self = list_new ();
177 top->opaque_lsa_self->del = free_opaque_info_per_type;
178 top->t_opaque_lsa_self = NULL;
179
180#ifdef MONITOR_LSDB_CHANGE
181 top->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
182 top->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
183#endif /* MONITOR_LSDB_CHANGE */
184 return 0;
185}
186
187void
188ospf_opaque_type11_lsa_term (struct ospf *top)
189{
190#ifdef MONITOR_LSDB_CHANGE
191 top->lsdb->new_lsa_hook =
192 top->lsdb->del_lsa_hook = NULL;
193#endif /* MONITOR_LSDB_CHANGE */
194
195 OSPF_TIMER_OFF (top->t_opaque_lsa_self);
196 if (top->opaque_lsa_self != NULL)
197 list_delete (top->opaque_lsa_self);
198 top->opaque_lsa_self = NULL;
199 return;
200}
201
202static const char *
203ospf_opaque_type_name (u_char opaque_type)
204{
205 const char *name = "Unknown";
206
207 switch (opaque_type)
208 {
209 case OPAQUE_TYPE_WILDCARD: /* This is a special assignment! */
210 name = "Wildcard";
211 break;
212 case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA:
213 name = "Traffic Engineering LSA";
214 break;
215 case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC:
216 name = "Sycamore optical topology description";
217 break;
218 case OPAQUE_TYPE_GRACE_LSA:
219 name = "Grace-LSA";
220 break;
16f1b9ee
OD
221 case OPAQUE_TYPE_INTER_AS_LSA:
222 name = "Inter-AS TE-v2 LSA";
223 break;
0ef4bcdc
OD
224 case OPAQUE_TYPE_ROUTER_INFORMATION_LSA:
225 name = "Router Information LSA";
226 break;
718e3744 227 default:
228 if (OPAQUE_TYPE_RANGE_UNASSIGNED (opaque_type))
229 name = "Unassigned";
0798cee3
AC
230 else
231 {
232 u_int32_t bigger_range = opaque_type;
233 /*
234 * Get around type-limits warning: comparison is always true due to limited range of data type
235 */
236 if (OPAQUE_TYPE_RANGE_RESERVED (bigger_range))
237 name = "Private/Experimental";
238 }
718e3744 239 break;
240 }
241 return name;
242}
243
244/*------------------------------------------------------------------------*
245 * Followings are management functions to store user specified callbacks.
246 *------------------------------------------------------------------------*/
247
248struct opaque_info_per_type; /* Forward declaration. */
249
250struct ospf_opaque_functab
251{
252 u_char opaque_type;
253 struct opaque_info_per_type *oipt;
254
255 int (* new_if_hook)(struct interface *ifp);
256 int (* del_if_hook)(struct interface *ifp);
257 void (* ism_change_hook)(struct ospf_interface *oi, int old_status);
258 void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status);
259 void (* config_write_router)(struct vty *vty);
260 void (* config_write_if )(struct vty *vty, struct interface *ifp);
261 void (* config_write_debug )(struct vty *vty);
262 void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa);
263 int (* lsa_originator)(void *arg);
d71ea652 264 struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa);
718e3744 265 int (* new_lsa_hook)(struct ospf_lsa *lsa);
266 int (* del_lsa_hook)(struct ospf_lsa *lsa);
267};
268
87d6f87a 269/* Handle LSA-9/10/11 altogether. */
270static struct list *ospf_opaque_wildcard_funclist;
271static struct list *ospf_opaque_type9_funclist;
272static struct list *ospf_opaque_type10_funclist;
273static struct list *ospf_opaque_type11_funclist;
718e3744 274
275static void
276ospf_opaque_del_functab (void *val)
277{
278 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, val);
279 return;
280}
281
282static void
283ospf_opaque_funclist_init (void)
284{
87d6f87a 285 struct list *funclist;
718e3744 286
09e4efdc 287 funclist = ospf_opaque_wildcard_funclist = list_new ();
288 funclist->del = ospf_opaque_del_functab;
289
718e3744 290 funclist = ospf_opaque_type9_funclist = list_new ();
291 funclist->del = ospf_opaque_del_functab;
292
293 funclist = ospf_opaque_type10_funclist = list_new ();
294 funclist->del = ospf_opaque_del_functab;
295
296 funclist = ospf_opaque_type11_funclist = list_new ();
297 funclist->del = ospf_opaque_del_functab;
298 return;
299}
300
301static void
302ospf_opaque_funclist_term (void)
303{
87d6f87a 304 struct list *funclist;
718e3744 305
09e4efdc 306 funclist = ospf_opaque_wildcard_funclist;
307 list_delete (funclist);
308
718e3744 309 funclist = ospf_opaque_type9_funclist;
310 list_delete (funclist);
311
312 funclist = ospf_opaque_type10_funclist;
313 list_delete (funclist);
314
315 funclist = ospf_opaque_type11_funclist;
316 list_delete (funclist);
317 return;
318}
319
87d6f87a 320static struct list *
718e3744 321ospf_get_opaque_funclist (u_char lsa_type)
322{
87d6f87a 323 struct list *funclist = NULL;
718e3744 324
325 switch (lsa_type)
326 {
09e4efdc 327 case OPAQUE_TYPE_WILDCARD:
328 /* XXX
329 * This is an ugly trick to handle type-9/10/11 LSA altogether.
330 * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor
331 * an officially assigned opaque-type.
332 * Though it is possible that the value might be officially used
333 * in the future, we use it internally as a special label, for now.
334 */
335 funclist = ospf_opaque_wildcard_funclist;
336 break;
718e3744 337 case OSPF_OPAQUE_LINK_LSA:
338 funclist = ospf_opaque_type9_funclist;
339 break;
340 case OSPF_OPAQUE_AREA_LSA:
341 funclist = ospf_opaque_type10_funclist;
342 break;
343 case OSPF_OPAQUE_AS_LSA:
344 funclist = ospf_opaque_type11_funclist;
345 break;
346 default:
347 zlog_warn ("ospf_get_opaque_funclist: Unexpected LSA-type(%u)", lsa_type);
348 break;
349 }
350 return funclist;
351}
352
87d6f87a 353/* XXX: such a huge argument list can /not/ be healthy... */
718e3744 354int
355ospf_register_opaque_functab (
356 u_char lsa_type,
357 u_char opaque_type,
358 int (* new_if_hook)(struct interface *ifp),
359 int (* del_if_hook)(struct interface *ifp),
360 void (* ism_change_hook)(struct ospf_interface *oi, int old_status),
361 void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status),
362 void (* config_write_router)(struct vty *vty),
363 void (* config_write_if )(struct vty *vty, struct interface *ifp),
364 void (* config_write_debug )(struct vty *vty),
365 void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa),
366 int (* lsa_originator)(void *arg),
d71ea652 367 struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa),
718e3744 368 int (* new_lsa_hook)(struct ospf_lsa *lsa),
369 int (* del_lsa_hook)(struct ospf_lsa *lsa))
370{
87d6f87a 371 struct list *funclist;
718e3744 372 struct ospf_opaque_functab *new;
373 int rc = -1;
374
375 if ((funclist = ospf_get_opaque_funclist (lsa_type)) == NULL)
376 {
87d6f87a 377 zlog_warn ("ospf_register_opaque_functab: Cannot get funclist"
378 " for Type-%u LSAs?",
379 lsa_type);
718e3744 380 goto out;
381 }
382 else
383 {
1eb8ef25 384 struct listnode *node, *nnode;
718e3744 385 struct ospf_opaque_functab *functab;
87d6f87a 386
1eb8ef25 387 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
87d6f87a 388 if (functab->opaque_type == opaque_type)
389 {
390 zlog_warn ("ospf_register_opaque_functab: Duplicated entry?:"
391 " lsa_type(%u), opaque_type(%u)",
392 lsa_type, opaque_type);
393 goto out;
394 }
718e3744 395 }
396
397 if ((new = XCALLOC (MTYPE_OSPF_OPAQUE_FUNCTAB,
398 sizeof (struct ospf_opaque_functab))) == NULL)
399 {
87d6f87a 400 zlog_warn ("ospf_register_opaque_functab: XMALLOC: %s",
6099b3b5 401 safe_strerror (errno));
718e3744 402 goto out;
403 }
404
405 new->opaque_type = opaque_type;
406 new->oipt = NULL;
407 new->new_if_hook = new_if_hook;
408 new->del_if_hook = del_if_hook;
409 new->ism_change_hook = ism_change_hook;
410 new->nsm_change_hook = nsm_change_hook;
411 new->config_write_router = config_write_router;
412 new->config_write_if = config_write_if;
413 new->config_write_debug = config_write_debug;
414 new->show_opaque_info = show_opaque_info;
415 new->lsa_originator = lsa_originator;
416 new->lsa_refresher = lsa_refresher;
417 new->new_lsa_hook = new_lsa_hook;
418 new->del_lsa_hook = del_lsa_hook;
419
420 listnode_add (funclist, new);
421 rc = 0;
422
423out:
424 return rc;
425}
426
427void
428ospf_delete_opaque_functab (u_char lsa_type, u_char opaque_type)
429{
87d6f87a 430 struct list *funclist;
1eb8ef25 431 struct listnode *node, *nnode;
718e3744 432 struct ospf_opaque_functab *functab;
433
434 if ((funclist = ospf_get_opaque_funclist (lsa_type)) != NULL)
1eb8ef25 435 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
718e3744 436 {
1eb8ef25 437 if (functab->opaque_type == opaque_type)
718e3744 438 {
439 /* Cleanup internal control information, if it still remains. */
440 if (functab->oipt != NULL)
441 free_opaque_info_per_type (functab->oipt);
442
443 /* Dequeue listnode entry from the list. */
444 listnode_delete (funclist, functab);
445
446 /* Avoid misjudgement in the next lookup. */
447 if (listcount (funclist) == 0)
448 funclist->head = funclist->tail = NULL;
449
450 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, functab);
87d6f87a 451 break;
718e3744 452 }
453 }
87d6f87a 454
718e3744 455 return;
456}
457
458static struct ospf_opaque_functab *
459ospf_opaque_functab_lookup (struct ospf_lsa *lsa)
460{
87d6f87a 461 struct list *funclist;
462 struct listnode *node;
718e3744 463 struct ospf_opaque_functab *functab;
464 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
465
466 if ((funclist = ospf_get_opaque_funclist (lsa->data->type)) != NULL)
1eb8ef25 467 for (ALL_LIST_ELEMENTS_RO (funclist, node, functab))
87d6f87a 468 if (functab->opaque_type == key)
469 return functab;
718e3744 470
471 return NULL;
472}
473
474/*------------------------------------------------------------------------*
475 * Followings are management functions for self-originated LSA entries.
476 *------------------------------------------------------------------------*/
477
478/*
479 * Opaque-LSA control information per opaque-type.
480 * Single Opaque-Type may have multiple instances; each of them will be
481 * identified by their opaque-id.
482 */
483struct opaque_info_per_type
484{
09e4efdc 485 u_char lsa_type;
718e3744 486 u_char opaque_type;
487
488 enum { PROC_NORMAL, PROC_SUSPEND } status;
489
490 /*
491 * Thread for (re-)origination scheduling for this opaque-type.
492 *
493 * Initial origination of Opaque-LSAs is controlled by generic
494 * Opaque-LSA handling module so that same opaque-type entries are
495 * called all at once when certain conditions are met.
496 * However, there might be cases that some Opaque-LSA clients need
497 * to (re-)originate their own Opaque-LSAs out-of-sync with others.
498 * This thread is prepared for that specific purpose.
499 */
500 struct thread *t_opaque_lsa_self;
501
502 /*
09e4efdc 503 * Backpointer to an "owner" which is LSA-type dependent.
718e3744 504 * type-9: struct ospf_interface
505 * type-10: struct ospf_area
506 * type-11: struct ospf
507 */
508 void *owner;
509
510 /* Collection of callback functions for this opaque-type. */
511 struct ospf_opaque_functab *functab;
512
513 /* List of Opaque-LSA control informations per opaque-id. */
87d6f87a 514 struct list *id_list;
718e3744 515};
516
517/* Opaque-LSA control information per opaque-id. */
518struct opaque_info_per_id
519{
520 u_int32_t opaque_id;
521
522 /* Thread for refresh/flush scheduling for this opaque-type/id. */
523 struct thread *t_opaque_lsa_self;
524
525 /* Backpointer to Opaque-LSA control information per opaque-type. */
526 struct opaque_info_per_type *opqctl_type;
527
528 /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
529 struct ospf_lsa *lsa;
530};
531
532static struct opaque_info_per_type *register_opaque_info_per_type (struct ospf_opaque_functab *functab, struct ospf_lsa *new);
533static struct opaque_info_per_type *lookup_opaque_info_by_type (struct ospf_lsa *lsa);
534static struct opaque_info_per_id *register_opaque_info_per_id (struct opaque_info_per_type *oipt, struct ospf_lsa *new);
535static struct opaque_info_per_id *lookup_opaque_info_by_id (struct opaque_info_per_type *oipt, struct ospf_lsa *lsa);
536static struct opaque_info_per_id *register_opaque_lsa (struct ospf_lsa *new);
537
538
539static struct opaque_info_per_type *
540register_opaque_info_per_type (struct ospf_opaque_functab *functab,
541 struct ospf_lsa *new)
542{
543 struct ospf *top;
544 struct opaque_info_per_type *oipt;
545
546 if ((oipt = XCALLOC (MTYPE_OPAQUE_INFO_PER_TYPE,
547 sizeof (struct opaque_info_per_type))) == NULL)
548 {
6099b3b5 549 zlog_warn ("register_opaque_info_per_type: XMALLOC: %s", safe_strerror (errno));
718e3744 550 goto out;
551 }
552
553 switch (new->data->type)
554 {
555 case OSPF_OPAQUE_LINK_LSA:
556 oipt->owner = new->oi;
557 listnode_add (new->oi->opaque_lsa_self, oipt);
558 break;
559 case OSPF_OPAQUE_AREA_LSA:
560 oipt->owner = new->area;
561 listnode_add (new->area->opaque_lsa_self, oipt);
562 break;
563 case OSPF_OPAQUE_AS_LSA:
020709f9 564 top = ospf_lookup ();
68980084 565 if (new->area != NULL && (top = new->area->ospf) == NULL)
718e3744 566 {
567 free_opaque_info_per_type ((void *) oipt);
568 oipt = NULL;
569 goto out; /* This case may not exist. */
570 }
571 oipt->owner = top;
572 listnode_add (top->opaque_lsa_self, oipt);
573 break;
574 default:
09e4efdc 575 zlog_warn ("register_opaque_info_per_type: Unexpected LSA-type(%u)", new->data->type);
718e3744 576 free_opaque_info_per_type ((void *) oipt);
577 oipt = NULL;
578 goto out; /* This case may not exist. */
579 }
580
09e4efdc 581 oipt->lsa_type = new->data->type;
718e3744 582 oipt->opaque_type = GET_OPAQUE_TYPE (ntohl (new->data->id.s_addr));
583 oipt->status = PROC_NORMAL;
584 oipt->t_opaque_lsa_self = NULL;
585 oipt->functab = functab;
586 functab->oipt = oipt;
587 oipt->id_list = list_new ();
588 oipt->id_list->del = free_opaque_info_per_id;
589
590out:
591 return oipt;
592}
593
594static void
595free_opaque_info_per_type (void *val)
596{
597 struct opaque_info_per_type *oipt = (struct opaque_info_per_type *) val;
598 struct opaque_info_per_id *oipi;
599 struct ospf_lsa *lsa;
1eb8ef25 600 struct listnode *node, *nnode;
718e3744 601
602 /* Control information per opaque-id may still exist. */
1eb8ef25 603 for (ALL_LIST_ELEMENTS (oipt->id_list, node, nnode, oipi))
718e3744 604 {
718e3744 605 if ((lsa = oipi->lsa) == NULL)
606 continue;
607 if (IS_LSA_MAXAGE (lsa))
608 continue;
609 ospf_opaque_lsa_flush_schedule (lsa);
610 }
611
09e4efdc 612 /* Remove "oipt" from its owner's self-originated LSA list. */
613 switch (oipt->lsa_type)
614 {
615 case OSPF_OPAQUE_LINK_LSA:
616 {
617 struct ospf_interface *oi = (struct ospf_interface *)(oipt->owner);
618 listnode_delete (oi->opaque_lsa_self, oipt);
619 break;
620 }
621 case OSPF_OPAQUE_AREA_LSA:
622 {
623 struct ospf_area *area = (struct ospf_area *)(oipt->owner);
624 listnode_delete (area->opaque_lsa_self, oipt);
625 break;
626 }
627 case OSPF_OPAQUE_AS_LSA:
628 {
629 struct ospf *top = (struct ospf *)(oipt->owner);
630 listnode_delete (top->opaque_lsa_self, oipt);
631 break;
632 }
633 default:
634 zlog_warn ("free_opaque_info_per_type: Unexpected LSA-type(%u)", oipt->lsa_type);
635 break; /* This case may not exist. */
636 }
637
718e3744 638 OSPF_TIMER_OFF (oipt->t_opaque_lsa_self);
639 list_delete (oipt->id_list);
640 XFREE (MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
641 return;
642}
643
644static struct opaque_info_per_type *
645lookup_opaque_info_by_type (struct ospf_lsa *lsa)
646{
647 struct ospf *top;
648 struct ospf_area *area;
649 struct ospf_interface *oi;
87d6f87a 650 struct list *listtop = NULL;
1eb8ef25 651 struct listnode *node, *nnode;
718e3744 652 struct opaque_info_per_type *oipt = NULL;
653 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
654
655 switch (lsa->data->type)
656 {
657 case OSPF_OPAQUE_LINK_LSA:
658 if ((oi = lsa->oi) != NULL)
659 listtop = oi->opaque_lsa_self;
660 else
661 zlog_warn ("Type-9 Opaque-LSA: Reference to OI is missing?");
662 break;
663 case OSPF_OPAQUE_AREA_LSA:
664 if ((area = lsa->area) != NULL)
665 listtop = area->opaque_lsa_self;
666 else
667 zlog_warn ("Type-10 Opaque-LSA: Reference to AREA is missing?");
668 break;
669 case OSPF_OPAQUE_AS_LSA:
020709f9 670 top = ospf_lookup ();
68980084 671 if ((area = lsa->area) != NULL && (top = area->ospf) == NULL)
718e3744 672 {
673 zlog_warn ("Type-11 Opaque-LSA: Reference to OSPF is missing?");
674 break; /* Unlikely to happen. */
675 }
676 listtop = top->opaque_lsa_self;
677 break;
678 default:
679 zlog_warn ("lookup_opaque_info_by_type: Unexpected LSA-type(%u)", lsa->data->type);
680 break;
681 }
682
683 if (listtop != NULL)
1eb8ef25 684 for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt))
87d6f87a 685 if (oipt->opaque_type == key)
686 return oipt;
718e3744 687
688 return NULL;
689}
690
691static struct opaque_info_per_id *
692register_opaque_info_per_id (struct opaque_info_per_type *oipt,
693 struct ospf_lsa *new)
694{
695 struct opaque_info_per_id *oipi;
696
697 if ((oipi = XCALLOC (MTYPE_OPAQUE_INFO_PER_ID,
698 sizeof (struct opaque_info_per_id))) == NULL)
699 {
6099b3b5 700 zlog_warn ("register_opaque_info_per_id: XMALLOC: %s", safe_strerror (errno));
718e3744 701 goto out;
702 }
703 oipi->opaque_id = GET_OPAQUE_ID (ntohl (new->data->id.s_addr));
704 oipi->t_opaque_lsa_self = NULL;
705 oipi->opqctl_type = oipt;
706 oipi->lsa = ospf_lsa_lock (new);
707
708 listnode_add (oipt->id_list, oipi);
709
710out:
711 return oipi;
712}
713
714static void
715free_opaque_info_per_id (void *val)
716{
717 struct opaque_info_per_id *oipi = (struct opaque_info_per_id *) val;
718
719 OSPF_TIMER_OFF (oipi->t_opaque_lsa_self);
720 if (oipi->lsa != NULL)
1fe6ed38 721 ospf_lsa_unlock (&oipi->lsa);
718e3744 722 XFREE (MTYPE_OPAQUE_INFO_PER_ID, oipi);
723 return;
724}
725
726static struct opaque_info_per_id *
727lookup_opaque_info_by_id (struct opaque_info_per_type *oipt,
728 struct ospf_lsa *lsa)
729{
1eb8ef25 730 struct listnode *node, *nnode;
718e3744 731 struct opaque_info_per_id *oipi;
732 u_int32_t key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
733
1eb8ef25 734 for (ALL_LIST_ELEMENTS (oipt->id_list, node, nnode, oipi))
87d6f87a 735 if (oipi->opaque_id == key)
736 return oipi;
718e3744 737
738 return NULL;
739}
740
741static struct opaque_info_per_id *
742register_opaque_lsa (struct ospf_lsa *new)
743{
744 struct ospf_opaque_functab *functab;
745 struct opaque_info_per_type *oipt;
746 struct opaque_info_per_id *oipi = NULL;
747
748 if ((functab = ospf_opaque_functab_lookup (new)) == NULL)
749 goto out;
750
751 if ((oipt = lookup_opaque_info_by_type (new)) == NULL
752 && (oipt = register_opaque_info_per_type (functab, new)) == NULL)
753 goto out;
754
755 if ((oipi = register_opaque_info_per_id (oipt, new)) == NULL)
756 goto out;
757
758out:
759 return oipi;
760}
761
762/*------------------------------------------------------------------------*
763 * Followings are (vty) configuration functions for Opaque-LSAs handling.
764 *------------------------------------------------------------------------*/
765
766DEFUN (capability_opaque,
767 capability_opaque_cmd,
768 "capability opaque",
769 "Enable specific OSPF feature\n"
770 "Opaque LSA\n")
771{
cdc2d765 772 VTY_DECLVAR_CONTEXT(ospf, ospf);
718e3744 773
774 /* Turn on the "master switch" of opaque-lsa capability. */
775 if (!CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
776 {
777 if (IS_DEBUG_OSPF_EVENT)
2a42e285 778 zlog_debug ("Opaque capability: OFF -> ON");
718e3744 779
780 SET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
781 ospf_renegotiate_optional_capabilities (ospf);
782 }
783 return CMD_SUCCESS;
784}
785
692b4c65
QY
786DEFUN (ospf_opaque,
787 ospf_opaque_cmd,
788 "ospf opaque-lsa",
789 "OSPF specific commands\n"
790 "Enable the Opaque-LSA capability (rfc2370)\n")
791{
792 return capability_opaque (self, vty, argc, argv);
793}
718e3744 794
795DEFUN (no_capability_opaque,
796 no_capability_opaque_cmd,
797 "no capability opaque",
798 NO_STR
799 "Enable specific OSPF feature\n"
800 "Opaque LSA\n")
801{
cdc2d765 802 VTY_DECLVAR_CONTEXT(ospf, ospf);
718e3744 803
804 /* Turn off the "master switch" of opaque-lsa capability. */
805 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
806 {
807 if (IS_DEBUG_OSPF_EVENT)
2a42e285 808 zlog_debug ("Opaque capability: ON -> OFF");
718e3744 809
810 UNSET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
811 ospf_renegotiate_optional_capabilities (ospf);
812 }
813 return CMD_SUCCESS;
814}
815
692b4c65
QY
816DEFUN (no_ospf_opaque,
817 no_ospf_opaque_cmd,
818 "no ospf opaque-lsa",
819 NO_STR
820 "OSPF specific commands\n"
821 "Enable the Opaque-LSA capability (rfc2370)\n")
822{
823 return no_capability_opaque (self, vty, argc, argv);
824}
718e3744 825
826static void
827ospf_opaque_register_vty (void)
828{
829 install_element (OSPF_NODE, &capability_opaque_cmd);
830 install_element (OSPF_NODE, &no_capability_opaque_cmd);
692b4c65
QY
831 install_element (OSPF_NODE, &ospf_opaque_cmd);
832 install_element (OSPF_NODE, &no_ospf_opaque_cmd);
718e3744 833 return;
834}
835
836/*------------------------------------------------------------------------*
837 * Followings are collection of user-registered function callers.
838 *------------------------------------------------------------------------*/
839
840static int
87d6f87a 841opaque_lsa_new_if_callback (struct list *funclist, struct interface *ifp)
718e3744 842{
1eb8ef25 843 struct listnode *node, *nnode;
718e3744 844 struct ospf_opaque_functab *functab;
845 int rc = -1;
846
1eb8ef25 847 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
87d6f87a 848 if (functab->new_if_hook != NULL)
849 if ((* functab->new_if_hook)(ifp) != 0)
850 goto out;
718e3744 851 rc = 0;
852out:
853 return rc;
854}
855
856static int
87d6f87a 857opaque_lsa_del_if_callback (struct list *funclist, struct interface *ifp)
718e3744 858{
1eb8ef25 859 struct listnode *node, *nnode;
718e3744 860 struct ospf_opaque_functab *functab;
861 int rc = -1;
862
1eb8ef25 863 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
87d6f87a 864 if (functab->del_if_hook != NULL)
865 if ((* functab->del_if_hook)(ifp) != 0)
866 goto out;
718e3744 867 rc = 0;
868out:
869 return rc;
870}
871
872static void
87d6f87a 873opaque_lsa_ism_change_callback (struct list *funclist,
718e3744 874 struct ospf_interface *oi, int old_status)
875{
1eb8ef25 876 struct listnode *node, *nnode;
718e3744 877 struct ospf_opaque_functab *functab;
878
1eb8ef25 879 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
87d6f87a 880 if (functab->ism_change_hook != NULL)
881 (* functab->ism_change_hook)(oi, old_status);
882
718e3744 883 return;
884}
885
886static void
87d6f87a 887opaque_lsa_nsm_change_callback (struct list *funclist,
718e3744 888 struct ospf_neighbor *nbr, int old_status)
889{
1eb8ef25 890 struct listnode *node, *nnode;
718e3744 891 struct ospf_opaque_functab *functab;
892
1eb8ef25 893 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
87d6f87a 894 if (functab->nsm_change_hook != NULL)
895 (* functab->nsm_change_hook)(nbr, old_status);
718e3744 896 return;
897}
898
899static void
87d6f87a 900opaque_lsa_config_write_router_callback (struct list *funclist,
901 struct vty *vty)
718e3744 902{
1eb8ef25 903 struct listnode *node, *nnode;
718e3744 904 struct ospf_opaque_functab *functab;
905
1eb8ef25 906 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
87d6f87a 907 if (functab->config_write_router != NULL)
908 (* functab->config_write_router)(vty);
718e3744 909 return;
910}
911
912static void
87d6f87a 913opaque_lsa_config_write_if_callback (struct list *funclist,
718e3744 914 struct vty *vty, struct interface *ifp)
915{
1eb8ef25 916 struct listnode *node, *nnode;
718e3744 917 struct ospf_opaque_functab *functab;
918
1eb8ef25 919 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
87d6f87a 920 if (functab->config_write_if != NULL)
921 (* functab->config_write_if)(vty, ifp);
718e3744 922 return;
923}
924
925static void
87d6f87a 926opaque_lsa_config_write_debug_callback (struct list *funclist, struct vty *vty)
718e3744 927{
1eb8ef25 928 struct listnode *node, *nnode;
718e3744 929 struct ospf_opaque_functab *functab;
930
1eb8ef25 931 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
87d6f87a 932 if (functab->config_write_debug != NULL)
933 (* functab->config_write_debug)(vty);
718e3744 934 return;
935}
936
937static int
87d6f87a 938opaque_lsa_originate_callback (struct list *funclist, void *lsa_type_dependent)
718e3744 939{
1eb8ef25 940 struct listnode *node, *nnode;
718e3744 941 struct ospf_opaque_functab *functab;
942 int rc = -1;
943
1eb8ef25 944 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
87d6f87a 945 if (functab->lsa_originator != NULL)
946 if ((* functab->lsa_originator)(lsa_type_dependent) != 0)
947 goto out;
718e3744 948 rc = 0;
949out:
950 return rc;
951}
952
953static int
87d6f87a 954new_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
718e3744 955{
1eb8ef25 956 struct listnode *node, *nnode;
718e3744 957 struct ospf_opaque_functab *functab;
958 int rc = -1;
959
960 /* This function handles ALL types of LSAs, not only opaque ones. */
1eb8ef25 961 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
87d6f87a 962 if (functab->new_lsa_hook != NULL)
963 if ((* functab->new_lsa_hook)(lsa) != 0)
964 goto out;
718e3744 965 rc = 0;
966out:
967 return rc;
968}
969
970static int
87d6f87a 971del_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
718e3744 972{
1eb8ef25 973 struct listnode *node, *nnode;
718e3744 974 struct ospf_opaque_functab *functab;
975 int rc = -1;
976
977 /* This function handles ALL types of LSAs, not only opaque ones. */
1eb8ef25 978 for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
87d6f87a 979 if (functab->del_lsa_hook != NULL)
980 if ((* functab->del_lsa_hook)(lsa) != 0)
981 goto out;
718e3744 982 rc = 0;
983out:
984 return rc;
985}
986
987/*------------------------------------------------------------------------*
988 * Followings are glue functions to call Opaque-LSA specific processing.
989 *------------------------------------------------------------------------*/
990
991int
992ospf_opaque_new_if (struct interface *ifp)
993{
87d6f87a 994 struct list *funclist;
718e3744 995 int rc = -1;
996
09e4efdc 997 funclist = ospf_opaque_wildcard_funclist;
998 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
999 goto out;
1000
718e3744 1001 funclist = ospf_opaque_type9_funclist;
1002 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
1003 goto out;
1004
1005 funclist = ospf_opaque_type10_funclist;
1006 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
1007 goto out;
1008
1009 funclist = ospf_opaque_type11_funclist;
1010 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
1011 goto out;
1012
1013 rc = 0;
1014out:
1015 return rc;
1016}
1017
1018int
1019ospf_opaque_del_if (struct interface *ifp)
1020{
87d6f87a 1021 struct list *funclist;
718e3744 1022 int rc = -1;
1023
09e4efdc 1024 funclist = ospf_opaque_wildcard_funclist;
1025 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1026 goto out;
1027
718e3744 1028 funclist = ospf_opaque_type9_funclist;
1029 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1030 goto out;
1031
1032 funclist = ospf_opaque_type10_funclist;
1033 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1034 goto out;
1035
1036 funclist = ospf_opaque_type11_funclist;
1037 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1038 goto out;
1039
1040 rc = 0;
1041out:
1042 return rc;
1043}
1044
1045void
1046ospf_opaque_ism_change (struct ospf_interface *oi, int old_status)
1047{
87d6f87a 1048 struct list *funclist;
718e3744 1049
09e4efdc 1050 funclist = ospf_opaque_wildcard_funclist;
1051 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1052
718e3744 1053 funclist = ospf_opaque_type9_funclist;
1054 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1055
1056 funclist = ospf_opaque_type10_funclist;
1057 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1058
1059 funclist = ospf_opaque_type11_funclist;
1060 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1061
1062 return;
1063}
1064
1065void
1066ospf_opaque_nsm_change (struct ospf_neighbor *nbr, int old_state)
1067{
1068 struct ospf *top;
87d6f87a 1069 struct list *funclist;
718e3744 1070
1071 if ((top = oi_to_top (nbr->oi)) == NULL)
1072 goto out;
1073
1074 if (old_state != NSM_Full && nbr->state == NSM_Full)
1075 {
1076 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
1077 {
1078 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1079 {
1080 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1081 zlog_debug ("Opaque-LSA: Now get operational!");
718e3744 1082
1083 SET_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT);
1084 }
1085
1086 ospf_opaque_lsa_originate_schedule (nbr->oi, NULL);
1087 }
1088 }
1089 else
1090 if (old_state == NSM_Full && nbr->state != NSM_Full)
1091 {
1092#ifdef NOTYET
1093 /*
1094 * If no more opaque-capable full-state neighbor remains in the
1095 * flooding scope which corresponds to Opaque-LSA type, periodic
1096 * LS flooding should be stopped.
1097 */
1098#endif /* NOTYET */
1099 ;
1100 }
1101
09e4efdc 1102 funclist = ospf_opaque_wildcard_funclist;
1103 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1104
718e3744 1105 funclist = ospf_opaque_type9_funclist;
1106 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1107
1108 funclist = ospf_opaque_type10_funclist;
1109 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1110
1111 funclist = ospf_opaque_type11_funclist;
1112 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1113
1114out:
1115 return;
1116}
1117
1118void
1119ospf_opaque_config_write_router (struct vty *vty, struct ospf *ospf)
1120{
87d6f87a 1121 struct list *funclist;
718e3744 1122
1123 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
1124 vty_out (vty, " capability opaque%s", VTY_NEWLINE);
1125
09e4efdc 1126 funclist = ospf_opaque_wildcard_funclist;
1127 opaque_lsa_config_write_router_callback (funclist, vty);
1128
718e3744 1129 funclist = ospf_opaque_type9_funclist;
1130 opaque_lsa_config_write_router_callback (funclist, vty);
1131
1132 funclist = ospf_opaque_type10_funclist;
1133 opaque_lsa_config_write_router_callback (funclist, vty);
1134
1135 funclist = ospf_opaque_type11_funclist;
1136 opaque_lsa_config_write_router_callback (funclist, vty);
1137
1138 return;
1139}
1140
1141void
1142ospf_opaque_config_write_if (struct vty *vty, struct interface *ifp)
1143{
87d6f87a 1144 struct list *funclist;
718e3744 1145
09e4efdc 1146 funclist = ospf_opaque_wildcard_funclist;
1147 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1148
718e3744 1149 funclist = ospf_opaque_type9_funclist;
1150 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1151
1152 funclist = ospf_opaque_type10_funclist;
1153 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1154
1155 funclist = ospf_opaque_type11_funclist;
1156 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1157
1158 return;
1159}
1160
1161void
1162ospf_opaque_config_write_debug (struct vty *vty)
1163{
87d6f87a 1164 struct list *funclist;
718e3744 1165
09e4efdc 1166 funclist = ospf_opaque_wildcard_funclist;
1167 opaque_lsa_config_write_debug_callback (funclist, vty);
1168
718e3744 1169 funclist = ospf_opaque_type9_funclist;
1170 opaque_lsa_config_write_debug_callback (funclist, vty);
1171
1172 funclist = ospf_opaque_type10_funclist;
1173 opaque_lsa_config_write_debug_callback (funclist, vty);
1174
1175 funclist = ospf_opaque_type11_funclist;
1176 opaque_lsa_config_write_debug_callback (funclist, vty);
1177
1178 return;
1179}
1180
1181void
1182show_opaque_info_detail (struct vty *vty, struct ospf_lsa *lsa)
1183{
1184 struct lsa_header *lsah = (struct lsa_header *) lsa->data;
1185 u_int32_t lsid = ntohl (lsah->id.s_addr);
1186 u_char opaque_type = GET_OPAQUE_TYPE (lsid);
1187 u_int32_t opaque_id = GET_OPAQUE_ID (lsid);
1188 struct ospf_opaque_functab *functab;
1189
1190 /* Switch output functionality by vty address. */
1191 if (vty != NULL)
1192 {
020709f9 1193 vty_out (vty, " Opaque-Type %u (%s)%s", opaque_type,
1194 ospf_opaque_type_name (opaque_type), VTY_NEWLINE);
718e3744 1195 vty_out (vty, " Opaque-ID 0x%x%s", opaque_id, VTY_NEWLINE);
1196
1197 vty_out (vty, " Opaque-Info: %u octets of data%s%s",
1198 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1199 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)",
1200 VTY_NEWLINE);
1201 }
1202 else
1203 {
2a42e285 1204 zlog_debug (" Opaque-Type %u (%s)", opaque_type,
020709f9 1205 ospf_opaque_type_name (opaque_type));
2a42e285 1206 zlog_debug (" Opaque-ID 0x%x", opaque_id);
718e3744 1207
2a42e285 1208 zlog_debug (" Opaque-Info: %u octets of data%s",
718e3744 1209 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1210 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)");
1211 }
1212
1213 /* Call individual output functions. */
1214 if ((functab = ospf_opaque_functab_lookup (lsa)) != NULL)
1215 if (functab->show_opaque_info != NULL)
1216 (* functab->show_opaque_info)(vty, lsa);
1217
1218 return;
1219}
1220
1221void
1222ospf_opaque_lsa_dump (struct stream *s, u_int16_t length)
1223{
1224 struct ospf_lsa lsa;
1225
1226 lsa.data = (struct lsa_header *) STREAM_PNT (s);
1227 show_opaque_info_detail (NULL, &lsa);
1228 return;
1229}
1230
1231static int
1232ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa)
1233{
87d6f87a 1234 struct list *funclist;
718e3744 1235 int rc = -1;
1236
1237 /*
1238 * Some Opaque-LSA user may want to monitor every LSA installation
1239 * into the LSDB, regardless with target LSA type.
1240 */
09e4efdc 1241 funclist = ospf_opaque_wildcard_funclist;
1242 if (new_lsa_callback (funclist, lsa) != 0)
1243 goto out;
1244
718e3744 1245 funclist = ospf_opaque_type9_funclist;
1246 if (new_lsa_callback (funclist, lsa) != 0)
1247 goto out;
1248
1249 funclist = ospf_opaque_type10_funclist;
1250 if (new_lsa_callback (funclist, lsa) != 0)
1251 goto out;
1252
1253 funclist = ospf_opaque_type11_funclist;
1254 if (new_lsa_callback (funclist, lsa) != 0)
1255 goto out;
1256
1257 rc = 0;
1258out:
1259 return rc;
1260}
1261
1262static int
1263ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa)
1264{
87d6f87a 1265 struct list *funclist;
718e3744 1266 int rc = -1;
1267
1268 /*
1269 * Some Opaque-LSA user may want to monitor every LSA deletion
1270 * from the LSDB, regardless with target LSA type.
1271 */
09e4efdc 1272 funclist = ospf_opaque_wildcard_funclist;
1273 if (del_lsa_callback (funclist, lsa) != 0)
1274 goto out;
1275
718e3744 1276 funclist = ospf_opaque_type9_funclist;
1277 if (del_lsa_callback (funclist, lsa) != 0)
1278 goto out;
1279
1280 funclist = ospf_opaque_type10_funclist;
1281 if (del_lsa_callback (funclist, lsa) != 0)
1282 goto out;
1283
1284 funclist = ospf_opaque_type11_funclist;
1285 if (del_lsa_callback (funclist, lsa) != 0)
1286 goto out;
1287
1288 rc = 0;
1289out:
1290 return rc;
1291}
1292
1293/*------------------------------------------------------------------------*
1294 * Followings are Opaque-LSA origination/refresh management functions.
1295 *------------------------------------------------------------------------*/
1296
1297static int ospf_opaque_type9_lsa_originate (struct thread *t);
1298static int ospf_opaque_type10_lsa_originate (struct thread *t);
1299static int ospf_opaque_type11_lsa_originate (struct thread *t);
87d6f87a 1300static void ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg);
718e3744 1301
1302void
1303ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0)
1304{
1305 struct ospf *top;
1306 struct ospf_area *area;
1eb8ef25 1307 struct listnode *node, *nnode;
718e3744 1308 struct opaque_info_per_type *oipt;
1309 int delay = 0;
1310
1311 if ((top = oi_to_top (oi)) == NULL || (area = oi->area) == NULL)
1312 {
1313 zlog_warn ("ospf_opaque_lsa_originate_schedule: Invalid argument?");
1314 goto out;
1315 }
1316
1317 /* It may not a right time to schedule origination now. */
1318 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1319 {
1320 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1321 zlog_debug ("ospf_opaque_lsa_originate_schedule: Not operational.");
718e3744 1322 goto out; /* This is not an error. */
1323 }
801e0e14 1324
718e3744 1325 if (delay0 != NULL)
1326 delay = *delay0;
1327
1328 /*
1329 * There might be some entries that have been waiting for triggering
1330 * of per opaque-type re-origination get resumed.
1331 */
1332 ospf_opaque_lsa_reoriginate_resume ( oi->opaque_lsa_self, (void *) oi);
1333 ospf_opaque_lsa_reoriginate_resume (area->opaque_lsa_self, (void *) area);
1334 ospf_opaque_lsa_reoriginate_resume ( top->opaque_lsa_self, (void *) top);
1335
1336 /*
1337 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1338 */
1339 if (! list_isempty (ospf_opaque_type9_funclist)
1340 && list_isempty (oi->opaque_lsa_self)
1341 && oi->t_opaque_lsa_self == NULL)
1342 {
1343 if (IS_DEBUG_OSPF_EVENT)
ac7424f9 1344 zlog_debug ("Schedule Type-9 Opaque-LSA origination in %d ms later.", delay);
718e3744 1345 oi->t_opaque_lsa_self =
ac7424f9
MR
1346 thread_add_timer_msec (master, ospf_opaque_type9_lsa_originate, oi, delay);
1347 delay += top->min_ls_interval;
718e3744 1348 }
1349
1350 if (! list_isempty (ospf_opaque_type10_funclist)
1351 && list_isempty (area->opaque_lsa_self)
1352 && area->t_opaque_lsa_self == NULL)
1353 {
1354 /*
1355 * One AREA may contain multiple OIs, but above 2nd and 3rd
1356 * conditions prevent from scheduling the originate function
1357 * again and again.
1358 */
1359 if (IS_DEBUG_OSPF_EVENT)
ac7424f9 1360 zlog_debug ("Schedule Type-10 Opaque-LSA origination in %d ms later.", delay);
718e3744 1361 area->t_opaque_lsa_self =
ac7424f9
MR
1362 thread_add_timer_msec (master, ospf_opaque_type10_lsa_originate,
1363 area, delay);
1364 delay += top->min_ls_interval;
718e3744 1365 }
1366
1367 if (! list_isempty (ospf_opaque_type11_funclist)
1368 && list_isempty (top->opaque_lsa_self)
1369 && top->t_opaque_lsa_self == NULL)
1370 {
1371 /*
1372 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1373 * conditions prevent from scheduling the originate function
1374 * again and again.
1375 */
1376 if (IS_DEBUG_OSPF_EVENT)
ac7424f9 1377 zlog_debug ("Schedule Type-11 Opaque-LSA origination in %d ms later.", delay);
718e3744 1378 top->t_opaque_lsa_self =
ac7424f9
MR
1379 thread_add_timer_msec (master, ospf_opaque_type11_lsa_originate,
1380 top, delay);
1381 delay += top->min_ls_interval;
718e3744 1382 }
1383
1384 /*
1385 * Following section treats a special situation that this node's
1386 * opaque capability has changed as "ON -> OFF -> ON".
1387 */
1388 if (! list_isempty (ospf_opaque_type9_funclist)
1389 && ! list_isempty (oi->opaque_lsa_self))
1390 {
1eb8ef25 1391 for (ALL_LIST_ELEMENTS (oi->opaque_lsa_self, node, nnode, oipt))
718e3744 1392 {
0d85b995 1393 /*
1394 * removed the test for
1395 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1396 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1397 * not being empty.
1398 */
1eb8ef25 1399 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1400 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
718e3744 1401 continue;
1402
1403 ospf_opaque_lsa_reoriginate_schedule ((void *) oi,
1404 OSPF_OPAQUE_LINK_LSA, oipt->opaque_type);
1405 }
1406 }
1407
1408 if (! list_isempty (ospf_opaque_type10_funclist)
1409 && ! list_isempty (area->opaque_lsa_self))
1410 {
1eb8ef25 1411 for (ALL_LIST_ELEMENTS (area->opaque_lsa_self, node, nnode, oipt))
718e3744 1412 {
0d85b995 1413 /*
1414 * removed the test for
1415 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1416 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1417 * not being empty.
1418 */
1eb8ef25 1419 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1420 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
718e3744 1421 continue;
1422
1423 ospf_opaque_lsa_reoriginate_schedule ((void *) area,
1424 OSPF_OPAQUE_AREA_LSA, oipt->opaque_type);
1425 }
1426 }
1427
1428 if (! list_isempty (ospf_opaque_type11_funclist)
1429 && ! list_isempty (top->opaque_lsa_self))
1430 {
1eb8ef25 1431 for (ALL_LIST_ELEMENTS (top->opaque_lsa_self, node, nnode, oipt))
718e3744 1432 {
0d85b995 1433 /*
1434 * removed the test for
1435 * (! list_isempty (oipt->id_list)) * Handler is already active. *
1436 * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
1437 * not being empty.
1438 */
1eb8ef25 1439 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1440 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
718e3744 1441 continue;
1442
1443 ospf_opaque_lsa_reoriginate_schedule ((void *) top,
1444 OSPF_OPAQUE_AS_LSA, oipt->opaque_type);
1445 }
1446 }
1447
1448 if (delay0 != NULL)
1449 *delay0 = delay;
1450
1451out:
1452 return;
1453}
1454
1455static int
1456ospf_opaque_type9_lsa_originate (struct thread *t)
1457{
1458 struct ospf_interface *oi;
1459 int rc;
1460
1461 oi = THREAD_ARG (t);
1462 oi->t_opaque_lsa_self = NULL;
1463
1464 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1465 zlog_debug ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
718e3744 1466 IF_NAME (oi));
1467
1468 rc = opaque_lsa_originate_callback (ospf_opaque_type9_funclist, oi);
1469
1470 return rc;
1471}
1472
1473static int
1474ospf_opaque_type10_lsa_originate (struct thread *t)
1475{
1476 struct ospf_area *area;
1477 int rc;
1478
1479 area = THREAD_ARG (t);
1480 area->t_opaque_lsa_self = NULL;
1481
1482 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1483 zlog_debug ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
718e3744 1484 inet_ntoa (area->area_id));
1485
1486 rc = opaque_lsa_originate_callback (ospf_opaque_type10_funclist, area);
1487
1488 return rc;
1489}
1490
1491static int
1492ospf_opaque_type11_lsa_originate (struct thread *t)
1493{
1494 struct ospf *top;
1495 int rc;
1496
1497 top = THREAD_ARG (t);
1498 top->t_opaque_lsa_self = NULL;
1499
1500 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1501 zlog_debug ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
718e3744 1502
1503 rc = opaque_lsa_originate_callback (ospf_opaque_type11_funclist, top);
1504
1505 return rc;
1506}
1507
1508static void
87d6f87a 1509ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg)
718e3744 1510{
1eb8ef25 1511 struct listnode *node, *nnode;
718e3744 1512 struct opaque_info_per_type *oipt;
1513 struct ospf_opaque_functab *functab;
1514
1515 if (listtop == NULL)
1516 goto out;
1517
1518 /*
1519 * Pickup oipt entries those which in SUSPEND status, and give
1520 * them a chance to start re-origination now.
1521 */
1eb8ef25 1522 for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt))
718e3744 1523 {
87d6f87a 1524 if (oipt->status != PROC_SUSPEND)
718e3744 1525 continue;
1526
1527 oipt->status = PROC_NORMAL;
1528
1529 if ((functab = oipt->functab) == NULL
87d6f87a 1530 || functab->lsa_originator == NULL)
718e3744 1531 continue;
1532
1533 if ((* functab->lsa_originator)(arg) != 0)
1534 {
1535 zlog_warn ("ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", oipt->opaque_type);
1536 continue;
1537 }
1538 }
1539
1540out:
1541 return;
1542}
1543
1544struct ospf_lsa *
1545ospf_opaque_lsa_install (struct ospf_lsa *lsa, int rt_recalc)
1546{
1547 struct ospf_lsa *new = NULL;
1548 struct opaque_info_per_type *oipt;
1549 struct opaque_info_per_id *oipi;
1550 struct ospf *top;
1551
1552 /* Don't take "rt_recalc" into consideration for now. *//* XXX */
1553
1554 if (! IS_LSA_SELF (lsa))
1555 {
1556 new = lsa; /* Don't touch this LSA. */
1557 goto out;
1558 }
1559
1560 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
2a42e285 1561 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)));
718e3744 1562
1563 /* Replace the existing lsa with the new one. */
1564 if ((oipt = lookup_opaque_info_by_type (lsa)) != NULL
87d6f87a 1565 && (oipi = lookup_opaque_info_by_id (oipt, lsa)) != NULL)
718e3744 1566 {
1fe6ed38 1567 ospf_lsa_unlock (&oipi->lsa);
718e3744 1568 oipi->lsa = ospf_lsa_lock (lsa);
1569 }
1570 /* Register the new lsa entry and get its control info. */
1571 else
1572 if ((oipi = register_opaque_lsa (lsa)) == NULL)
1573 {
1574 zlog_warn ("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1575 goto out;
1576 }
1577
1578 /*
1579 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1580 * for periodic refresh of self-originated Opaque-LSAs.
1581 */
1582 switch (lsa->data->type)
1583 {
1584 case OSPF_OPAQUE_LINK_LSA:
09e4efdc 1585 if ((top = oi_to_top (lsa->oi)) == NULL)
1586 {
1587 /* Above conditions must have passed. */
1588 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1589 goto out;
1590 }
1591 break;
718e3744 1592 case OSPF_OPAQUE_AREA_LSA:
68980084 1593 if (lsa->area == NULL || (top = lsa->area->ospf) == NULL)
718e3744 1594 {
1595 /* Above conditions must have passed. */
1596 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1597 goto out;
1598 }
1599 break;
1600 case OSPF_OPAQUE_AS_LSA:
020709f9 1601 top = ospf_lookup ();
68980084 1602 if (lsa->area != NULL && (top = lsa->area->ospf) == NULL)
718e3744 1603 {
1604 /* Above conditions must have passed. */
1605 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1606 goto out;
1607 }
1608 break;
1609 default:
1610 zlog_warn ("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", lsa->data->type);
1611 goto out;
1612 }
1613
1614 ospf_refresher_register_lsa (top, lsa);
1615 new = lsa;
1616
1617out:
1618 return new;
1619}
1620
d71ea652 1621struct ospf_lsa *
718e3744 1622ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
1623{
020709f9 1624 struct ospf *ospf;
718e3744 1625 struct ospf_opaque_functab *functab;
d71ea652
PJ
1626 struct ospf_lsa *new = NULL;
1627
020709f9 1628 ospf = ospf_lookup ();
1629
718e3744 1630 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL
87d6f87a 1631 || functab->lsa_refresher == NULL)
718e3744 1632 {
1633 /*
1634 * Though this LSA seems to have originated on this node, the
1635 * handling module for this "lsa-type and opaque-type" was
1636 * already deleted sometime ago.
1637 * Anyway, this node still has a responsibility to flush this
1638 * LSA from the routing domain.
1639 */
1640 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1641 zlog_debug ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id));
718e3744 1642
1643 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
02d942c9 1644 ospf_lsa_flush (ospf, lsa);
718e3744 1645 }
1646 else
d71ea652 1647 new = (* functab->lsa_refresher)(lsa);
718e3744 1648
d71ea652 1649 return new;
718e3744 1650}
1651
1652/*------------------------------------------------------------------------*
1653 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1654 * triggered by external interventions (vty session, signaling, etc).
1655 *------------------------------------------------------------------------*/
1656
1657#define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
1658 if (!(T)) \
ac7424f9 1659 (T) = thread_add_timer_msec (master, (F), (L), (V))
718e3744 1660
1661static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type);
1662static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t);
1663static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t);
1664static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t);
1665static int ospf_opaque_lsa_refresh_timer (struct thread *t);
1666
1667void
1668ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
1669 u_char lsa_type, u_char opaque_type)
1670{
1671 struct ospf *top;
1672 struct ospf_area dummy, *area = NULL;
1673 struct ospf_interface *oi = NULL;
1674
1675 struct ospf_lsa *lsa;
1676 struct opaque_info_per_type *oipt;
87d6f87a 1677 int (*func) (struct thread * t) = NULL;
718e3744 1678 int delay;
1679
1680 switch (lsa_type)
1681 {
1682 case OSPF_OPAQUE_LINK_LSA:
1683 if ((oi = (struct ospf_interface *) lsa_type_dependent) == NULL)
1684 {
87d6f87a 1685 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1686 " Type-9 Opaque-LSA: Invalid parameter?");
1687 goto out;
718e3744 1688 }
1689 if ((top = oi_to_top (oi)) == NULL)
1690 {
87d6f87a 1691 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1692 IF_NAME (oi));
718e3744 1693 goto out;
1694 }
87d6f87a 1695 if (!list_isempty (ospf_opaque_type9_funclist)
1696 && list_isempty (oi->opaque_lsa_self)
1697 && oi->t_opaque_lsa_self != NULL)
718e3744 1698 {
87d6f87a 1699 zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u):"
1700 " Common origination for OI(%s) has already started",
1701 opaque_type, IF_NAME (oi));
718e3744 1702 goto out;
1703 }
1704 func = ospf_opaque_type9_lsa_reoriginate_timer;
1705 break;
1706 case OSPF_OPAQUE_AREA_LSA:
1707 if ((area = (struct ospf_area *) lsa_type_dependent) == NULL)
1708 {
87d6f87a 1709 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1710 " Type-10 Opaque-LSA: Invalid parameter?");
718e3744 1711 goto out;
1712 }
68980084 1713 if ((top = area->ospf) == NULL)
718e3744 1714 {
87d6f87a 1715 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1716 " AREA(%s) -> TOP?", inet_ntoa (area->area_id));
718e3744 1717 goto out;
1718 }
87d6f87a 1719 if (!list_isempty (ospf_opaque_type10_funclist)
1720 && list_isempty (area->opaque_lsa_self)
1721 && area->t_opaque_lsa_self != NULL)
718e3744 1722 {
87d6f87a 1723 zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u):"
1724 " Common origination for AREA(%s) has already started",
1725 opaque_type, inet_ntoa (area->area_id));
718e3744 1726 goto out;
1727 }
1728 func = ospf_opaque_type10_lsa_reoriginate_timer;
1729 break;
1730 case OSPF_OPAQUE_AS_LSA:
1731 if ((top = (struct ospf *) lsa_type_dependent) == NULL)
1732 {
87d6f87a 1733 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1734 " Type-11 Opaque-LSA: Invalid parameter?");
1735 goto out;
718e3744 1736 }
87d6f87a 1737 if (!list_isempty (ospf_opaque_type11_funclist)
1738 && list_isempty (top->opaque_lsa_self)
1739 && top->t_opaque_lsa_self != NULL)
718e3744 1740 {
87d6f87a 1741 zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u):"
1742 " Common origination has already started", opaque_type);
718e3744 1743 goto out;
1744 }
1745
1746 /* Fake "area" to pass "ospf" to a lookup function later. */
68980084 1747 dummy.ospf = top;
718e3744 1748 area = &dummy;
1749
1750 func = ospf_opaque_type11_lsa_reoriginate_timer;
1751 break;
1752 default:
87d6f87a 1753 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1754 " Unexpected LSA-type(%u)",
1755 lsa_type);
718e3744 1756 goto out;
1757 }
1758
1759 /* It may not a right time to schedule reorigination now. */
87d6f87a 1760 if (!CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
718e3744 1761 {
1762 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1763 zlog_debug ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
87d6f87a 1764 goto out; /* This is not an error. */
718e3744 1765 }
801e0e14 1766
718e3744 1767 /* Generate a dummy lsa to be passed for a lookup function. */
1768 lsa = pseudo_lsa (oi, area, lsa_type, opaque_type);
1769
1770 if ((oipt = lookup_opaque_info_by_type (lsa)) == NULL)
1771 {
1772 struct ospf_opaque_functab *functab;
1773 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL)
1774 {
87d6f87a 1775 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1776 " No associated function?: lsa_type(%u),"
1777 " opaque_type(%u)",
1778 lsa_type, opaque_type);
718e3744 1779 goto out;
1780 }
1781 if ((oipt = register_opaque_info_per_type (functab, lsa)) == NULL)
1782 {
87d6f87a 1783 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1784 " Cannot get a control info?: lsa_type(%u),"
1785 " opaque_type(%u)",
1786 lsa_type, opaque_type);
718e3744 1787 goto out;
1788 }
1789 }
1790
1791 if (oipt->t_opaque_lsa_self != NULL)
1792 {
1793 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1794 zlog_debug ("Type-%u Opaque-LSA has already scheduled to"
87d6f87a 1795 " RE-ORIGINATE: [opaque-type=%u]",
1796 lsa_type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
718e3744 1797 goto out;
1798 }
1799
1800 /*
1801 * Different from initial origination time, in which various conditions
1802 * (opaque capability, neighbor status etc) are assured by caller of
1803 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1804 * it is highly possible that these conditions might not be satisfied
1805 * at the time of re-origination function is to be called.
1806 */
ac7424f9 1807 delay = top->min_ls_interval; /* XXX */
718e3744 1808
1809 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1810 zlog_debug ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
ac7424f9 1811 " ms later: [opaque-type=%u]",
87d6f87a 1812 lsa_type, delay,
1813 GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
718e3744 1814
ac7424f9 1815 OSPF_OPAQUE_TIMER_ON (oipt->t_opaque_lsa_self, func, oipt, delay * 1000);
718e3744 1816
1817out:
1818 return;
1819}
1820
1821static struct ospf_lsa *
1822pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area,
1823 u_char lsa_type, u_char opaque_type)
1824{
1825 static struct ospf_lsa lsa = { 0 };
1826 static struct lsa_header lsah = { 0 };
1827 u_int32_t tmp;
1828
1829 lsa.oi = oi;
1830 lsa.area = area;
1831 lsa.data = &lsah;
1832
1833 lsah.type = lsa_type;
1834 tmp = SET_OPAQUE_LSID (opaque_type, 0); /* Opaque-ID is unused here. */
1835 lsah.id.s_addr = htonl (tmp);
1836
1837 return &lsa;
1838}
1839
1840static int
1841ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t)
1842{
1843 struct opaque_info_per_type *oipt;
1844 struct ospf_opaque_functab *functab;
1845 struct ospf *top;
1846 struct ospf_interface *oi;
1847 int rc = -1;
1848
1849 oipt = THREAD_ARG (t);
1850 oipt->t_opaque_lsa_self = NULL;
1851
1852 if ((functab = oipt->functab) == NULL
1853 || functab->lsa_originator == NULL)
1854 {
1855 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1856 goto out;
1857 }
1858
1859 oi = (struct ospf_interface *) oipt->owner;
1860 if ((top = oi_to_top (oi)) == NULL)
1861 {
1862 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1863 goto out;
1864 }
1865
1866 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)
1867 || ! ospf_if_is_enable (oi)
68980084 1868 || ospf_nbr_count_opaque_capable (oi) == 0)
718e3744 1869 {
1870 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1871 zlog_debug ("Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
718e3744 1872
1873 oipt->status = PROC_SUSPEND;
1874 rc = 0;
1875 goto out;
1876 }
1877
1878 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1879 zlog_debug ("Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)", oipt->opaque_type, IF_NAME (oi));
718e3744 1880
1881 rc = (* functab->lsa_originator)(oi);
1882out:
1883 return rc;
1884}
1885
1886static int
1887ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t)
1888{
1889 struct opaque_info_per_type *oipt;
1890 struct ospf_opaque_functab *functab;
1eb8ef25 1891 struct listnode *node, *nnode;
718e3744 1892 struct ospf *top;
1893 struct ospf_area *area;
1894 struct ospf_interface *oi;
1895 int n, rc = -1;
1896
1897 oipt = THREAD_ARG (t);
1898 oipt->t_opaque_lsa_self = NULL;
1899
1900 if ((functab = oipt->functab) == NULL
1901 || functab->lsa_originator == NULL)
1902 {
1903 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1904 goto out;
1905 }
1906
1907 area = (struct ospf_area *) oipt->owner;
68980084 1908 if (area == NULL || (top = area->ospf) == NULL)
718e3744 1909 {
1910 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1911 goto out;
1912 }
1913
1914 /* There must be at least one "opaque-capable, full-state" neighbor. */
1915 n = 0;
1eb8ef25 1916 for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi))
718e3744 1917 {
68980084 1918 if ((n = ospf_nbr_count_opaque_capable (oi)) > 0)
718e3744 1919 break;
1920 }
1921
1922 if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1923 {
1924 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1925 zlog_debug ("Suspend re-origination of Type-10 Opaque-LSAs"
87d6f87a 1926 " (opaque-type=%u) for a while...",
1927 oipt->opaque_type);
718e3744 1928
1929 oipt->status = PROC_SUSPEND;
1930 rc = 0;
1931 goto out;
1932 }
1933
1934 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1935 zlog_debug ("Timer[Type10-LSA]: Re-originate Opaque-LSAs"
87d6f87a 1936 " (opaque-type=%u) for Area %s",
1937 oipt->opaque_type, inet_ntoa (area->area_id));
718e3744 1938
1939 rc = (* functab->lsa_originator)(area);
1940out:
1941 return rc;
1942}
1943
1944static int
1945ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t)
1946{
1947 struct opaque_info_per_type *oipt;
1948 struct ospf_opaque_functab *functab;
1949 struct ospf *top;
1950 int rc = -1;
1951
1952 oipt = THREAD_ARG (t);
1953 oipt->t_opaque_lsa_self = NULL;
1954
1955 if ((functab = oipt->functab) == NULL
87d6f87a 1956 || functab->lsa_originator == NULL)
718e3744 1957 {
87d6f87a 1958 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer:"
1959 " No associated function?");
718e3744 1960 goto out;
1961 }
1962
1963 if ((top = (struct ospf *) oipt->owner) == NULL)
1964 {
1965 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1966 goto out;
1967 }
1968
1969 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1970 {
1971 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1972 zlog_debug ("Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
718e3744 1973
1974 oipt->status = PROC_SUSPEND;
1975 rc = 0;
1976 goto out;
1977 }
1978
1979 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1980 zlog_debug ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type);
718e3744 1981
1982 rc = (* functab->lsa_originator)(top);
1983out:
1984 return rc;
1985}
1986
718e3744 1987void
1988ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
1989{
1990 struct opaque_info_per_type *oipt;
1991 struct opaque_info_per_id *oipi;
1992 struct ospf_lsa *lsa;
16f1b9ee 1993 struct ospf *top;
718e3744 1994 int delay;
1995
1996 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
1997 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
1998 {
1999 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
2000 goto out;
2001 }
2002
2003 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2004 if ((lsa = oipi->lsa) == NULL)
2005 {
2006 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
2007 goto out;
2008 }
2009
2010 if (oipi->t_opaque_lsa_self != NULL)
2011 {
2012 if (IS_DEBUG_OSPF_EVENT)
2a42e285 2013 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)));
718e3744 2014 goto out;
2015 }
2016
2017 /* Delete this lsa from neighbor retransmit-list. */
2018 switch (lsa->data->type)
2019 {
2020 case OSPF_OPAQUE_LINK_LSA:
2021 case OSPF_OPAQUE_AREA_LSA:
68980084 2022 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
718e3744 2023 break;
2024 case OSPF_OPAQUE_AS_LSA:
16f1b9ee
OD
2025 top = ospf_lookup ();
2026 if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
2027 top = lsa0->area->ospf;
2028 ospf_ls_retransmit_delete_nbr_as (top, lsa);
718e3744 2029 break;
2030 default:
2031 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2032 goto out;
2033 }
2034
2035 delay = ospf_lsa_refresh_delay (lsa);
2036
2037 if (IS_DEBUG_OSPF_EVENT)
2a42e285 2038 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)));
718e3744 2039
2040 OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self,
ac7424f9 2041 ospf_opaque_lsa_refresh_timer, oipi, delay * 1000);
718e3744 2042out:
2043 return;
2044}
2045
2046static int
2047ospf_opaque_lsa_refresh_timer (struct thread *t)
2048{
2049 struct opaque_info_per_id *oipi;
2050 struct ospf_opaque_functab *functab;
2051 struct ospf_lsa *lsa;
2052
2053 if (IS_DEBUG_OSPF_EVENT)
2a42e285 2054 zlog_debug ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
718e3744 2055
2056 oipi = THREAD_ARG (t);
2057 oipi->t_opaque_lsa_self = NULL;
2058
2059 if ((lsa = oipi->lsa) != NULL)
2060 if ((functab = oipi->opqctl_type->functab) != NULL)
2061 if (functab->lsa_refresher != NULL)
2062 (* functab->lsa_refresher)(lsa);
2063
2064 return 0;
2065}
2066
2067void
2068ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
2069{
2070 struct opaque_info_per_type *oipt;
2071 struct opaque_info_per_id *oipi;
2072 struct ospf_lsa *lsa;
16f1b9ee
OD
2073 struct ospf *top;
2074
2075 top = ospf_lookup ();
718e3744 2076
2077 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
2078 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
2079 {
2080 zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2081 goto out;
2082 }
2083
2084 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2085 if ((lsa = oipi->lsa) == NULL)
2086 {
2087 zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
2088 goto out;
2089 }
2090
2091 /* Delete this lsa from neighbor retransmit-list. */
2092 switch (lsa->data->type)
2093 {
2094 case OSPF_OPAQUE_LINK_LSA:
2095 case OSPF_OPAQUE_AREA_LSA:
68980084 2096 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
718e3744 2097 break;
2098 case OSPF_OPAQUE_AS_LSA:
16f1b9ee
OD
2099 if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
2100 top = lsa0->area->ospf;
2101 ospf_ls_retransmit_delete_nbr_as (top, lsa);
718e3744 2102 break;
2103 default:
2104 zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2105 goto out;
2106 }
2107
2108 /* Dequeue listnode entry from the list. */
2109 listnode_delete (oipt->id_list, oipi);
2110
2111 /* Avoid misjudgement in the next lookup. */
2112 if (listcount (oipt->id_list) == 0)
2113 oipt->id_list->head = oipt->id_list->tail = NULL;
2114
2115 /* Disassociate internal control information with the given lsa. */
718e3744 2116 free_opaque_info_per_id ((void *) oipi);
2117
2118 /* Force given lsa's age to MaxAge. */
2119 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2120
2121 if (IS_DEBUG_OSPF_EVENT)
2a42e285 2122 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)));
718e3744 2123
2124 /* This lsa will be flushed and removed eventually. */
16f1b9ee 2125 ospf_lsa_flush (top, lsa);
718e3744 2126
2127out:
2128 return;
2129}
2130
718e3744 2131void
87d6f87a 2132ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr,
69310a67 2133 struct ospf_lsa *lsa)
718e3744 2134{
2135 struct ospf *top;
801e0e14 2136
718e3744 2137 if ((top = oi_to_top (nbr->oi)) == NULL)
1fe6ed38 2138 return;
718e3744 2139
69310a67 2140 /*
2141 * Since these LSA entries are not yet installed into corresponding
2142 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2143 */
2144 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2145 switch (lsa->data->type)
718e3744 2146 {
69310a67 2147 case OSPF_OPAQUE_LINK_LSA:
69310a67 2148 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2149 break;
2150 case OSPF_OPAQUE_AREA_LSA:
69310a67 2151 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2152 break;
2153 case OSPF_OPAQUE_AS_LSA:
69310a67 2154 ospf_flood_through_as (top, NULL/*inbr*/, lsa);
2155 break;
2156 default:
2157 zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
1fe6ed38 2158 return;
718e3744 2159 }
801e0e14 2160 ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */
718e3744 2161}
2162
2163/*------------------------------------------------------------------------*
2164 * Followings are util functions; probably be used by Opaque-LSAs only...
2165 *------------------------------------------------------------------------*/
2166
718e3744 2167struct ospf *
2168oi_to_top (struct ospf_interface *oi)
2169{
2170 struct ospf *top = NULL;
2171 struct ospf_area *area;
2172
68980084 2173 if (oi == NULL || (area = oi->area) == NULL || (top = area->ospf) == NULL)
718e3744 2174 zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");
2175
2176 return top;
2177}
2178