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