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