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