]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_opaque.c
ospfd: Fix MI-OSPF configuraton clis
[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_INSTANCE_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_INSTANCE_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 (
1362 oipt->t_opaque_lsa_self
1363 != NULL /* Waiting for a thread call. */
1364 || oipt->status == PROC_SUSPEND) /* Cannot
1365 originate
1366 now. */
1367 continue;
1368
1369 ospf_opaque_lsa_reoriginate_schedule(
1370 (void *)oi, OSPF_OPAQUE_LINK_LSA,
1371 oipt->opaque_type);
1372 }
1373 }
1374
1375 if (!list_isempty(ospf_opaque_type10_funclist)
1376 && !list_isempty(area->opaque_lsa_self)) {
1377 for (ALL_LIST_ELEMENTS(area->opaque_lsa_self, node, nnode,
1378 oipt)) {
1379 /*
1380 * removed the test for
1381 * (! list_isempty (oipt->id_list)) * Handler is
1382 * already active. *
1383 * because opaque cababilities ON -> OFF -> ON result in
1384 * list_isempty (oipt->id_list)
1385 * not being empty.
1386 */
1387 if (
1388 oipt->t_opaque_lsa_self
1389 != NULL /* Waiting for a thread call. */
1390 || oipt->status == PROC_SUSPEND) /* Cannot
1391 originate
1392 now. */
1393 continue;
1394
1395 ospf_opaque_lsa_reoriginate_schedule(
1396 (void *)area, OSPF_OPAQUE_AREA_LSA,
1397 oipt->opaque_type);
1398 }
1399 }
1400
1401 if (!list_isempty(ospf_opaque_type11_funclist)
1402 && !list_isempty(top->opaque_lsa_self)) {
1403 for (ALL_LIST_ELEMENTS(top->opaque_lsa_self, node, nnode,
1404 oipt)) {
1405 /*
1406 * removed the test for
1407 * (! list_isempty (oipt->id_list)) * Handler is
1408 * already active. *
1409 * because opaque cababilities ON -> OFF -> ON result in
1410 * list_isempty (oipt->id_list)
1411 * not being empty.
1412 */
1413 if (
1414 oipt->t_opaque_lsa_self
1415 != NULL /* Waiting for a thread call. */
1416 || oipt->status == PROC_SUSPEND) /* Cannot
1417 originate
1418 now. */
1419 continue;
1420
1421 ospf_opaque_lsa_reoriginate_schedule((void *)top,
1422 OSPF_OPAQUE_AS_LSA,
1423 oipt->opaque_type);
1424 }
1425 }
1426
1427 if (delay0 != NULL)
1428 *delay0 = delay;
1429
1430 out:
1431 return;
1432 }
1433
1434 static int ospf_opaque_type9_lsa_originate(struct thread *t)
1435 {
1436 struct ospf_interface *oi;
1437 int rc;
1438
1439 oi = THREAD_ARG(t);
1440 oi->t_opaque_lsa_self = NULL;
1441
1442 if (IS_DEBUG_OSPF_EVENT)
1443 zlog_debug("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
1444 IF_NAME(oi));
1445
1446 rc = opaque_lsa_originate_callback(ospf_opaque_type9_funclist, oi);
1447
1448 return rc;
1449 }
1450
1451 static int ospf_opaque_type10_lsa_originate(struct thread *t)
1452 {
1453 struct ospf_area *area;
1454 int rc;
1455
1456 area = THREAD_ARG(t);
1457 area->t_opaque_lsa_self = NULL;
1458
1459 if (IS_DEBUG_OSPF_EVENT)
1460 zlog_debug(
1461 "Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
1462 inet_ntoa(area->area_id));
1463
1464 rc = opaque_lsa_originate_callback(ospf_opaque_type10_funclist, area);
1465
1466 return rc;
1467 }
1468
1469 static int ospf_opaque_type11_lsa_originate(struct thread *t)
1470 {
1471 struct ospf *top;
1472 int rc;
1473
1474 top = THREAD_ARG(t);
1475 top->t_opaque_lsa_self = NULL;
1476
1477 if (IS_DEBUG_OSPF_EVENT)
1478 zlog_debug(
1479 "Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
1480
1481 rc = opaque_lsa_originate_callback(ospf_opaque_type11_funclist, top);
1482
1483 return rc;
1484 }
1485
1486 static void ospf_opaque_lsa_reoriginate_resume(struct list *listtop, void *arg)
1487 {
1488 struct listnode *node, *nnode;
1489 struct opaque_info_per_type *oipt;
1490 struct ospf_opaque_functab *functab;
1491
1492 if (listtop == NULL)
1493 goto out;
1494
1495 /*
1496 * Pickup oipt entries those which in SUSPEND status, and give
1497 * them a chance to start re-origination now.
1498 */
1499 for (ALL_LIST_ELEMENTS(listtop, node, nnode, oipt)) {
1500 if (oipt->status != PROC_SUSPEND)
1501 continue;
1502
1503 oipt->status = PROC_NORMAL;
1504
1505 if ((functab = oipt->functab) == NULL
1506 || functab->lsa_originator == NULL)
1507 continue;
1508
1509 if ((*functab->lsa_originator)(arg) != 0) {
1510 zlog_warn(
1511 "ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)",
1512 oipt->opaque_type);
1513 continue;
1514 }
1515 }
1516
1517 out:
1518 return;
1519 }
1520
1521 struct ospf_lsa *ospf_opaque_lsa_install(struct ospf_lsa *lsa, int rt_recalc)
1522 {
1523 struct ospf_lsa *new = NULL;
1524 struct opaque_info_per_type *oipt;
1525 struct opaque_info_per_id *oipi;
1526 struct ospf *top;
1527
1528 /* Don't take "rt_recalc" into consideration for now. */ /* XXX */
1529
1530 if (!IS_LSA_SELF(lsa)) {
1531 new = lsa; /* Don't touch this LSA. */
1532 goto out;
1533 }
1534
1535 if (IS_DEBUG_OSPF(lsa, LSA_INSTALL))
1536 zlog_debug(
1537 "Install Type-%u Opaque-LSA: [opaque-type=%u, opaque-id=%x]",
1538 lsa->data->type,
1539 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)),
1540 GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)));
1541
1542 /* Replace the existing lsa with the new one. */
1543 if ((oipt = lookup_opaque_info_by_type(lsa)) != NULL
1544 && (oipi = lookup_opaque_info_by_id(oipt, lsa)) != NULL) {
1545 ospf_lsa_unlock(&oipi->lsa);
1546 oipi->lsa = ospf_lsa_lock(lsa);
1547 }
1548 /* Register the new lsa entry and get its control info. */
1549 else if ((oipi = register_opaque_lsa(lsa)) == NULL) {
1550 zlog_warn("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1551 goto out;
1552 }
1553
1554 /*
1555 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1556 * for periodic refresh of self-originated Opaque-LSAs.
1557 */
1558 switch (lsa->data->type) {
1559 case OSPF_OPAQUE_LINK_LSA:
1560 if ((top = oi_to_top(lsa->oi)) == NULL) {
1561 /* Above conditions must have passed. */
1562 zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?");
1563 goto out;
1564 }
1565 break;
1566 case OSPF_OPAQUE_AREA_LSA:
1567 if (lsa->area == NULL || (top = lsa->area->ospf) == NULL) {
1568 /* Above conditions must have passed. */
1569 zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?");
1570 goto out;
1571 }
1572 break;
1573 case OSPF_OPAQUE_AS_LSA:
1574 top = ospf_lookup();
1575 if (lsa->area != NULL && (top = lsa->area->ospf) == NULL) {
1576 /* Above conditions must have passed. */
1577 zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?");
1578 goto out;
1579 }
1580 break;
1581 default:
1582 zlog_warn("ospf_opaque_lsa_install: Unexpected LSA-type(%u)",
1583 lsa->data->type);
1584 goto out;
1585 }
1586
1587 ospf_refresher_register_lsa(top, lsa);
1588 new = lsa;
1589
1590 out:
1591 return new;
1592 }
1593
1594 struct ospf_lsa *ospf_opaque_lsa_refresh(struct ospf_lsa *lsa)
1595 {
1596 struct ospf *ospf;
1597 struct ospf_opaque_functab *functab;
1598 struct ospf_lsa *new = NULL;
1599
1600 ospf = ospf_lookup();
1601
1602 if ((functab = ospf_opaque_functab_lookup(lsa)) == NULL
1603 || functab->lsa_refresher == NULL) {
1604 /*
1605 * Though this LSA seems to have originated on this node, the
1606 * handling module for this "lsa-type and opaque-type" was
1607 * already deleted sometime ago.
1608 * Anyway, this node still has a responsibility to flush this
1609 * LSA from the routing domain.
1610 */
1611 if (IS_DEBUG_OSPF_EVENT)
1612 zlog_debug("LSA[Type%d:%s]: Flush stray Opaque-LSA",
1613 lsa->data->type, inet_ntoa(lsa->data->id));
1614
1615 lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
1616 ospf_lsa_flush(ospf, lsa);
1617 } else
1618 new = (*functab->lsa_refresher)(lsa);
1619
1620 return new;
1621 }
1622
1623 /*------------------------------------------------------------------------*
1624 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1625 * triggered by external interventions (vty session, signaling, etc).
1626 *------------------------------------------------------------------------*/
1627
1628 #define OSPF_OPAQUE_TIMER_ON(T,F,L,V) thread_add_timer_msec (master, (F), (L), (V), &(T))
1629
1630 static struct ospf_lsa *pseudo_lsa(struct ospf_interface *oi,
1631 struct ospf_area *area, u_char lsa_type,
1632 u_char opaque_type);
1633 static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread *t);
1634 static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread *t);
1635 static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread *t);
1636 static int ospf_opaque_lsa_refresh_timer(struct thread *t);
1637
1638 void ospf_opaque_lsa_reoriginate_schedule(void *lsa_type_dependent,
1639 u_char lsa_type, u_char opaque_type)
1640 {
1641 struct ospf *top;
1642 struct ospf_area dummy, *area = NULL;
1643 struct ospf_interface *oi = NULL;
1644
1645 struct ospf_lsa *lsa;
1646 struct opaque_info_per_type *oipt;
1647 int (*func)(struct thread * t) = NULL;
1648 int delay;
1649
1650 switch (lsa_type) {
1651 case OSPF_OPAQUE_LINK_LSA:
1652 if ((oi = (struct ospf_interface *)lsa_type_dependent)
1653 == NULL) {
1654 zlog_warn(
1655 "ospf_opaque_lsa_reoriginate_schedule:"
1656 " Type-9 Opaque-LSA: Invalid parameter?");
1657 goto out;
1658 }
1659 if ((top = oi_to_top(oi)) == NULL) {
1660 zlog_warn(
1661 "ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1662 IF_NAME(oi));
1663 goto out;
1664 }
1665 if (!list_isempty(ospf_opaque_type9_funclist)
1666 && list_isempty(oi->opaque_lsa_self)
1667 && oi->t_opaque_lsa_self != NULL) {
1668 zlog_warn(
1669 "Type-9 Opaque-LSA (opaque_type=%u):"
1670 " Common origination for OI(%s) has already started",
1671 opaque_type, IF_NAME(oi));
1672 goto out;
1673 }
1674 func = ospf_opaque_type9_lsa_reoriginate_timer;
1675 break;
1676 case OSPF_OPAQUE_AREA_LSA:
1677 if ((area = (struct ospf_area *)lsa_type_dependent) == NULL) {
1678 zlog_warn(
1679 "ospf_opaque_lsa_reoriginate_schedule:"
1680 " Type-10 Opaque-LSA: Invalid parameter?");
1681 goto out;
1682 }
1683 if ((top = area->ospf) == NULL) {
1684 zlog_warn(
1685 "ospf_opaque_lsa_reoriginate_schedule:"
1686 " AREA(%s) -> TOP?",
1687 inet_ntoa(area->area_id));
1688 goto out;
1689 }
1690 if (!list_isempty(ospf_opaque_type10_funclist)
1691 && list_isempty(area->opaque_lsa_self)
1692 && area->t_opaque_lsa_self != NULL) {
1693 zlog_warn(
1694 "Type-10 Opaque-LSA (opaque_type=%u):"
1695 " Common origination for AREA(%s) has already started",
1696 opaque_type, inet_ntoa(area->area_id));
1697 goto out;
1698 }
1699 func = ospf_opaque_type10_lsa_reoriginate_timer;
1700 break;
1701 case OSPF_OPAQUE_AS_LSA:
1702 if ((top = (struct ospf *)lsa_type_dependent) == NULL) {
1703 zlog_warn(
1704 "ospf_opaque_lsa_reoriginate_schedule:"
1705 " Type-11 Opaque-LSA: Invalid parameter?");
1706 goto out;
1707 }
1708 if (!list_isempty(ospf_opaque_type11_funclist)
1709 && list_isempty(top->opaque_lsa_self)
1710 && top->t_opaque_lsa_self != NULL) {
1711 zlog_warn(
1712 "Type-11 Opaque-LSA (opaque_type=%u):"
1713 " Common origination has already started",
1714 opaque_type);
1715 goto out;
1716 }
1717
1718 /* Fake "area" to pass "ospf" to a lookup function later. */
1719 dummy.ospf = top;
1720 area = &dummy;
1721
1722 func = ospf_opaque_type11_lsa_reoriginate_timer;
1723 break;
1724 default:
1725 zlog_warn(
1726 "ospf_opaque_lsa_reoriginate_schedule:"
1727 " Unexpected LSA-type(%u)",
1728 lsa_type);
1729 goto out;
1730 }
1731
1732 /* It may not a right time to schedule reorigination now. */
1733 if (!CHECK_FLAG(top->opaque, OPAQUE_OPERATION_READY_BIT)) {
1734 if (IS_DEBUG_OSPF_EVENT)
1735 zlog_debug(
1736 "ospf_opaque_lsa_reoriginate_schedule: Not operational.");
1737 goto out; /* This is not an error. */
1738 }
1739
1740 /* Generate a dummy lsa to be passed for a lookup function. */
1741 lsa = pseudo_lsa(oi, area, lsa_type, opaque_type);
1742
1743 if ((oipt = lookup_opaque_info_by_type(lsa)) == NULL) {
1744 struct ospf_opaque_functab *functab;
1745 if ((functab = ospf_opaque_functab_lookup(lsa)) == NULL) {
1746 zlog_warn(
1747 "ospf_opaque_lsa_reoriginate_schedule:"
1748 " No associated function?: lsa_type(%u),"
1749 " opaque_type(%u)",
1750 lsa_type, opaque_type);
1751 goto out;
1752 }
1753 if ((oipt = register_opaque_info_per_type(functab, lsa))
1754 == NULL) {
1755 zlog_warn(
1756 "ospf_opaque_lsa_reoriginate_schedule:"
1757 " Cannot get a control info?: lsa_type(%u),"
1758 " opaque_type(%u)",
1759 lsa_type, opaque_type);
1760 goto out;
1761 }
1762 }
1763
1764 if (oipt->t_opaque_lsa_self != NULL) {
1765 if (IS_DEBUG_OSPF_EVENT)
1766 zlog_debug(
1767 "Type-%u Opaque-LSA has already scheduled to"
1768 " RE-ORIGINATE: [opaque-type=%u]",
1769 lsa_type,
1770 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)));
1771 goto out;
1772 }
1773
1774 /*
1775 * Different from initial origination time, in which various conditions
1776 * (opaque capability, neighbor status etc) are assured by caller of
1777 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1778 * it is highly possible that these conditions might not be satisfied
1779 * at the time of re-origination function is to be called.
1780 */
1781 delay = top->min_ls_interval; /* XXX */
1782
1783 if (IS_DEBUG_OSPF_EVENT)
1784 zlog_debug(
1785 "Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
1786 " ms later: [opaque-type=%u]",
1787 lsa_type, delay,
1788 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)));
1789
1790 OSPF_OPAQUE_TIMER_ON(oipt->t_opaque_lsa_self, func, oipt, delay * 1000);
1791
1792 out:
1793 return;
1794 }
1795
1796 static struct ospf_lsa *pseudo_lsa(struct ospf_interface *oi,
1797 struct ospf_area *area, u_char lsa_type,
1798 u_char opaque_type)
1799 {
1800 static struct ospf_lsa lsa = {0};
1801 static struct lsa_header lsah = {0};
1802 u_int32_t tmp;
1803
1804 lsa.oi = oi;
1805 lsa.area = area;
1806 lsa.data = &lsah;
1807
1808 lsah.type = lsa_type;
1809 tmp = SET_OPAQUE_LSID(opaque_type, 0); /* Opaque-ID is unused here. */
1810 lsah.id.s_addr = htonl(tmp);
1811
1812 return &lsa;
1813 }
1814
1815 static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread *t)
1816 {
1817 struct opaque_info_per_type *oipt;
1818 struct ospf_opaque_functab *functab;
1819 struct ospf *top;
1820 struct ospf_interface *oi;
1821 int rc = -1;
1822
1823 oipt = THREAD_ARG(t);
1824 oipt->t_opaque_lsa_self = NULL;
1825
1826 if ((functab = oipt->functab) == NULL
1827 || functab->lsa_originator == NULL) {
1828 zlog_warn(
1829 "ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1830 goto out;
1831 }
1832
1833 oi = (struct ospf_interface *)oipt->owner;
1834 if ((top = oi_to_top(oi)) == NULL) {
1835 zlog_warn(
1836 "ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1837 goto out;
1838 }
1839
1840 if (!CHECK_FLAG(top->config, OSPF_OPAQUE_CAPABLE)
1841 || !ospf_if_is_enable(oi)
1842 || ospf_nbr_count_opaque_capable(oi) == 0) {
1843 if (IS_DEBUG_OSPF_EVENT)
1844 zlog_debug(
1845 "Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...",
1846 oipt->opaque_type);
1847
1848 oipt->status = PROC_SUSPEND;
1849 rc = 0;
1850 goto out;
1851 }
1852
1853 if (IS_DEBUG_OSPF_EVENT)
1854 zlog_debug(
1855 "Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)",
1856 oipt->opaque_type, IF_NAME(oi));
1857
1858 rc = (*functab->lsa_originator)(oi);
1859 out:
1860 return rc;
1861 }
1862
1863 static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread *t)
1864 {
1865 struct opaque_info_per_type *oipt;
1866 struct ospf_opaque_functab *functab;
1867 struct listnode *node, *nnode;
1868 struct ospf *top;
1869 struct ospf_area *area;
1870 struct ospf_interface *oi;
1871 int n, rc = -1;
1872
1873 oipt = THREAD_ARG(t);
1874 oipt->t_opaque_lsa_self = NULL;
1875
1876 if ((functab = oipt->functab) == NULL
1877 || functab->lsa_originator == NULL) {
1878 zlog_warn(
1879 "ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1880 goto out;
1881 }
1882
1883 area = (struct ospf_area *)oipt->owner;
1884 if (area == NULL || (top = area->ospf) == NULL) {
1885 zlog_warn(
1886 "ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1887 goto out;
1888 }
1889
1890 /* There must be at least one "opaque-capable, full-state" neighbor. */
1891 n = 0;
1892 for (ALL_LIST_ELEMENTS(area->oiflist, node, nnode, oi)) {
1893 if ((n = ospf_nbr_count_opaque_capable(oi)) > 0)
1894 break;
1895 }
1896
1897 if (n == 0 || !CHECK_FLAG(top->config, OSPF_OPAQUE_CAPABLE)) {
1898 if (IS_DEBUG_OSPF_EVENT)
1899 zlog_debug(
1900 "Suspend re-origination of Type-10 Opaque-LSAs"
1901 " (opaque-type=%u) for a while...",
1902 oipt->opaque_type);
1903
1904 oipt->status = PROC_SUSPEND;
1905 rc = 0;
1906 goto out;
1907 }
1908
1909 if (IS_DEBUG_OSPF_EVENT)
1910 zlog_debug(
1911 "Timer[Type10-LSA]: Re-originate Opaque-LSAs"
1912 " (opaque-type=%u) for Area %s",
1913 oipt->opaque_type, inet_ntoa(area->area_id));
1914
1915 rc = (*functab->lsa_originator)(area);
1916 out:
1917 return rc;
1918 }
1919
1920 static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread *t)
1921 {
1922 struct opaque_info_per_type *oipt;
1923 struct ospf_opaque_functab *functab;
1924 struct ospf *top;
1925 int rc = -1;
1926
1927 oipt = THREAD_ARG(t);
1928 oipt->t_opaque_lsa_self = NULL;
1929
1930 if ((functab = oipt->functab) == NULL
1931 || functab->lsa_originator == NULL) {
1932 zlog_warn(
1933 "ospf_opaque_type11_lsa_reoriginate_timer:"
1934 " No associated function?");
1935 goto out;
1936 }
1937
1938 if ((top = (struct ospf *)oipt->owner) == NULL) {
1939 zlog_warn(
1940 "ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1941 goto out;
1942 }
1943
1944 if (!CHECK_FLAG(top->config, OSPF_OPAQUE_CAPABLE)) {
1945 if (IS_DEBUG_OSPF_EVENT)
1946 zlog_debug(
1947 "Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...",
1948 oipt->opaque_type);
1949
1950 oipt->status = PROC_SUSPEND;
1951 rc = 0;
1952 goto out;
1953 }
1954
1955 if (IS_DEBUG_OSPF_EVENT)
1956 zlog_debug(
1957 "Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).",
1958 oipt->opaque_type);
1959
1960 rc = (*functab->lsa_originator)(top);
1961 out:
1962 return rc;
1963 }
1964
1965 void ospf_opaque_lsa_refresh_schedule(struct ospf_lsa *lsa0)
1966 {
1967 struct opaque_info_per_type *oipt;
1968 struct opaque_info_per_id *oipi;
1969 struct ospf_lsa *lsa;
1970 struct ospf *top;
1971 int delay;
1972
1973 if ((oipt = lookup_opaque_info_by_type(lsa0)) == NULL
1974 || (oipi = lookup_opaque_info_by_id(oipt, lsa0)) == NULL) {
1975 zlog_warn(
1976 "ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
1977 goto out;
1978 }
1979
1980 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
1981 if ((lsa = oipi->lsa) == NULL) {
1982 zlog_warn("ospf_opaque_lsa_refresh_schedule: Something wrong?");
1983 goto out;
1984 }
1985
1986 if (oipi->t_opaque_lsa_self != NULL) {
1987 if (IS_DEBUG_OSPF_EVENT)
1988 zlog_debug(
1989 "Type-%u Opaque-LSA has already scheduled to REFRESH: [opaque-type=%u, opaque-id=%x]",
1990 lsa->data->type,
1991 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)),
1992 GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)));
1993 goto out;
1994 }
1995
1996 /* Delete this lsa from neighbor retransmit-list. */
1997 switch (lsa->data->type) {
1998 case OSPF_OPAQUE_LINK_LSA:
1999 case OSPF_OPAQUE_AREA_LSA:
2000 ospf_ls_retransmit_delete_nbr_area(lsa->area, lsa);
2001 break;
2002 case OSPF_OPAQUE_AS_LSA:
2003 top = ospf_lookup();
2004 if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
2005 top = lsa0->area->ospf;
2006 ospf_ls_retransmit_delete_nbr_as(top, lsa);
2007 break;
2008 default:
2009 zlog_warn(
2010 "ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)",
2011 lsa->data->type);
2012 goto out;
2013 }
2014
2015 delay = ospf_lsa_refresh_delay(lsa);
2016
2017 if (IS_DEBUG_OSPF_EVENT)
2018 zlog_debug(
2019 "Schedule Type-%u Opaque-LSA to REFRESH in %d sec later: [opaque-type=%u, opaque-id=%x]",
2020 lsa->data->type, delay,
2021 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)),
2022 GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)));
2023
2024 OSPF_OPAQUE_TIMER_ON(oipi->t_opaque_lsa_self,
2025 ospf_opaque_lsa_refresh_timer, oipi, delay * 1000);
2026 out:
2027 return;
2028 }
2029
2030 static int ospf_opaque_lsa_refresh_timer(struct thread *t)
2031 {
2032 struct opaque_info_per_id *oipi;
2033 struct ospf_opaque_functab *functab;
2034 struct ospf_lsa *lsa;
2035
2036 if (IS_DEBUG_OSPF_EVENT)
2037 zlog_debug("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
2038
2039 oipi = THREAD_ARG(t);
2040 oipi->t_opaque_lsa_self = NULL;
2041
2042 if ((lsa = oipi->lsa) != NULL)
2043 if ((functab = oipi->opqctl_type->functab) != NULL)
2044 if (functab->lsa_refresher != NULL)
2045 (*functab->lsa_refresher)(lsa);
2046
2047 return 0;
2048 }
2049
2050 void ospf_opaque_lsa_flush_schedule(struct ospf_lsa *lsa0)
2051 {
2052 struct opaque_info_per_type *oipt;
2053 struct opaque_info_per_id *oipi;
2054 struct ospf_lsa *lsa;
2055 struct ospf *top;
2056
2057 top = ospf_lookup();
2058
2059 if ((oipt = lookup_opaque_info_by_type(lsa0)) == NULL
2060 || (oipi = lookup_opaque_info_by_id(oipt, lsa0)) == NULL) {
2061 zlog_warn("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2062 goto out;
2063 }
2064
2065 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2066 if ((lsa = oipi->lsa) == NULL) {
2067 zlog_warn("ospf_opaque_lsa_flush_schedule: Something wrong?");
2068 goto out;
2069 }
2070
2071 /* Delete this lsa from neighbor retransmit-list. */
2072 switch (lsa->data->type) {
2073 case OSPF_OPAQUE_LINK_LSA:
2074 case OSPF_OPAQUE_AREA_LSA:
2075 ospf_ls_retransmit_delete_nbr_area(lsa->area, lsa);
2076 break;
2077 case OSPF_OPAQUE_AS_LSA:
2078 if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
2079 top = lsa0->area->ospf;
2080 ospf_ls_retransmit_delete_nbr_as(top, lsa);
2081 break;
2082 default:
2083 zlog_warn(
2084 "ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)",
2085 lsa->data->type);
2086 goto out;
2087 }
2088
2089 /* Dequeue listnode entry from the list. */
2090 listnode_delete(oipt->id_list, oipi);
2091
2092 /* Avoid misjudgement in the next lookup. */
2093 if (listcount(oipt->id_list) == 0)
2094 oipt->id_list->head = oipt->id_list->tail = NULL;
2095
2096 /* Disassociate internal control information with the given lsa. */
2097 free_opaque_info_per_id((void *)oipi);
2098
2099 /* Force given lsa's age to MaxAge. */
2100 lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
2101
2102 if (IS_DEBUG_OSPF_EVENT)
2103 zlog_debug(
2104 "Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]",
2105 lsa->data->type,
2106 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)),
2107 GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)));
2108
2109 /* This lsa will be flushed and removed eventually. */
2110 ospf_lsa_flush(top, lsa);
2111
2112 out:
2113 return;
2114 }
2115
2116 void ospf_opaque_self_originated_lsa_received(struct ospf_neighbor *nbr,
2117 struct ospf_lsa *lsa)
2118 {
2119 struct ospf *top;
2120
2121 if ((top = oi_to_top(nbr->oi)) == NULL)
2122 return;
2123
2124 /*
2125 * Since these LSA entries are not yet installed into corresponding
2126 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2127 */
2128 lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
2129 switch (lsa->data->type) {
2130 case OSPF_OPAQUE_LINK_LSA:
2131 ospf_flood_through_area(nbr->oi->area, NULL /*inbr*/, lsa);
2132 break;
2133 case OSPF_OPAQUE_AREA_LSA:
2134 ospf_flood_through_area(nbr->oi->area, NULL /*inbr*/, lsa);
2135 break;
2136 case OSPF_OPAQUE_AS_LSA:
2137 ospf_flood_through_as(top, NULL /*inbr*/, lsa);
2138 break;
2139 default:
2140 zlog_warn(
2141 "ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)",
2142 lsa->data->type);
2143 return;
2144 }
2145 ospf_lsa_discard(lsa); /* List "lsas" will be deleted by caller. */
2146 }
2147
2148 /*------------------------------------------------------------------------*
2149 * Followings are util functions; probably be used by Opaque-LSAs only...
2150 *------------------------------------------------------------------------*/
2151
2152 struct ospf *oi_to_top(struct ospf_interface *oi)
2153 {
2154 struct ospf *top = NULL;
2155 struct ospf_area *area;
2156
2157 if (oi == NULL || (area = oi->area) == NULL
2158 || (top = area->ospf) == NULL)
2159 zlog_warn("Broken relationship for \"OI -> AREA -> OSPF\"?");
2160
2161 return top;
2162 }