]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_opaque.c
Merge pull request #2805 from opensourcerouting/malloc-size
[mirror_frr.git] / ospfd / ospf_opaque.c
1 /*
2 * This is an implementation of rfc2370.
3 * Copyright (C) 2001 KDD R&D Laboratories, Inc.
4 * http://www.kddlabs.co.jp/
5 *
6 * This file is part of GNU Zebra.
7 *
8 * GNU Zebra is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
11 * later version.
12 *
13 * GNU Zebra is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; see the file COPYING; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include <zebra.h>
24
25 #include "linklist.h"
26 #include "prefix.h"
27 #include "if.h"
28 #include "table.h"
29 #include "memory.h"
30 #include "command.h"
31 #include "vty.h"
32 #include "stream.h"
33 #include "log.h"
34 #include "thread.h"
35 #include "hash.h"
36 #include "sockunion.h" /* for inet_aton() */
37
38 #include "ospfd/ospfd.h"
39 #include "ospfd/ospf_interface.h"
40 #include "ospfd/ospf_ism.h"
41 #include "ospfd/ospf_asbr.h"
42 #include "ospfd/ospf_lsa.h"
43 #include "ospfd/ospf_lsdb.h"
44 #include "ospfd/ospf_neighbor.h"
45 #include "ospfd/ospf_nsm.h"
46 #include "ospfd/ospf_flood.h"
47 #include "ospfd/ospf_packet.h"
48 #include "ospfd/ospf_spf.h"
49 #include "ospfd/ospf_dump.h"
50 #include "ospfd/ospf_route.h"
51 #include "ospfd/ospf_ase.h"
52 #include "ospfd/ospf_zebra.h"
53 #include "ospfd/ospf_te.h"
54 #include "ospfd/ospf_sr.h"
55 #include "ospfd/ospf_ri.h"
56 #include "ospfd/ospf_ext.h"
57
58 DEFINE_MTYPE_STATIC(OSPFD, OSPF_OPAQUE_FUNCTAB, "OSPF opaque function table")
59 DEFINE_MTYPE_STATIC(OSPFD, OPAQUE_INFO_PER_TYPE, "OSPF opaque per-type info")
60 DEFINE_MTYPE_STATIC(OSPFD, OPAQUE_INFO_PER_ID, "OSPF opaque per-ID info")
61
62 /*------------------------------------------------------------------------*
63 * Followings are initialize/terminate functions for Opaque-LSAs handling.
64 *------------------------------------------------------------------------*/
65
66 #ifdef SUPPORT_OSPF_API
67 int ospf_apiserver_init(void);
68 void ospf_apiserver_term(void);
69 /* Init apiserver? It's disabled by default. */
70 int ospf_apiserver_enable;
71 #endif /* SUPPORT_OSPF_API */
72
73 static void ospf_opaque_register_vty(void);
74 static void ospf_opaque_funclist_init(void);
75 static void ospf_opaque_funclist_term(void);
76 static void free_opaque_info_per_type(void *val);
77 static void free_opaque_info_per_id(void *val);
78 static void free_opaque_info_owner(void *val);
79 static int ospf_opaque_lsa_install_hook(struct ospf_lsa *lsa);
80 static int ospf_opaque_lsa_delete_hook(struct ospf_lsa *lsa);
81
82 void ospf_opaque_init(void)
83 {
84 ospf_opaque_register_vty();
85 ospf_opaque_funclist_init();
86
87 if (ospf_mpls_te_init() != 0)
88 exit(1);
89
90 /* Segment Routing init */
91 if (ospf_sr_init() != 0)
92 exit(1);
93
94 if (ospf_router_info_init() != 0)
95 exit(1);
96
97 if (ospf_ext_init() != 0)
98 exit(1);
99
100 #ifdef SUPPORT_OSPF_API
101 if ((ospf_apiserver_enable) && (ospf_apiserver_init() != 0))
102 exit(1);
103 #endif /* SUPPORT_OSPF_API */
104
105 return;
106 }
107
108 void ospf_opaque_term(void)
109 {
110 ospf_mpls_te_term();
111
112 ospf_router_info_term();
113
114 ospf_ext_term();
115
116 ospf_sr_term();
117
118 #ifdef SUPPORT_OSPF_API
119 ospf_apiserver_term();
120 #endif /* SUPPORT_OSPF_API */
121
122 ospf_opaque_funclist_term();
123 return;
124 }
125
126 void ospf_opaque_finish(void)
127 {
128 ospf_router_info_finish();
129
130 ospf_ext_finish();
131
132 ospf_sr_finish();
133 }
134
135 int ospf_opaque_type9_lsa_init(struct ospf_interface *oi)
136 {
137 if (oi->opaque_lsa_self != NULL)
138 list_delete_and_null(&oi->opaque_lsa_self);
139
140 oi->opaque_lsa_self = list_new();
141 oi->opaque_lsa_self->del = free_opaque_info_per_type;
142 oi->t_opaque_lsa_self = NULL;
143 return 0;
144 }
145
146 void ospf_opaque_type9_lsa_term(struct ospf_interface *oi)
147 {
148 OSPF_TIMER_OFF(oi->t_opaque_lsa_self);
149 if (oi->opaque_lsa_self != NULL)
150 list_delete_and_null(&oi->opaque_lsa_self);
151 oi->opaque_lsa_self = NULL;
152 return;
153 }
154
155 int ospf_opaque_type10_lsa_init(struct ospf_area *area)
156 {
157 if (area->opaque_lsa_self != NULL)
158 list_delete_and_null(&area->opaque_lsa_self);
159
160 area->opaque_lsa_self = list_new();
161 area->opaque_lsa_self->del = free_opaque_info_per_type;
162 area->t_opaque_lsa_self = NULL;
163
164 #ifdef MONITOR_LSDB_CHANGE
165 area->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
166 area->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
167 #endif /* MONITOR_LSDB_CHANGE */
168 return 0;
169 }
170
171 void ospf_opaque_type10_lsa_term(struct ospf_area *area)
172 {
173 #ifdef MONITOR_LSDB_CHANGE
174 area->lsdb->new_lsa_hook = area->lsdb->del_lsa_hook = NULL;
175 #endif /* MONITOR_LSDB_CHANGE */
176
177 OSPF_TIMER_OFF(area->t_opaque_lsa_self);
178 if (area->opaque_lsa_self != NULL)
179 list_delete_and_null(&area->opaque_lsa_self);
180 return;
181 }
182
183 int ospf_opaque_type11_lsa_init(struct ospf *top)
184 {
185 if (top->opaque_lsa_self != NULL)
186 list_delete_and_null(&top->opaque_lsa_self);
187
188 top->opaque_lsa_self = list_new();
189 top->opaque_lsa_self->del = free_opaque_info_per_type;
190 top->t_opaque_lsa_self = NULL;
191
192 #ifdef MONITOR_LSDB_CHANGE
193 top->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
194 top->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
195 #endif /* MONITOR_LSDB_CHANGE */
196 return 0;
197 }
198
199 void ospf_opaque_type11_lsa_term(struct ospf *top)
200 {
201 #ifdef MONITOR_LSDB_CHANGE
202 top->lsdb->new_lsa_hook = top->lsdb->del_lsa_hook = NULL;
203 #endif /* MONITOR_LSDB_CHANGE */
204
205 OSPF_TIMER_OFF(top->t_opaque_lsa_self);
206 if (top->opaque_lsa_self != NULL)
207 list_delete_and_null(&top->opaque_lsa_self);
208 return;
209 }
210
211 static const char *ospf_opaque_type_name(uint8_t opaque_type)
212 {
213 const char *name = "Unknown";
214
215 switch (opaque_type) {
216 case OPAQUE_TYPE_WILDCARD: /* This is a special assignment! */
217 name = "Wildcard";
218 break;
219 case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA:
220 name = "Traffic Engineering LSA";
221 break;
222 case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC:
223 name = "Sycamore optical topology description";
224 break;
225 case OPAQUE_TYPE_GRACE_LSA:
226 name = "Grace-LSA";
227 break;
228 case OPAQUE_TYPE_INTER_AS_LSA:
229 name = "Inter-AS TE-v2 LSA";
230 break;
231 case OPAQUE_TYPE_ROUTER_INFORMATION_LSA:
232 name = "Router Information LSA";
233 break;
234 case OPAQUE_TYPE_EXTENDED_PREFIX_LSA:
235 name = "Extended Prefix Opaque LSA";
236 break;
237 case OPAQUE_TYPE_EXTENDED_LINK_LSA:
238 name = "Extended Link Opaque LSA";
239 break;
240 default:
241 if (OPAQUE_TYPE_RANGE_UNASSIGNED(opaque_type))
242 name = "Unassigned";
243 else {
244 uint32_t bigger_range = opaque_type;
245 /*
246 * Get around type-limits warning: comparison is always
247 * true due to limited range of data type
248 */
249 if (OPAQUE_TYPE_RANGE_RESERVED(bigger_range))
250 name = "Private/Experimental";
251 }
252 break;
253 }
254 return name;
255 }
256
257 /*------------------------------------------------------------------------*
258 * Followings are management functions to store user specified callbacks.
259 *------------------------------------------------------------------------*/
260
261 struct opaque_info_per_type; /* Forward declaration. */
262
263 struct ospf_opaque_functab {
264 uint8_t opaque_type;
265 struct opaque_info_per_type *oipt;
266
267 int (*new_if_hook)(struct interface *ifp);
268 int (*del_if_hook)(struct interface *ifp);
269 void (*ism_change_hook)(struct ospf_interface *oi, int old_status);
270 void (*nsm_change_hook)(struct ospf_neighbor *nbr, int old_status);
271 void (*config_write_router)(struct vty *vty);
272 void (*config_write_if)(struct vty *vty, struct interface *ifp);
273 void (*config_write_debug)(struct vty *vty);
274 void (*show_opaque_info)(struct vty *vty, struct ospf_lsa *lsa);
275 int (*lsa_originator)(void *arg);
276 struct ospf_lsa *(*lsa_refresher)(struct ospf_lsa *lsa);
277 int (*new_lsa_hook)(struct ospf_lsa *lsa);
278 int (*del_lsa_hook)(struct ospf_lsa *lsa);
279 };
280
281 /* Handle LSA-9/10/11 altogether. */
282 static struct list *ospf_opaque_wildcard_funclist;
283 static struct list *ospf_opaque_type9_funclist;
284 static struct list *ospf_opaque_type10_funclist;
285 static struct list *ospf_opaque_type11_funclist;
286
287 static void ospf_opaque_del_functab(void *val)
288 {
289 XFREE(MTYPE_OSPF_OPAQUE_FUNCTAB, val);
290 return;
291 }
292
293 static void ospf_opaque_funclist_init(void)
294 {
295 struct list *funclist;
296
297 funclist = ospf_opaque_wildcard_funclist = list_new();
298 funclist->del = ospf_opaque_del_functab;
299
300 funclist = ospf_opaque_type9_funclist = list_new();
301 funclist->del = ospf_opaque_del_functab;
302
303 funclist = ospf_opaque_type10_funclist = list_new();
304 funclist->del = ospf_opaque_del_functab;
305
306 funclist = ospf_opaque_type11_funclist = list_new();
307 funclist->del = ospf_opaque_del_functab;
308 return;
309 }
310
311 static void ospf_opaque_funclist_term(void)
312 {
313 struct list *funclist;
314
315 funclist = ospf_opaque_wildcard_funclist;
316 list_delete_and_null(&funclist);
317
318 funclist = ospf_opaque_type9_funclist;
319 list_delete_and_null(&funclist);
320
321 funclist = ospf_opaque_type10_funclist;
322 list_delete_and_null(&funclist);
323
324 funclist = ospf_opaque_type11_funclist;
325 list_delete_and_null(&funclist);
326 return;
327 }
328
329 static struct list *ospf_get_opaque_funclist(uint8_t lsa_type)
330 {
331 struct list *funclist = NULL;
332
333 switch (lsa_type) {
334 case OPAQUE_TYPE_WILDCARD:
335 /* XXX
336 * This is an ugly trick to handle type-9/10/11 LSA altogether.
337 * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor
338 * an officially assigned opaque-type.
339 * Though it is possible that the value might be officially used
340 * in the future, we use it internally as a special label, for
341 * now.
342 */
343 funclist = ospf_opaque_wildcard_funclist;
344 break;
345 case OSPF_OPAQUE_LINK_LSA:
346 funclist = ospf_opaque_type9_funclist;
347 break;
348 case OSPF_OPAQUE_AREA_LSA:
349 funclist = ospf_opaque_type10_funclist;
350 break;
351 case OSPF_OPAQUE_AS_LSA:
352 funclist = ospf_opaque_type11_funclist;
353 break;
354 default:
355 zlog_warn("ospf_get_opaque_funclist: Unexpected LSA-type(%u)",
356 lsa_type);
357 break;
358 }
359 return funclist;
360 }
361
362 /* XXX: such a huge argument list can /not/ be healthy... */
363 int ospf_register_opaque_functab(
364 uint8_t lsa_type, uint8_t opaque_type,
365 int (*new_if_hook)(struct interface *ifp),
366 int (*del_if_hook)(struct interface *ifp),
367 void (*ism_change_hook)(struct ospf_interface *oi, int old_status),
368 void (*nsm_change_hook)(struct ospf_neighbor *nbr, int old_status),
369 void (*config_write_router)(struct vty *vty),
370 void (*config_write_if)(struct vty *vty, struct interface *ifp),
371 void (*config_write_debug)(struct vty *vty),
372 void (*show_opaque_info)(struct vty *vty, struct ospf_lsa *lsa),
373 int (*lsa_originator)(void *arg),
374 struct ospf_lsa *(*lsa_refresher)(struct ospf_lsa *lsa),
375 int (*new_lsa_hook)(struct ospf_lsa *lsa),
376 int (*del_lsa_hook)(struct ospf_lsa *lsa))
377 {
378 struct list *funclist;
379 struct ospf_opaque_functab *new;
380 int rc = -1;
381
382 if ((funclist = ospf_get_opaque_funclist(lsa_type)) == NULL) {
383 zlog_warn(
384 "ospf_register_opaque_functab: Cannot get funclist"
385 " for Type-%u LSAs?",
386 lsa_type);
387 goto out;
388 } else {
389 struct listnode *node, *nnode;
390 struct ospf_opaque_functab *functab;
391
392 for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab))
393 if (functab->opaque_type == opaque_type) {
394 zlog_warn(
395 "ospf_register_opaque_functab: Duplicated entry?:"
396 " lsa_type(%u), opaque_type(%u)",
397 lsa_type, opaque_type);
398 goto out;
399 }
400 }
401
402 new = XCALLOC(MTYPE_OSPF_OPAQUE_FUNCTAB,
403 sizeof(struct ospf_opaque_functab));
404
405 new->opaque_type = opaque_type;
406 new->oipt = NULL;
407 new->new_if_hook = new_if_hook;
408 new->del_if_hook = del_if_hook;
409 new->ism_change_hook = ism_change_hook;
410 new->nsm_change_hook = nsm_change_hook;
411 new->config_write_router = config_write_router;
412 new->config_write_if = config_write_if;
413 new->config_write_debug = config_write_debug;
414 new->show_opaque_info = show_opaque_info;
415 new->lsa_originator = lsa_originator;
416 new->lsa_refresher = lsa_refresher;
417 new->new_lsa_hook = new_lsa_hook;
418 new->del_lsa_hook = del_lsa_hook;
419
420 listnode_add(funclist, new);
421 rc = 0;
422
423 out:
424 return rc;
425 }
426
427 void ospf_delete_opaque_functab(uint8_t lsa_type, uint8_t opaque_type)
428 {
429 struct list *funclist;
430 struct listnode *node, *nnode;
431 struct ospf_opaque_functab *functab;
432
433 if ((funclist = ospf_get_opaque_funclist(lsa_type)) != NULL)
434 for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab)) {
435 if (functab->opaque_type == opaque_type) {
436 /* Cleanup internal control information, if it
437 * still remains. */
438 if (functab->oipt != NULL) {
439 free_opaque_info_per_type(
440 functab->oipt);
441 free_opaque_info_owner(functab->oipt);
442 }
443
444 /* Dequeue listnode entry from the list. */
445 listnode_delete(funclist, functab);
446
447 /* Avoid misjudgement in the next lookup. */
448 if (listcount(funclist) == 0)
449 funclist->head = funclist->tail = NULL;
450
451 XFREE(MTYPE_OSPF_OPAQUE_FUNCTAB, functab);
452 break;
453 }
454 }
455
456 return;
457 }
458
459 static struct ospf_opaque_functab *
460 ospf_opaque_functab_lookup(struct ospf_lsa *lsa)
461 {
462 struct list *funclist;
463 struct listnode *node;
464 struct ospf_opaque_functab *functab;
465 uint8_t key = GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr));
466
467 if ((funclist = ospf_get_opaque_funclist(lsa->data->type)) != NULL)
468 for (ALL_LIST_ELEMENTS_RO(funclist, node, functab))
469 if (functab->opaque_type == key)
470 return functab;
471
472 return NULL;
473 }
474
475 /*------------------------------------------------------------------------*
476 * Followings are management functions for self-originated LSA entries.
477 *------------------------------------------------------------------------*/
478
479 /*
480 * Opaque-LSA control information per opaque-type.
481 * Single Opaque-Type may have multiple instances; each of them will be
482 * identified by their opaque-id.
483 */
484 struct opaque_info_per_type {
485 uint8_t lsa_type;
486 uint8_t opaque_type;
487
488 enum { PROC_NORMAL, PROC_SUSPEND } status;
489
490 /*
491 * Thread for (re-)origination scheduling for this opaque-type.
492 *
493 * Initial origination of Opaque-LSAs is controlled by generic
494 * Opaque-LSA handling module so that same opaque-type entries are
495 * called all at once when certain conditions are met.
496 * However, there might be cases that some Opaque-LSA clients need
497 * to (re-)originate their own Opaque-LSAs out-of-sync with others.
498 * This thread is prepared for that specific purpose.
499 */
500 struct thread *t_opaque_lsa_self;
501
502 /*
503 * Backpointer to an "owner" which is LSA-type dependent.
504 * type-9: struct ospf_interface
505 * type-10: struct ospf_area
506 * type-11: struct ospf
507 */
508 void *owner;
509
510 /* Collection of callback functions for this opaque-type. */
511 struct ospf_opaque_functab *functab;
512
513 /* List of Opaque-LSA control informations per opaque-id. */
514 struct list *id_list;
515 };
516
517 /* Opaque-LSA control information per opaque-id. */
518 struct opaque_info_per_id {
519 uint32_t opaque_id;
520
521 /* Thread for refresh/flush scheduling for this opaque-type/id. */
522 struct thread *t_opaque_lsa_self;
523
524 /* Backpointer to Opaque-LSA control information per opaque-type. */
525 struct opaque_info_per_type *opqctl_type;
526
527 /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
528 struct ospf_lsa *lsa;
529 };
530
531 static struct opaque_info_per_type *
532 register_opaque_info_per_type(struct ospf_opaque_functab *functab,
533 struct ospf_lsa *new);
534 static struct opaque_info_per_type *
535 lookup_opaque_info_by_type(struct ospf_lsa *lsa);
536 static struct opaque_info_per_id *
537 register_opaque_info_per_id(struct opaque_info_per_type *oipt,
538 struct ospf_lsa *new);
539 static struct opaque_info_per_id *
540 lookup_opaque_info_by_id(struct opaque_info_per_type *oipt,
541 struct ospf_lsa *lsa);
542 static struct opaque_info_per_id *register_opaque_lsa(struct ospf_lsa *new);
543
544
545 static struct opaque_info_per_type *
546 register_opaque_info_per_type(struct ospf_opaque_functab *functab,
547 struct ospf_lsa *new)
548 {
549 struct ospf *top;
550 struct opaque_info_per_type *oipt;
551
552 oipt = XCALLOC(MTYPE_OPAQUE_INFO_PER_TYPE,
553 sizeof(struct opaque_info_per_type));
554
555 switch (new->data->type) {
556 case OSPF_OPAQUE_LINK_LSA:
557 oipt->owner = new->oi;
558 listnode_add(new->oi->opaque_lsa_self, oipt);
559 break;
560 case OSPF_OPAQUE_AREA_LSA:
561 oipt->owner = new->area;
562 listnode_add(new->area->opaque_lsa_self, oipt);
563 break;
564 case OSPF_OPAQUE_AS_LSA:
565 top = ospf_lookup_by_vrf_id(new->vrf_id);
566 if (new->area != NULL && (top = new->area->ospf) == NULL) {
567 free_opaque_info_per_type((void *)oipt);
568 free_opaque_info_owner(oipt);
569 oipt = NULL;
570 goto out; /* This case may not exist. */
571 }
572 oipt->owner = top;
573 listnode_add(top->opaque_lsa_self, oipt);
574 break;
575 default:
576 zlog_warn(
577 "register_opaque_info_per_type: Unexpected LSA-type(%u)",
578 new->data->type);
579 free_opaque_info_per_type((void *)oipt);
580 free_opaque_info_owner(oipt);
581 oipt = NULL;
582 goto out; /* This case may not exist. */
583 }
584
585 oipt->lsa_type = new->data->type;
586 oipt->opaque_type = GET_OPAQUE_TYPE(ntohl(new->data->id.s_addr));
587 oipt->status = PROC_NORMAL;
588 oipt->t_opaque_lsa_self = NULL;
589 oipt->functab = functab;
590 functab->oipt = oipt;
591 oipt->id_list = list_new();
592 oipt->id_list->del = free_opaque_info_per_id;
593
594 out:
595 return oipt;
596 }
597
598 /* Remove "oipt" from its owner's self-originated LSA list. */
599 static void free_opaque_info_owner(void *val)
600 {
601 struct opaque_info_per_type *oipt = (struct opaque_info_per_type *)val;
602
603 switch (oipt->lsa_type) {
604 case OSPF_OPAQUE_LINK_LSA: {
605 struct ospf_interface *oi =
606 (struct ospf_interface *)(oipt->owner);
607 listnode_delete(oi->opaque_lsa_self, oipt);
608 break;
609 }
610 case OSPF_OPAQUE_AREA_LSA: {
611 struct ospf_area *area = (struct ospf_area *)(oipt->owner);
612 listnode_delete(area->opaque_lsa_self, oipt);
613 break;
614 }
615 case OSPF_OPAQUE_AS_LSA: {
616 struct ospf *top = (struct ospf *)(oipt->owner);
617 listnode_delete(top->opaque_lsa_self, oipt);
618 break;
619 }
620 default:
621 zlog_warn("free_opaque_info_owner: Unexpected LSA-type(%u)",
622 oipt->lsa_type);
623 break; /* This case may not exist. */
624 }
625 }
626
627 static void free_opaque_info_per_type(void *val)
628 {
629 struct opaque_info_per_type *oipt = (struct opaque_info_per_type *)val;
630 struct opaque_info_per_id *oipi;
631 struct ospf_lsa *lsa;
632 struct listnode *node, *nnode;
633
634 /* Control information per opaque-id may still exist. */
635 for (ALL_LIST_ELEMENTS(oipt->id_list, node, nnode, oipi)) {
636 if ((lsa = oipi->lsa) == NULL)
637 continue;
638 if (IS_LSA_MAXAGE(lsa))
639 continue;
640 ospf_opaque_lsa_flush_schedule(lsa);
641 }
642
643 OSPF_TIMER_OFF(oipt->t_opaque_lsa_self);
644 list_delete_and_null(&oipt->id_list);
645 XFREE(MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
646 return;
647 }
648
649 static struct opaque_info_per_type *
650 lookup_opaque_info_by_type(struct ospf_lsa *lsa)
651 {
652 struct ospf *top;
653 struct ospf_area *area;
654 struct ospf_interface *oi;
655 struct list *listtop = NULL;
656 struct listnode *node, *nnode;
657 struct opaque_info_per_type *oipt = NULL;
658 uint8_t key = GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr));
659
660 switch (lsa->data->type) {
661 case OSPF_OPAQUE_LINK_LSA:
662 if ((oi = lsa->oi) != NULL)
663 listtop = oi->opaque_lsa_self;
664 else
665 zlog_warn(
666 "Type-9 Opaque-LSA: Reference to OI is missing?");
667 break;
668 case OSPF_OPAQUE_AREA_LSA:
669 if ((area = lsa->area) != NULL)
670 listtop = area->opaque_lsa_self;
671 else
672 zlog_warn(
673 "Type-10 Opaque-LSA: Reference to AREA is missing?");
674 break;
675 case OSPF_OPAQUE_AS_LSA:
676 top = ospf_lookup_by_vrf_id(lsa->vrf_id);
677 if ((area = lsa->area) != NULL && (top = area->ospf) == NULL) {
678 zlog_warn(
679 "Type-11 Opaque-LSA: Reference to OSPF is missing?");
680 break; /* Unlikely to happen. */
681 }
682 listtop = top->opaque_lsa_self;
683 break;
684 default:
685 zlog_warn("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 zlog_warn(
1290 "ospf_opaque_lsa_originate_schedule: Invalid argument?");
1291 goto out;
1292 }
1293
1294 /* It may not a right time to schedule origination now. */
1295 if (!CHECK_FLAG(top->opaque, OPAQUE_OPERATION_READY_BIT)) {
1296 if (IS_DEBUG_OSPF_EVENT)
1297 zlog_debug(
1298 "ospf_opaque_lsa_originate_schedule: Not operational.");
1299 goto out; /* This is not an error. */
1300 }
1301
1302 if (delay0 != NULL)
1303 delay = *delay0;
1304
1305 /*
1306 * There might be some entries that have been waiting for triggering
1307 * of per opaque-type re-origination get resumed.
1308 */
1309 ospf_opaque_lsa_reoriginate_resume(oi->opaque_lsa_self, (void *)oi);
1310 ospf_opaque_lsa_reoriginate_resume(area->opaque_lsa_self, (void *)area);
1311 ospf_opaque_lsa_reoriginate_resume(top->opaque_lsa_self, (void *)top);
1312
1313 /*
1314 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1315 */
1316 if (!list_isempty(ospf_opaque_type9_funclist)
1317 && list_isempty(oi->opaque_lsa_self)
1318 && oi->t_opaque_lsa_self == NULL) {
1319 if (IS_DEBUG_OSPF_EVENT)
1320 zlog_debug(
1321 "Schedule Type-9 Opaque-LSA origination in %d ms later.",
1322 delay);
1323 oi->t_opaque_lsa_self = NULL;
1324 thread_add_timer_msec(master, ospf_opaque_type9_lsa_originate,
1325 oi, delay, &oi->t_opaque_lsa_self);
1326 delay += top->min_ls_interval;
1327 }
1328
1329 if (!list_isempty(ospf_opaque_type10_funclist)
1330 && list_isempty(area->opaque_lsa_self)
1331 && area->t_opaque_lsa_self == NULL) {
1332 /*
1333 * One AREA may contain multiple OIs, but above 2nd and 3rd
1334 * conditions prevent from scheduling the originate function
1335 * again and again.
1336 */
1337 if (IS_DEBUG_OSPF_EVENT)
1338 zlog_debug(
1339 "Schedule Type-10 Opaque-LSA origination in %d ms later.",
1340 delay);
1341 area->t_opaque_lsa_self = NULL;
1342 thread_add_timer_msec(master, ospf_opaque_type10_lsa_originate,
1343 area, delay, &area->t_opaque_lsa_self);
1344 delay += top->min_ls_interval;
1345 }
1346
1347 if (!list_isempty(ospf_opaque_type11_funclist)
1348 && list_isempty(top->opaque_lsa_self)
1349 && top->t_opaque_lsa_self == NULL) {
1350 /*
1351 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1352 * conditions prevent from scheduling the originate function
1353 * again and again.
1354 */
1355 if (IS_DEBUG_OSPF_EVENT)
1356 zlog_debug(
1357 "Schedule Type-11 Opaque-LSA origination in %d ms later.",
1358 delay);
1359 top->t_opaque_lsa_self = NULL;
1360 thread_add_timer_msec(master, ospf_opaque_type11_lsa_originate,
1361 top, delay, &top->t_opaque_lsa_self);
1362 delay += top->min_ls_interval;
1363 }
1364
1365 /*
1366 * Following section treats a special situation that this node's
1367 * opaque capability has changed as "ON -> OFF -> ON".
1368 */
1369 if (!list_isempty(ospf_opaque_type9_funclist)
1370 && !list_isempty(oi->opaque_lsa_self)) {
1371 for (ALL_LIST_ELEMENTS(oi->opaque_lsa_self, node, nnode,
1372 oipt)) {
1373 /*
1374 * removed the test for
1375 * (! list_isempty (oipt->id_list)) * Handler is
1376 * already active. *
1377 * because opaque cababilities ON -> OFF -> ON result in
1378 * list_isempty (oipt->id_list)
1379 * not being empty.
1380 */
1381 if (oipt->t_opaque_lsa_self
1382 != NULL /* Waiting for a thread call. */
1383 || oipt->status == PROC_SUSPEND) /* Cannot
1384 originate
1385 now. */
1386 continue;
1387
1388 ospf_opaque_lsa_reoriginate_schedule(
1389 (void *)oi, OSPF_OPAQUE_LINK_LSA,
1390 oipt->opaque_type);
1391 }
1392 }
1393
1394 if (!list_isempty(ospf_opaque_type10_funclist)
1395 && !list_isempty(area->opaque_lsa_self)) {
1396 for (ALL_LIST_ELEMENTS(area->opaque_lsa_self, node, nnode,
1397 oipt)) {
1398 /*
1399 * removed the test for
1400 * (! list_isempty (oipt->id_list)) * Handler is
1401 * already active. *
1402 * because opaque cababilities ON -> OFF -> ON result in
1403 * list_isempty (oipt->id_list)
1404 * not being empty.
1405 */
1406 if (oipt->t_opaque_lsa_self
1407 != NULL /* Waiting for a thread call. */
1408 || oipt->status == PROC_SUSPEND) /* Cannot
1409 originate
1410 now. */
1411 continue;
1412
1413 ospf_opaque_lsa_reoriginate_schedule(
1414 (void *)area, OSPF_OPAQUE_AREA_LSA,
1415 oipt->opaque_type);
1416 }
1417 }
1418
1419 if (!list_isempty(ospf_opaque_type11_funclist)
1420 && !list_isempty(top->opaque_lsa_self)) {
1421 for (ALL_LIST_ELEMENTS(top->opaque_lsa_self, node, nnode,
1422 oipt)) {
1423 /*
1424 * removed the test for
1425 * (! list_isempty (oipt->id_list)) * Handler is
1426 * already active. *
1427 * because opaque cababilities ON -> OFF -> ON result in
1428 * list_isempty (oipt->id_list)
1429 * not being empty.
1430 */
1431 if (oipt->t_opaque_lsa_self
1432 != NULL /* Waiting for a thread call. */
1433 || oipt->status == PROC_SUSPEND) /* Cannot
1434 originate
1435 now. */
1436 continue;
1437
1438 ospf_opaque_lsa_reoriginate_schedule((void *)top,
1439 OSPF_OPAQUE_AS_LSA,
1440 oipt->opaque_type);
1441 }
1442 }
1443
1444 if (delay0 != NULL)
1445 *delay0 = delay;
1446
1447 out:
1448 return;
1449 }
1450
1451 static int ospf_opaque_type9_lsa_originate(struct thread *t)
1452 {
1453 struct ospf_interface *oi;
1454 int rc;
1455
1456 oi = THREAD_ARG(t);
1457 oi->t_opaque_lsa_self = NULL;
1458
1459 if (IS_DEBUG_OSPF_EVENT)
1460 zlog_debug("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
1461 IF_NAME(oi));
1462
1463 rc = opaque_lsa_originate_callback(ospf_opaque_type9_funclist, oi);
1464
1465 return rc;
1466 }
1467
1468 static int ospf_opaque_type10_lsa_originate(struct thread *t)
1469 {
1470 struct ospf_area *area;
1471 int rc;
1472
1473 area = THREAD_ARG(t);
1474 area->t_opaque_lsa_self = NULL;
1475
1476 if (IS_DEBUG_OSPF_EVENT)
1477 zlog_debug(
1478 "Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
1479 inet_ntoa(area->area_id));
1480
1481 rc = opaque_lsa_originate_callback(ospf_opaque_type10_funclist, area);
1482
1483 return rc;
1484 }
1485
1486 static int ospf_opaque_type11_lsa_originate(struct thread *t)
1487 {
1488 struct ospf *top;
1489 int rc;
1490
1491 top = THREAD_ARG(t);
1492 top->t_opaque_lsa_self = NULL;
1493
1494 if (IS_DEBUG_OSPF_EVENT)
1495 zlog_debug(
1496 "Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
1497
1498 rc = opaque_lsa_originate_callback(ospf_opaque_type11_funclist, top);
1499
1500 return rc;
1501 }
1502
1503 static void ospf_opaque_lsa_reoriginate_resume(struct list *listtop, void *arg)
1504 {
1505 struct listnode *node, *nnode;
1506 struct opaque_info_per_type *oipt;
1507 struct ospf_opaque_functab *functab;
1508
1509 if (listtop == NULL)
1510 goto out;
1511
1512 /*
1513 * Pickup oipt entries those which in SUSPEND status, and give
1514 * them a chance to start re-origination now.
1515 */
1516 for (ALL_LIST_ELEMENTS(listtop, node, nnode, oipt)) {
1517 if (oipt->status != PROC_SUSPEND)
1518 continue;
1519
1520 oipt->status = PROC_NORMAL;
1521
1522 if ((functab = oipt->functab) == NULL
1523 || functab->lsa_originator == NULL)
1524 continue;
1525
1526 if ((*functab->lsa_originator)(arg) != 0) {
1527 zlog_warn(
1528 "ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)",
1529 oipt->opaque_type);
1530 continue;
1531 }
1532 }
1533
1534 out:
1535 return;
1536 }
1537
1538 struct ospf_lsa *ospf_opaque_lsa_install(struct ospf_lsa *lsa, int rt_recalc)
1539 {
1540 struct ospf_lsa *new = NULL;
1541 struct opaque_info_per_type *oipt;
1542 struct opaque_info_per_id *oipi;
1543 struct ospf *top;
1544
1545 /* Don't take "rt_recalc" into consideration for now. */ /* XXX */
1546
1547 if (!IS_LSA_SELF(lsa)) {
1548 new = lsa; /* Don't touch this LSA. */
1549 goto out;
1550 }
1551
1552 if (IS_DEBUG_OSPF(lsa, LSA_INSTALL))
1553 zlog_debug(
1554 "Install Type-%u Opaque-LSA: [opaque-type=%u, opaque-id=%x]",
1555 lsa->data->type,
1556 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)),
1557 GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)));
1558
1559 /* Replace the existing lsa with the new one. */
1560 if ((oipt = lookup_opaque_info_by_type(lsa)) != NULL
1561 && (oipi = lookup_opaque_info_by_id(oipt, lsa)) != NULL) {
1562 ospf_lsa_unlock(&oipi->lsa);
1563 oipi->lsa = ospf_lsa_lock(lsa);
1564 }
1565 /* Register the new lsa entry and get its control info. */
1566 else if ((oipi = register_opaque_lsa(lsa)) == NULL) {
1567 zlog_warn("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 zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?");
1580 goto out;
1581 }
1582 break;
1583 case OSPF_OPAQUE_AREA_LSA:
1584 if (lsa->area == NULL || (top = lsa->area->ospf) == NULL) {
1585 /* Above conditions must have passed. */
1586 zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?");
1587 goto out;
1588 }
1589 break;
1590 case OSPF_OPAQUE_AS_LSA:
1591 top = ospf_lookup_by_vrf_id(lsa->vrf_id);
1592 if (lsa->area != NULL && (top = lsa->area->ospf) == NULL) {
1593 /* Above conditions must have passed. */
1594 zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?");
1595 goto out;
1596 }
1597 break;
1598 default:
1599 zlog_warn("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 zlog_warn(
1672 "ospf_opaque_lsa_reoriginate_schedule:"
1673 " Type-9 Opaque-LSA: Invalid parameter?");
1674 goto out;
1675 }
1676 if ((top = oi_to_top(oi)) == NULL) {
1677 zlog_warn(
1678 "ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1679 IF_NAME(oi));
1680 goto out;
1681 }
1682 if (!list_isempty(ospf_opaque_type9_funclist)
1683 && list_isempty(oi->opaque_lsa_self)
1684 && oi->t_opaque_lsa_self != NULL) {
1685 zlog_warn(
1686 "Type-9 Opaque-LSA (opaque_type=%u):"
1687 " Common origination for OI(%s) has already started",
1688 opaque_type, IF_NAME(oi));
1689 goto out;
1690 }
1691 func = ospf_opaque_type9_lsa_reoriginate_timer;
1692 break;
1693 case OSPF_OPAQUE_AREA_LSA:
1694 if ((area = (struct ospf_area *)lsa_type_dependent) == NULL) {
1695 zlog_warn(
1696 "ospf_opaque_lsa_reoriginate_schedule:"
1697 " Type-10 Opaque-LSA: Invalid parameter?");
1698 goto out;
1699 }
1700 if ((top = area->ospf) == NULL) {
1701 zlog_warn(
1702 "ospf_opaque_lsa_reoriginate_schedule:"
1703 " AREA(%s) -> TOP?",
1704 inet_ntoa(area->area_id));
1705 goto out;
1706 }
1707 if (!list_isempty(ospf_opaque_type10_funclist)
1708 && list_isempty(area->opaque_lsa_self)
1709 && area->t_opaque_lsa_self != NULL) {
1710 zlog_warn(
1711 "Type-10 Opaque-LSA (opaque_type=%u):"
1712 " Common origination for AREA(%s) has already started",
1713 opaque_type, inet_ntoa(area->area_id));
1714 goto out;
1715 }
1716 func = ospf_opaque_type10_lsa_reoriginate_timer;
1717 break;
1718 case OSPF_OPAQUE_AS_LSA:
1719 if ((top = (struct ospf *)lsa_type_dependent) == NULL) {
1720 zlog_warn(
1721 "ospf_opaque_lsa_reoriginate_schedule:"
1722 " Type-11 Opaque-LSA: Invalid parameter?");
1723 goto out;
1724 }
1725 if (!list_isempty(ospf_opaque_type11_funclist)
1726 && list_isempty(top->opaque_lsa_self)
1727 && top->t_opaque_lsa_self != NULL) {
1728 zlog_warn(
1729 "Type-11 Opaque-LSA (opaque_type=%u):"
1730 " Common origination has already started",
1731 opaque_type);
1732 goto out;
1733 }
1734
1735 /* Fake "area" to pass "ospf" to a lookup function later. */
1736 dummy.ospf = top;
1737 area = &dummy;
1738
1739 func = ospf_opaque_type11_lsa_reoriginate_timer;
1740 break;
1741 default:
1742 zlog_warn(
1743 "ospf_opaque_lsa_reoriginate_schedule:"
1744 " Unexpected LSA-type(%u)",
1745 lsa_type);
1746 goto out;
1747 }
1748
1749 /* It may not a right time to schedule reorigination now. */
1750 if (!CHECK_FLAG(top->opaque, OPAQUE_OPERATION_READY_BIT)) {
1751 if (IS_DEBUG_OSPF_EVENT)
1752 zlog_debug(
1753 "ospf_opaque_lsa_reoriginate_schedule: Not operational.");
1754 goto out; /* This is not an error. */
1755 }
1756
1757 /* Generate a dummy lsa to be passed for a lookup function. */
1758 lsa = pseudo_lsa(oi, area, lsa_type, opaque_type);
1759 lsa->vrf_id = top->vrf_id;
1760
1761 if ((oipt = lookup_opaque_info_by_type(lsa)) == NULL) {
1762 struct ospf_opaque_functab *functab;
1763 if ((functab = ospf_opaque_functab_lookup(lsa)) == NULL) {
1764 zlog_warn(
1765 "ospf_opaque_lsa_reoriginate_schedule:"
1766 " No associated function?: lsa_type(%u),"
1767 " 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 zlog_warn(
1774 "ospf_opaque_lsa_reoriginate_schedule:"
1775 " Cannot get a control info?: lsa_type(%u),"
1776 " opaque_type(%u)",
1777 lsa_type, opaque_type);
1778 goto out;
1779 }
1780 }
1781
1782 if (oipt->t_opaque_lsa_self != NULL) {
1783 if (IS_DEBUG_OSPF_EVENT)
1784 zlog_debug(
1785 "Type-%u Opaque-LSA has already scheduled to"
1786 " RE-ORIGINATE: [opaque-type=%u]",
1787 lsa_type,
1788 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)));
1789 goto out;
1790 }
1791
1792 /*
1793 * Different from initial origination time, in which various conditions
1794 * (opaque capability, neighbor status etc) are assured by caller of
1795 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1796 * it is highly possible that these conditions might not be satisfied
1797 * at the time of re-origination function is to be called.
1798 */
1799 delay = top->min_ls_interval; /* XXX */
1800
1801 if (IS_DEBUG_OSPF_EVENT)
1802 zlog_debug(
1803 "Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
1804 " ms later: [opaque-type=%u]",
1805 lsa_type, delay,
1806 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)));
1807
1808 OSPF_OPAQUE_TIMER_ON(oipt->t_opaque_lsa_self, func, oipt, delay);
1809
1810 out:
1811 return;
1812 }
1813
1814 static struct ospf_lsa *pseudo_lsa(struct ospf_interface *oi,
1815 struct ospf_area *area, uint8_t lsa_type,
1816 uint8_t opaque_type)
1817 {
1818 static struct ospf_lsa lsa = {0};
1819 static struct lsa_header lsah = {0};
1820 uint32_t tmp;
1821
1822 lsa.oi = oi;
1823 lsa.area = area;
1824 lsa.data = &lsah;
1825 lsa.vrf_id = VRF_DEFAULT;
1826
1827 lsah.type = lsa_type;
1828 tmp = SET_OPAQUE_LSID(opaque_type, 0); /* Opaque-ID is unused here. */
1829 lsah.id.s_addr = htonl(tmp);
1830
1831 return &lsa;
1832 }
1833
1834 static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread *t)
1835 {
1836 struct opaque_info_per_type *oipt;
1837 struct ospf_opaque_functab *functab;
1838 struct ospf *top;
1839 struct ospf_interface *oi;
1840 int rc = -1;
1841
1842 oipt = THREAD_ARG(t);
1843 oipt->t_opaque_lsa_self = NULL;
1844
1845 if ((functab = oipt->functab) == NULL
1846 || functab->lsa_originator == NULL) {
1847 zlog_warn(
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 zlog_warn(
1855 "ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1856 goto out;
1857 }
1858
1859 if (!CHECK_FLAG(top->config, OSPF_OPAQUE_CAPABLE)
1860 || !ospf_if_is_enable(oi)
1861 || ospf_nbr_count_opaque_capable(oi) == 0) {
1862 if (IS_DEBUG_OSPF_EVENT)
1863 zlog_debug(
1864 "Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...",
1865 oipt->opaque_type);
1866
1867 oipt->status = PROC_SUSPEND;
1868 rc = 0;
1869 goto out;
1870 }
1871
1872 if (IS_DEBUG_OSPF_EVENT)
1873 zlog_debug(
1874 "Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)",
1875 oipt->opaque_type, IF_NAME(oi));
1876
1877 rc = (*functab->lsa_originator)(oi);
1878 out:
1879 return rc;
1880 }
1881
1882 static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread *t)
1883 {
1884 struct opaque_info_per_type *oipt;
1885 struct ospf_opaque_functab *functab;
1886 struct listnode *node, *nnode;
1887 struct ospf *top;
1888 struct ospf_area *area;
1889 struct ospf_interface *oi;
1890 int n, rc = -1;
1891
1892 oipt = THREAD_ARG(t);
1893 oipt->t_opaque_lsa_self = NULL;
1894
1895 if ((functab = oipt->functab) == NULL
1896 || functab->lsa_originator == NULL) {
1897 zlog_warn(
1898 "ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1899 goto out;
1900 }
1901
1902 area = (struct ospf_area *)oipt->owner;
1903 if (area == NULL || (top = area->ospf) == NULL) {
1904 zlog_warn(
1905 "ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1906 goto out;
1907 }
1908
1909 /* There must be at least one "opaque-capable, full-state" neighbor. */
1910 n = 0;
1911 for (ALL_LIST_ELEMENTS(area->oiflist, node, nnode, oi)) {
1912 if ((n = ospf_nbr_count_opaque_capable(oi)) > 0)
1913 break;
1914 }
1915
1916 if (n == 0 || !CHECK_FLAG(top->config, OSPF_OPAQUE_CAPABLE)) {
1917 if (IS_DEBUG_OSPF_EVENT)
1918 zlog_debug(
1919 "Suspend re-origination of Type-10 Opaque-LSAs"
1920 " (opaque-type=%u) for a while...",
1921 oipt->opaque_type);
1922
1923 oipt->status = PROC_SUSPEND;
1924 rc = 0;
1925 goto out;
1926 }
1927
1928 if (IS_DEBUG_OSPF_EVENT)
1929 zlog_debug(
1930 "Timer[Type10-LSA]: Re-originate Opaque-LSAs"
1931 " (opaque-type=%u) for Area %s",
1932 oipt->opaque_type, inet_ntoa(area->area_id));
1933
1934 rc = (*functab->lsa_originator)(area);
1935 out:
1936 return rc;
1937 }
1938
1939 static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread *t)
1940 {
1941 struct opaque_info_per_type *oipt;
1942 struct ospf_opaque_functab *functab;
1943 struct ospf *top;
1944 int rc = -1;
1945
1946 oipt = THREAD_ARG(t);
1947 oipt->t_opaque_lsa_self = NULL;
1948
1949 if ((functab = oipt->functab) == NULL
1950 || functab->lsa_originator == NULL) {
1951 zlog_warn(
1952 "ospf_opaque_type11_lsa_reoriginate_timer:"
1953 " No associated function?");
1954 goto out;
1955 }
1956
1957 if ((top = (struct ospf *)oipt->owner) == NULL) {
1958 zlog_warn(
1959 "ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1960 goto out;
1961 }
1962
1963 if (!CHECK_FLAG(top->config, OSPF_OPAQUE_CAPABLE)) {
1964 if (IS_DEBUG_OSPF_EVENT)
1965 zlog_debug(
1966 "Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...",
1967 oipt->opaque_type);
1968
1969 oipt->status = PROC_SUSPEND;
1970 rc = 0;
1971 goto out;
1972 }
1973
1974 if (IS_DEBUG_OSPF_EVENT)
1975 zlog_debug(
1976 "Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).",
1977 oipt->opaque_type);
1978
1979 rc = (*functab->lsa_originator)(top);
1980 out:
1981 return rc;
1982 }
1983
1984 void ospf_opaque_lsa_refresh_schedule(struct ospf_lsa *lsa0)
1985 {
1986 struct opaque_info_per_type *oipt;
1987 struct opaque_info_per_id *oipi;
1988 struct ospf_lsa *lsa;
1989 struct ospf *top;
1990 int delay;
1991
1992 if ((oipt = lookup_opaque_info_by_type(lsa0)) == NULL
1993 || (oipi = lookup_opaque_info_by_id(oipt, lsa0)) == NULL) {
1994 zlog_warn(
1995 "ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
1996 goto out;
1997 }
1998
1999 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2000 if ((lsa = oipi->lsa) == NULL) {
2001 zlog_warn("ospf_opaque_lsa_refresh_schedule: Something wrong?");
2002 goto out;
2003 }
2004
2005 if (oipi->t_opaque_lsa_self != NULL) {
2006 if (IS_DEBUG_OSPF_EVENT)
2007 zlog_debug(
2008 "Type-%u Opaque-LSA has already scheduled to REFRESH: [opaque-type=%u, opaque-id=%x]",
2009 lsa->data->type,
2010 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)),
2011 GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)));
2012 goto out;
2013 }
2014
2015 /* Delete this lsa from neighbor retransmit-list. */
2016 switch (lsa->data->type) {
2017 case OSPF_OPAQUE_LINK_LSA:
2018 case OSPF_OPAQUE_AREA_LSA:
2019 ospf_ls_retransmit_delete_nbr_area(lsa->area, lsa);
2020 break;
2021 case OSPF_OPAQUE_AS_LSA:
2022 top = ospf_lookup_by_vrf_id(lsa0->vrf_id);
2023 if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
2024 top = lsa0->area->ospf;
2025 ospf_ls_retransmit_delete_nbr_as(top, lsa);
2026 break;
2027 default:
2028 zlog_warn(
2029 "ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)",
2030 lsa->data->type);
2031 goto out;
2032 }
2033
2034 delay = ospf_lsa_refresh_delay(lsa);
2035
2036 if (IS_DEBUG_OSPF_EVENT)
2037 zlog_debug(
2038 "Schedule Type-%u Opaque-LSA to REFRESH in %d sec later: [opaque-type=%u, opaque-id=%x]",
2039 lsa->data->type, delay,
2040 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)),
2041 GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)));
2042
2043 OSPF_OPAQUE_TIMER_ON(oipi->t_opaque_lsa_self,
2044 ospf_opaque_lsa_refresh_timer, oipi, delay * 1000);
2045 out:
2046 return;
2047 }
2048
2049 static int ospf_opaque_lsa_refresh_timer(struct thread *t)
2050 {
2051 struct opaque_info_per_id *oipi;
2052 struct ospf_opaque_functab *functab;
2053 struct ospf_lsa *lsa;
2054
2055 if (IS_DEBUG_OSPF_EVENT)
2056 zlog_debug("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
2057
2058 oipi = THREAD_ARG(t);
2059 oipi->t_opaque_lsa_self = NULL;
2060
2061 if ((lsa = oipi->lsa) != NULL)
2062 if ((functab = oipi->opqctl_type->functab) != NULL)
2063 if (functab->lsa_refresher != NULL)
2064 (*functab->lsa_refresher)(lsa);
2065
2066 return 0;
2067 }
2068
2069 void ospf_opaque_lsa_flush_schedule(struct ospf_lsa *lsa0)
2070 {
2071 struct opaque_info_per_type *oipt;
2072 struct opaque_info_per_id *oipi;
2073 struct ospf_lsa *lsa;
2074 struct ospf *top;
2075
2076 top = ospf_lookup_by_vrf_id(lsa0->vrf_id);
2077
2078 if ((oipt = lookup_opaque_info_by_type(lsa0)) == NULL
2079 || (oipi = lookup_opaque_info_by_id(oipt, lsa0)) == NULL) {
2080 zlog_warn("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2081 goto out;
2082 }
2083
2084 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2085 if ((lsa = oipi->lsa) == NULL) {
2086 zlog_warn("ospf_opaque_lsa_flush_schedule: Something wrong?");
2087 goto out;
2088 }
2089
2090 /* Delete this lsa from neighbor retransmit-list. */
2091 switch (lsa->data->type) {
2092 case OSPF_OPAQUE_LINK_LSA:
2093 case OSPF_OPAQUE_AREA_LSA:
2094 ospf_ls_retransmit_delete_nbr_area(lsa->area, lsa);
2095 break;
2096 case OSPF_OPAQUE_AS_LSA:
2097 if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
2098 top = lsa0->area->ospf;
2099 ospf_ls_retransmit_delete_nbr_as(top, lsa);
2100 break;
2101 default:
2102 zlog_warn(
2103 "ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)",
2104 lsa->data->type);
2105 goto out;
2106 }
2107
2108 /* Dequeue listnode entry from the list. */
2109 listnode_delete(oipt->id_list, oipi);
2110
2111 /* Avoid misjudgement in the next lookup. */
2112 if (listcount(oipt->id_list) == 0)
2113 oipt->id_list->head = oipt->id_list->tail = NULL;
2114
2115 /* Disassociate internal control information with the given lsa. */
2116 free_opaque_info_per_id((void *)oipi);
2117
2118 /* Force given lsa's age to MaxAge. */
2119 lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
2120
2121 if (IS_DEBUG_OSPF_EVENT)
2122 zlog_debug(
2123 "Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]",
2124 lsa->data->type,
2125 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)),
2126 GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)));
2127
2128 /* This lsa will be flushed and removed eventually. */
2129 ospf_lsa_flush(top, lsa);
2130
2131 out:
2132 return;
2133 }
2134
2135 void ospf_opaque_self_originated_lsa_received(struct ospf_neighbor *nbr,
2136 struct ospf_lsa *lsa)
2137 {
2138 struct ospf *top;
2139
2140 if ((top = oi_to_top(nbr->oi)) == NULL)
2141 return;
2142
2143 /*
2144 * Since these LSA entries are not yet installed into corresponding
2145 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2146 */
2147 lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
2148 switch (lsa->data->type) {
2149 case OSPF_OPAQUE_LINK_LSA:
2150 ospf_flood_through_area(nbr->oi->area, NULL /*inbr*/, lsa);
2151 break;
2152 case OSPF_OPAQUE_AREA_LSA:
2153 ospf_flood_through_area(nbr->oi->area, NULL /*inbr*/, lsa);
2154 break;
2155 case OSPF_OPAQUE_AS_LSA:
2156 ospf_flood_through_as(top, NULL /*inbr*/, lsa);
2157 break;
2158 default:
2159 zlog_warn(
2160 "ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)",
2161 lsa->data->type);
2162 return;
2163 }
2164 ospf_lsa_discard(lsa); /* List "lsas" will be deleted by caller. */
2165 }
2166
2167 /*------------------------------------------------------------------------*
2168 * Followings are util functions; probably be used by Opaque-LSAs only...
2169 *------------------------------------------------------------------------*/
2170
2171 struct ospf *oi_to_top(struct ospf_interface *oi)
2172 {
2173 struct ospf *top = NULL;
2174 struct ospf_area *area;
2175
2176 if (oi == NULL || (area = oi->area) == NULL
2177 || (top = area->ospf) == NULL)
2178 zlog_warn("Broken relationship for \"OI -> AREA -> OSPF\"?");
2179
2180 return top;
2181 }