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