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