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