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