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