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