]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_opaque.c
Merge remote-tracking branch 'origin/stable/2.0'
[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_out (vty, " capability opaque%s", VTY_NEWLINE);
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_out (vty, " Opaque-Type %u (%s)%s", opaque_type,
1193 ospf_opaque_type_name (opaque_type), VTY_NEWLINE);
1194 vty_out (vty, " Opaque-ID 0x%x%s", opaque_id, VTY_NEWLINE);
1195
1196 vty_out (vty, " Opaque-Info: %u octets of data%s%s",
1197 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1198 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)",
1199 VTY_NEWLINE);
1200 }
1201 else
1202 {
1203 zlog_debug (" Opaque-Type %u (%s)", opaque_type,
1204 ospf_opaque_type_name (opaque_type));
1205 zlog_debug (" Opaque-ID 0x%x", opaque_id);
1206
1207 zlog_debug (" Opaque-Info: %u octets of data%s",
1208 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1209 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)");
1210 }
1211
1212 /* Call individual output functions. */
1213 if ((functab = ospf_opaque_functab_lookup (lsa)) != NULL)
1214 if (functab->show_opaque_info != NULL)
1215 (* functab->show_opaque_info)(vty, lsa);
1216
1217 return;
1218 }
1219
1220 void
1221 ospf_opaque_lsa_dump (struct stream *s, u_int16_t length)
1222 {
1223 struct ospf_lsa lsa;
1224
1225 lsa.data = (struct lsa_header *) STREAM_PNT (s);
1226 show_opaque_info_detail (NULL, &lsa);
1227 return;
1228 }
1229
1230 static int
1231 ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa)
1232 {
1233 struct list *funclist;
1234 int rc = -1;
1235
1236 /*
1237 * Some Opaque-LSA user may want to monitor every LSA installation
1238 * into the LSDB, regardless with target LSA type.
1239 */
1240 funclist = ospf_opaque_wildcard_funclist;
1241 if (new_lsa_callback (funclist, lsa) != 0)
1242 goto out;
1243
1244 funclist = ospf_opaque_type9_funclist;
1245 if (new_lsa_callback (funclist, lsa) != 0)
1246 goto out;
1247
1248 funclist = ospf_opaque_type10_funclist;
1249 if (new_lsa_callback (funclist, lsa) != 0)
1250 goto out;
1251
1252 funclist = ospf_opaque_type11_funclist;
1253 if (new_lsa_callback (funclist, lsa) != 0)
1254 goto out;
1255
1256 rc = 0;
1257 out:
1258 return rc;
1259 }
1260
1261 static int
1262 ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa)
1263 {
1264 struct list *funclist;
1265 int rc = -1;
1266
1267 /*
1268 * Some Opaque-LSA user may want to monitor every LSA deletion
1269 * from the LSDB, regardless with target LSA type.
1270 */
1271 funclist = ospf_opaque_wildcard_funclist;
1272 if (del_lsa_callback (funclist, lsa) != 0)
1273 goto out;
1274
1275 funclist = ospf_opaque_type9_funclist;
1276 if (del_lsa_callback (funclist, lsa) != 0)
1277 goto out;
1278
1279 funclist = ospf_opaque_type10_funclist;
1280 if (del_lsa_callback (funclist, lsa) != 0)
1281 goto out;
1282
1283 funclist = ospf_opaque_type11_funclist;
1284 if (del_lsa_callback (funclist, lsa) != 0)
1285 goto out;
1286
1287 rc = 0;
1288 out:
1289 return rc;
1290 }
1291
1292 /*------------------------------------------------------------------------*
1293 * Followings are Opaque-LSA origination/refresh management functions.
1294 *------------------------------------------------------------------------*/
1295
1296 static int ospf_opaque_type9_lsa_originate (struct thread *t);
1297 static int ospf_opaque_type10_lsa_originate (struct thread *t);
1298 static int ospf_opaque_type11_lsa_originate (struct thread *t);
1299 static void ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg);
1300
1301 void
1302 ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0)
1303 {
1304 struct ospf *top;
1305 struct ospf_area *area;
1306 struct listnode *node, *nnode;
1307 struct opaque_info_per_type *oipt;
1308 int delay = 0;
1309
1310 if ((top = oi_to_top (oi)) == NULL || (area = oi->area) == NULL)
1311 {
1312 zlog_warn ("ospf_opaque_lsa_originate_schedule: Invalid argument?");
1313 goto out;
1314 }
1315
1316 /* It may not a right time to schedule origination now. */
1317 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1318 {
1319 if (IS_DEBUG_OSPF_EVENT)
1320 zlog_debug ("ospf_opaque_lsa_originate_schedule: Not operational.");
1321 goto out; /* This is not an error. */
1322 }
1323
1324 if (delay0 != NULL)
1325 delay = *delay0;
1326
1327 /*
1328 * There might be some entries that have been waiting for triggering
1329 * of per opaque-type re-origination get resumed.
1330 */
1331 ospf_opaque_lsa_reoriginate_resume ( oi->opaque_lsa_self, (void *) oi);
1332 ospf_opaque_lsa_reoriginate_resume (area->opaque_lsa_self, (void *) area);
1333 ospf_opaque_lsa_reoriginate_resume ( top->opaque_lsa_self, (void *) top);
1334
1335 /*
1336 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1337 */
1338 if (! list_isempty (ospf_opaque_type9_funclist)
1339 && list_isempty (oi->opaque_lsa_self)
1340 && oi->t_opaque_lsa_self == NULL)
1341 {
1342 if (IS_DEBUG_OSPF_EVENT)
1343 zlog_debug ("Schedule Type-9 Opaque-LSA origination in %d ms later.", delay);
1344 oi->t_opaque_lsa_self = NULL;
1345 thread_add_timer_msec(master, ospf_opaque_type9_lsa_originate, oi, delay,
1346 &oi->t_opaque_lsa_self);
1347 delay += top->min_ls_interval;
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)
1360 zlog_debug ("Schedule Type-10 Opaque-LSA origination in %d ms later.", delay);
1361 area->t_opaque_lsa_self = NULL;
1362 thread_add_timer_msec(master, ospf_opaque_type10_lsa_originate, area, delay,
1363 &area->t_opaque_lsa_self);
1364 delay += top->min_ls_interval;
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)
1377 zlog_debug ("Schedule Type-11 Opaque-LSA origination in %d ms later.", delay);
1378 top->t_opaque_lsa_self = NULL;
1379 thread_add_timer_msec(master, ospf_opaque_type11_lsa_originate, top, delay,
1380 &top->t_opaque_lsa_self);
1381 delay += top->min_ls_interval;
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 {
1391 for (ALL_LIST_ELEMENTS (oi->opaque_lsa_self, node, nnode, oipt))
1392 {
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 */
1399 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1400 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
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 {
1411 for (ALL_LIST_ELEMENTS (area->opaque_lsa_self, node, nnode, oipt))
1412 {
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 */
1419 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1420 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
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 {
1431 for (ALL_LIST_ELEMENTS (top->opaque_lsa_self, node, nnode, oipt))
1432 {
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 */
1439 if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1440 || oipt->status == PROC_SUSPEND) /* Cannot originate now. */
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
1451 out:
1452 return;
1453 }
1454
1455 static int
1456 ospf_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)
1465 zlog_debug ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
1466 IF_NAME (oi));
1467
1468 rc = opaque_lsa_originate_callback (ospf_opaque_type9_funclist, oi);
1469
1470 return rc;
1471 }
1472
1473 static int
1474 ospf_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)
1483 zlog_debug ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
1484 inet_ntoa (area->area_id));
1485
1486 rc = opaque_lsa_originate_callback (ospf_opaque_type10_funclist, area);
1487
1488 return rc;
1489 }
1490
1491 static int
1492 ospf_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)
1501 zlog_debug ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
1502
1503 rc = opaque_lsa_originate_callback (ospf_opaque_type11_funclist, top);
1504
1505 return rc;
1506 }
1507
1508 static void
1509 ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg)
1510 {
1511 struct listnode *node, *nnode;
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 */
1522 for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt))
1523 {
1524 if (oipt->status != PROC_SUSPEND)
1525 continue;
1526
1527 oipt->status = PROC_NORMAL;
1528
1529 if ((functab = oipt->functab) == NULL
1530 || functab->lsa_originator == NULL)
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
1540 out:
1541 return;
1542 }
1543
1544 struct ospf_lsa *
1545 ospf_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))
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)));
1562
1563 /* Replace the existing lsa with the new one. */
1564 if ((oipt = lookup_opaque_info_by_type (lsa)) != NULL
1565 && (oipi = lookup_opaque_info_by_id (oipt, lsa)) != NULL)
1566 {
1567 ospf_lsa_unlock (&oipi->lsa);
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:
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;
1592 case OSPF_OPAQUE_AREA_LSA:
1593 if (lsa->area == NULL || (top = lsa->area->ospf) == NULL)
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:
1601 top = ospf_lookup ();
1602 if (lsa->area != NULL && (top = lsa->area->ospf) == NULL)
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
1617 out:
1618 return new;
1619 }
1620
1621 struct ospf_lsa *
1622 ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
1623 {
1624 struct ospf *ospf;
1625 struct ospf_opaque_functab *functab;
1626 struct ospf_lsa *new = NULL;
1627
1628 ospf = ospf_lookup ();
1629
1630 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL
1631 || functab->lsa_refresher == NULL)
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)
1641 zlog_debug ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id));
1642
1643 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
1644 ospf_lsa_flush (ospf, lsa);
1645 }
1646 else
1647 new = (* functab->lsa_refresher)(lsa);
1648
1649 return new;
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) thread_add_timer_msec (master, (F), (L), (V), &(T))
1658
1659 static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type);
1660 static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t);
1661 static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t);
1662 static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t);
1663 static int ospf_opaque_lsa_refresh_timer (struct thread *t);
1664
1665 void
1666 ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
1667 u_char lsa_type, u_char opaque_type)
1668 {
1669 struct ospf *top;
1670 struct ospf_area dummy, *area = NULL;
1671 struct ospf_interface *oi = NULL;
1672
1673 struct ospf_lsa *lsa;
1674 struct opaque_info_per_type *oipt;
1675 int (*func) (struct thread * t) = NULL;
1676 int delay;
1677
1678 switch (lsa_type)
1679 {
1680 case OSPF_OPAQUE_LINK_LSA:
1681 if ((oi = (struct ospf_interface *) lsa_type_dependent) == NULL)
1682 {
1683 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1684 " Type-9 Opaque-LSA: Invalid parameter?");
1685 goto out;
1686 }
1687 if ((top = oi_to_top (oi)) == NULL)
1688 {
1689 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1690 IF_NAME (oi));
1691 goto out;
1692 }
1693 if (!list_isempty (ospf_opaque_type9_funclist)
1694 && list_isempty (oi->opaque_lsa_self)
1695 && oi->t_opaque_lsa_self != NULL)
1696 {
1697 zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u):"
1698 " Common origination for OI(%s) has already started",
1699 opaque_type, IF_NAME (oi));
1700 goto out;
1701 }
1702 func = ospf_opaque_type9_lsa_reoriginate_timer;
1703 break;
1704 case OSPF_OPAQUE_AREA_LSA:
1705 if ((area = (struct ospf_area *) lsa_type_dependent) == NULL)
1706 {
1707 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1708 " Type-10 Opaque-LSA: Invalid parameter?");
1709 goto out;
1710 }
1711 if ((top = area->ospf) == NULL)
1712 {
1713 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1714 " AREA(%s) -> TOP?", inet_ntoa (area->area_id));
1715 goto out;
1716 }
1717 if (!list_isempty (ospf_opaque_type10_funclist)
1718 && list_isempty (area->opaque_lsa_self)
1719 && area->t_opaque_lsa_self != NULL)
1720 {
1721 zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u):"
1722 " Common origination for AREA(%s) has already started",
1723 opaque_type, inet_ntoa (area->area_id));
1724 goto out;
1725 }
1726 func = ospf_opaque_type10_lsa_reoriginate_timer;
1727 break;
1728 case OSPF_OPAQUE_AS_LSA:
1729 if ((top = (struct ospf *) lsa_type_dependent) == NULL)
1730 {
1731 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1732 " Type-11 Opaque-LSA: Invalid parameter?");
1733 goto out;
1734 }
1735 if (!list_isempty (ospf_opaque_type11_funclist)
1736 && list_isempty (top->opaque_lsa_self)
1737 && top->t_opaque_lsa_self != NULL)
1738 {
1739 zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u):"
1740 " Common origination has already started", opaque_type);
1741 goto out;
1742 }
1743
1744 /* Fake "area" to pass "ospf" to a lookup function later. */
1745 dummy.ospf = top;
1746 area = &dummy;
1747
1748 func = ospf_opaque_type11_lsa_reoriginate_timer;
1749 break;
1750 default:
1751 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1752 " Unexpected LSA-type(%u)",
1753 lsa_type);
1754 goto out;
1755 }
1756
1757 /* It may not a right time to schedule reorigination now. */
1758 if (!CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1759 {
1760 if (IS_DEBUG_OSPF_EVENT)
1761 zlog_debug ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
1762 goto out; /* This is not an error. */
1763 }
1764
1765 /* Generate a dummy lsa to be passed for a lookup function. */
1766 lsa = pseudo_lsa (oi, area, lsa_type, opaque_type);
1767
1768 if ((oipt = lookup_opaque_info_by_type (lsa)) == NULL)
1769 {
1770 struct ospf_opaque_functab *functab;
1771 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL)
1772 {
1773 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1774 " No associated function?: lsa_type(%u),"
1775 " opaque_type(%u)",
1776 lsa_type, opaque_type);
1777 goto out;
1778 }
1779 if ((oipt = register_opaque_info_per_type (functab, lsa)) == NULL)
1780 {
1781 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
1782 " Cannot get a control info?: lsa_type(%u),"
1783 " opaque_type(%u)",
1784 lsa_type, opaque_type);
1785 goto out;
1786 }
1787 }
1788
1789 if (oipt->t_opaque_lsa_self != NULL)
1790 {
1791 if (IS_DEBUG_OSPF_EVENT)
1792 zlog_debug ("Type-%u Opaque-LSA has already scheduled to"
1793 " RE-ORIGINATE: [opaque-type=%u]",
1794 lsa_type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
1795 goto out;
1796 }
1797
1798 /*
1799 * Different from initial origination time, in which various conditions
1800 * (opaque capability, neighbor status etc) are assured by caller of
1801 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1802 * it is highly possible that these conditions might not be satisfied
1803 * at the time of re-origination function is to be called.
1804 */
1805 delay = top->min_ls_interval; /* XXX */
1806
1807 if (IS_DEBUG_OSPF_EVENT)
1808 zlog_debug ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
1809 " ms later: [opaque-type=%u]",
1810 lsa_type, delay,
1811 GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
1812
1813 OSPF_OPAQUE_TIMER_ON (oipt->t_opaque_lsa_self, func, oipt, delay * 1000);
1814
1815 out:
1816 return;
1817 }
1818
1819 static struct ospf_lsa *
1820 pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area,
1821 u_char lsa_type, u_char opaque_type)
1822 {
1823 static struct ospf_lsa lsa = { 0 };
1824 static struct lsa_header lsah = { 0 };
1825 u_int32_t tmp;
1826
1827 lsa.oi = oi;
1828 lsa.area = area;
1829 lsa.data = &lsah;
1830
1831 lsah.type = lsa_type;
1832 tmp = SET_OPAQUE_LSID (opaque_type, 0); /* Opaque-ID is unused here. */
1833 lsah.id.s_addr = htonl (tmp);
1834
1835 return &lsa;
1836 }
1837
1838 static int
1839 ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t)
1840 {
1841 struct opaque_info_per_type *oipt;
1842 struct ospf_opaque_functab *functab;
1843 struct ospf *top;
1844 struct ospf_interface *oi;
1845 int rc = -1;
1846
1847 oipt = THREAD_ARG (t);
1848 oipt->t_opaque_lsa_self = NULL;
1849
1850 if ((functab = oipt->functab) == NULL
1851 || functab->lsa_originator == NULL)
1852 {
1853 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1854 goto out;
1855 }
1856
1857 oi = (struct ospf_interface *) oipt->owner;
1858 if ((top = oi_to_top (oi)) == NULL)
1859 {
1860 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1861 goto out;
1862 }
1863
1864 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)
1865 || ! ospf_if_is_enable (oi)
1866 || ospf_nbr_count_opaque_capable (oi) == 0)
1867 {
1868 if (IS_DEBUG_OSPF_EVENT)
1869 zlog_debug ("Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
1870
1871 oipt->status = PROC_SUSPEND;
1872 rc = 0;
1873 goto out;
1874 }
1875
1876 if (IS_DEBUG_OSPF_EVENT)
1877 zlog_debug ("Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)", oipt->opaque_type, IF_NAME (oi));
1878
1879 rc = (* functab->lsa_originator)(oi);
1880 out:
1881 return rc;
1882 }
1883
1884 static int
1885 ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t)
1886 {
1887 struct opaque_info_per_type *oipt;
1888 struct ospf_opaque_functab *functab;
1889 struct listnode *node, *nnode;
1890 struct ospf *top;
1891 struct ospf_area *area;
1892 struct ospf_interface *oi;
1893 int n, rc = -1;
1894
1895 oipt = THREAD_ARG (t);
1896 oipt->t_opaque_lsa_self = NULL;
1897
1898 if ((functab = oipt->functab) == NULL
1899 || functab->lsa_originator == NULL)
1900 {
1901 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1902 goto out;
1903 }
1904
1905 area = (struct ospf_area *) oipt->owner;
1906 if (area == NULL || (top = area->ospf) == NULL)
1907 {
1908 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1909 goto out;
1910 }
1911
1912 /* There must be at least one "opaque-capable, full-state" neighbor. */
1913 n = 0;
1914 for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi))
1915 {
1916 if ((n = ospf_nbr_count_opaque_capable (oi)) > 0)
1917 break;
1918 }
1919
1920 if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1921 {
1922 if (IS_DEBUG_OSPF_EVENT)
1923 zlog_debug ("Suspend re-origination of Type-10 Opaque-LSAs"
1924 " (opaque-type=%u) for a while...",
1925 oipt->opaque_type);
1926
1927 oipt->status = PROC_SUSPEND;
1928 rc = 0;
1929 goto out;
1930 }
1931
1932 if (IS_DEBUG_OSPF_EVENT)
1933 zlog_debug ("Timer[Type10-LSA]: Re-originate Opaque-LSAs"
1934 " (opaque-type=%u) for Area %s",
1935 oipt->opaque_type, inet_ntoa (area->area_id));
1936
1937 rc = (* functab->lsa_originator)(area);
1938 out:
1939 return rc;
1940 }
1941
1942 static int
1943 ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t)
1944 {
1945 struct opaque_info_per_type *oipt;
1946 struct ospf_opaque_functab *functab;
1947 struct ospf *top;
1948 int rc = -1;
1949
1950 oipt = THREAD_ARG (t);
1951 oipt->t_opaque_lsa_self = NULL;
1952
1953 if ((functab = oipt->functab) == NULL
1954 || functab->lsa_originator == NULL)
1955 {
1956 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer:"
1957 " No associated function?");
1958 goto out;
1959 }
1960
1961 if ((top = (struct ospf *) oipt->owner) == NULL)
1962 {
1963 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1964 goto out;
1965 }
1966
1967 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1968 {
1969 if (IS_DEBUG_OSPF_EVENT)
1970 zlog_debug ("Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
1971
1972 oipt->status = PROC_SUSPEND;
1973 rc = 0;
1974 goto out;
1975 }
1976
1977 if (IS_DEBUG_OSPF_EVENT)
1978 zlog_debug ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type);
1979
1980 rc = (* functab->lsa_originator)(top);
1981 out:
1982 return rc;
1983 }
1984
1985 void
1986 ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
1987 {
1988 struct opaque_info_per_type *oipt;
1989 struct opaque_info_per_id *oipi;
1990 struct ospf_lsa *lsa;
1991 struct ospf *top;
1992 int delay;
1993
1994 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
1995 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
1996 {
1997 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
1998 goto out;
1999 }
2000
2001 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2002 if ((lsa = oipi->lsa) == NULL)
2003 {
2004 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
2005 goto out;
2006 }
2007
2008 if (oipi->t_opaque_lsa_self != NULL)
2009 {
2010 if (IS_DEBUG_OSPF_EVENT)
2011 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)));
2012 goto out;
2013 }
2014
2015 /* Delete this lsa from neighbor retransmit-list. */
2016 switch (lsa->data->type)
2017 {
2018 case OSPF_OPAQUE_LINK_LSA:
2019 case OSPF_OPAQUE_AREA_LSA:
2020 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
2021 break;
2022 case OSPF_OPAQUE_AS_LSA:
2023 top = ospf_lookup ();
2024 if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
2025 top = lsa0->area->ospf;
2026 ospf_ls_retransmit_delete_nbr_as (top, lsa);
2027 break;
2028 default:
2029 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2030 goto out;
2031 }
2032
2033 delay = ospf_lsa_refresh_delay (lsa);
2034
2035 if (IS_DEBUG_OSPF_EVENT)
2036 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)));
2037
2038 OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self,
2039 ospf_opaque_lsa_refresh_timer, oipi, delay * 1000);
2040 out:
2041 return;
2042 }
2043
2044 static int
2045 ospf_opaque_lsa_refresh_timer (struct thread *t)
2046 {
2047 struct opaque_info_per_id *oipi;
2048 struct ospf_opaque_functab *functab;
2049 struct ospf_lsa *lsa;
2050
2051 if (IS_DEBUG_OSPF_EVENT)
2052 zlog_debug ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
2053
2054 oipi = THREAD_ARG (t);
2055 oipi->t_opaque_lsa_self = NULL;
2056
2057 if ((lsa = oipi->lsa) != NULL)
2058 if ((functab = oipi->opqctl_type->functab) != NULL)
2059 if (functab->lsa_refresher != NULL)
2060 (* functab->lsa_refresher)(lsa);
2061
2062 return 0;
2063 }
2064
2065 void
2066 ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
2067 {
2068 struct opaque_info_per_type *oipt;
2069 struct opaque_info_per_id *oipi;
2070 struct ospf_lsa *lsa;
2071 struct ospf *top;
2072
2073 top = ospf_lookup ();
2074
2075 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
2076 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
2077 {
2078 zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2079 goto out;
2080 }
2081
2082 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2083 if ((lsa = oipi->lsa) == NULL)
2084 {
2085 zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
2086 goto out;
2087 }
2088
2089 /* Delete this lsa from neighbor retransmit-list. */
2090 switch (lsa->data->type)
2091 {
2092 case OSPF_OPAQUE_LINK_LSA:
2093 case OSPF_OPAQUE_AREA_LSA:
2094 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
2095 break;
2096 case OSPF_OPAQUE_AS_LSA:
2097 if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
2098 top = lsa0->area->ospf;
2099 ospf_ls_retransmit_delete_nbr_as (top, lsa);
2100 break;
2101 default:
2102 zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2103 goto out;
2104 }
2105
2106 /* Dequeue listnode entry from the list. */
2107 listnode_delete (oipt->id_list, oipi);
2108
2109 /* Avoid misjudgement in the next lookup. */
2110 if (listcount (oipt->id_list) == 0)
2111 oipt->id_list->head = oipt->id_list->tail = NULL;
2112
2113 /* Disassociate internal control information with the given lsa. */
2114 free_opaque_info_per_id ((void *) oipi);
2115
2116 /* Force given lsa's age to MaxAge. */
2117 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2118
2119 if (IS_DEBUG_OSPF_EVENT)
2120 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)));
2121
2122 /* This lsa will be flushed and removed eventually. */
2123 ospf_lsa_flush (top, lsa);
2124
2125 out:
2126 return;
2127 }
2128
2129 void
2130 ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr,
2131 struct ospf_lsa *lsa)
2132 {
2133 struct ospf *top;
2134
2135 if ((top = oi_to_top (nbr->oi)) == NULL)
2136 return;
2137
2138 /*
2139 * Since these LSA entries are not yet installed into corresponding
2140 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2141 */
2142 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2143 switch (lsa->data->type)
2144 {
2145 case OSPF_OPAQUE_LINK_LSA:
2146 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2147 break;
2148 case OSPF_OPAQUE_AREA_LSA:
2149 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2150 break;
2151 case OSPF_OPAQUE_AS_LSA:
2152 ospf_flood_through_as (top, NULL/*inbr*/, lsa);
2153 break;
2154 default:
2155 zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
2156 return;
2157 }
2158 ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */
2159 }
2160
2161 /*------------------------------------------------------------------------*
2162 * Followings are util functions; probably be used by Opaque-LSAs only...
2163 *------------------------------------------------------------------------*/
2164
2165 struct ospf *
2166 oi_to_top (struct ospf_interface *oi)
2167 {
2168 struct ospf *top = NULL;
2169 struct ospf_area *area;
2170
2171 if (oi == NULL || (area = oi->area) == NULL || (top = area->ospf) == NULL)
2172 zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");
2173
2174 return top;
2175 }
2176