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