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