]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_opaque.c
2003-04-04 Paul Jakma <paul@dishone.st>
[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 /***** MTYPE definitions are not reflected to "memory.h" yet. *****/
25 #define MTYPE_OSPF_OPAQUE_FUNCTAB 0
26 #define MTYPE_OPAQUE_INFO_PER_TYPE 0
27 #define MTYPE_OPAQUE_INFO_PER_ID 0
28
29 #include <zebra.h>
30 #ifdef HAVE_OPAQUE_LSA
31
32 #include "linklist.h"
33 #include "prefix.h"
34 #include "if.h"
35 #include "table.h"
36 #include "memory.h"
37 #include "command.h"
38 #include "vty.h"
39 #include "stream.h"
40 #include "log.h"
41 #include "thread.h"
42 #include "hash.h"
43 #include "sockunion.h" /* for inet_aton() */
44
45 #include "ospfd/ospfd.h"
46 #include "ospfd/ospf_interface.h"
47 #include "ospfd/ospf_ism.h"
48 #include "ospfd/ospf_asbr.h"
49 #include "ospfd/ospf_lsa.h"
50 #include "ospfd/ospf_lsdb.h"
51 #include "ospfd/ospf_neighbor.h"
52 #include "ospfd/ospf_nsm.h"
53 #include "ospfd/ospf_flood.h"
54 #include "ospfd/ospf_packet.h"
55 #include "ospfd/ospf_spf.h"
56 #include "ospfd/ospf_dump.h"
57 #include "ospfd/ospf_route.h"
58 #include "ospfd/ospf_ase.h"
59 #include "ospfd/ospf_zebra.h"
60
61 /*------------------------------------------------------------------------*
62 * Followings are initialize/terminate functions for Opaque-LSAs handling.
63 *------------------------------------------------------------------------*/
64
65 #ifdef HAVE_OSPF_TE
66 #include "ospfd/ospf_te.h"
67 #endif /* HAVE_OSPF_TE */
68
69 #ifdef SUPPORT_OSPF_API
70 int ospf_apiserver_init (void);
71 void ospf_apiserver_term (void);
72 #endif /* SUPPORT_OSPF_API */
73
74 static void ospf_opaque_register_vty (void);
75 static void ospf_opaque_funclist_init (void);
76 static void ospf_opaque_funclist_term (void);
77 static void free_opaque_info_per_type (void *val);
78 static void free_opaque_info_per_id (void *val);
79 static int ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa);
80 static int ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa);
81
82 void
83 ospf_opaque_init (void)
84 {
85 ospf_opaque_register_vty ();
86 ospf_opaque_funclist_init ();
87
88 #ifdef HAVE_OSPF_TE
89 if (ospf_mpls_te_init () != 0)
90 exit (1);
91 #endif /* HAVE_OSPF_TE */
92
93 #ifdef SUPPORT_OSPF_API
94 if (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 #ifdef HAVE_OSPF_TE
105 ospf_mpls_te_term ();
106 #endif /* HAVE_OSPF_TE */
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 default:
222 if (OPAQUE_TYPE_RANGE_UNASSIGNED (opaque_type))
223 name = "Unassigned";
224 else if (OPAQUE_TYPE_RANGE_RESERVED (opaque_type))
225 name = "Private/Experimental";
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 {
239 u_char opaque_type;
240 struct opaque_info_per_type *oipt;
241
242 int (* new_if_hook)(struct interface *ifp);
243 int (* del_if_hook)(struct interface *ifp);
244 void (* ism_change_hook)(struct ospf_interface *oi, int old_status);
245 void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status);
246 void (* config_write_router)(struct vty *vty);
247 void (* config_write_if )(struct vty *vty, struct interface *ifp);
248 void (* config_write_debug )(struct vty *vty);
249 void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa);
250 int (* lsa_originator)(void *arg);
251 void (* lsa_refresher )(struct ospf_lsa *lsa);
252 int (* new_lsa_hook)(struct ospf_lsa *lsa);
253 int (* del_lsa_hook)(struct ospf_lsa *lsa);
254 };
255
256 static list ospf_opaque_wildcard_funclist; /* Handle LSA-9/10/11 altogether. */
257 static list ospf_opaque_type9_funclist;
258 static list ospf_opaque_type10_funclist;
259 static list ospf_opaque_type11_funclist;
260
261 static void
262 ospf_opaque_del_functab (void *val)
263 {
264 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, val);
265 return;
266 }
267
268 static void
269 ospf_opaque_funclist_init (void)
270 {
271 list funclist;
272
273 funclist = ospf_opaque_wildcard_funclist = list_new ();
274 funclist->del = ospf_opaque_del_functab;
275
276 funclist = ospf_opaque_type9_funclist = list_new ();
277 funclist->del = ospf_opaque_del_functab;
278
279 funclist = ospf_opaque_type10_funclist = list_new ();
280 funclist->del = ospf_opaque_del_functab;
281
282 funclist = ospf_opaque_type11_funclist = list_new ();
283 funclist->del = ospf_opaque_del_functab;
284 return;
285 }
286
287 static void
288 ospf_opaque_funclist_term (void)
289 {
290 list funclist;
291
292 funclist = ospf_opaque_wildcard_funclist;
293 list_delete (funclist);
294
295 funclist = ospf_opaque_type9_funclist;
296 list_delete (funclist);
297
298 funclist = ospf_opaque_type10_funclist;
299 list_delete (funclist);
300
301 funclist = ospf_opaque_type11_funclist;
302 list_delete (funclist);
303 return;
304 }
305
306 static list
307 ospf_get_opaque_funclist (u_char lsa_type)
308 {
309 list funclist = NULL;
310
311 switch (lsa_type)
312 {
313 case OPAQUE_TYPE_WILDCARD:
314 /* XXX
315 * This is an ugly trick to handle type-9/10/11 LSA altogether.
316 * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor
317 * an officially assigned opaque-type.
318 * Though it is possible that the value might be officially used
319 * in the future, we use it internally as a special label, for now.
320 */
321 funclist = ospf_opaque_wildcard_funclist;
322 break;
323 case OSPF_OPAQUE_LINK_LSA:
324 funclist = ospf_opaque_type9_funclist;
325 break;
326 case OSPF_OPAQUE_AREA_LSA:
327 funclist = ospf_opaque_type10_funclist;
328 break;
329 case OSPF_OPAQUE_AS_LSA:
330 funclist = ospf_opaque_type11_funclist;
331 break;
332 default:
333 zlog_warn ("ospf_get_opaque_funclist: Unexpected LSA-type(%u)", lsa_type);
334 break;
335 }
336 return funclist;
337 }
338
339 int
340 ospf_register_opaque_functab (
341 u_char lsa_type,
342 u_char opaque_type,
343 int (* new_if_hook)(struct interface *ifp),
344 int (* del_if_hook)(struct interface *ifp),
345 void (* ism_change_hook)(struct ospf_interface *oi, int old_status),
346 void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status),
347 void (* config_write_router)(struct vty *vty),
348 void (* config_write_if )(struct vty *vty, struct interface *ifp),
349 void (* config_write_debug )(struct vty *vty),
350 void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa),
351 int (* lsa_originator)(void *arg),
352 void (* lsa_refresher )(struct ospf_lsa *lsa),
353 int (* new_lsa_hook)(struct ospf_lsa *lsa),
354 int (* del_lsa_hook)(struct ospf_lsa *lsa))
355 {
356 list funclist;
357 struct ospf_opaque_functab *new;
358 int rc = -1;
359
360 if ((funclist = ospf_get_opaque_funclist (lsa_type)) == NULL)
361 {
362 zlog_warn ("ospf_register_opaque_functab: Cannot get funclist for Type-%u LSAs?", lsa_type);
363 goto out;
364 }
365 else
366 {
367 listnode node;
368 struct ospf_opaque_functab *functab;
369
370 for (node = listhead (funclist); node; nextnode (node))
371 if ((functab = getdata (node)) != NULL)
372 if (functab->opaque_type == opaque_type)
373 {
374 zlog_warn ("ospf_register_opaque_functab: Duplicated entry?: lsa_type(%u), opaque_type(%u)", lsa_type, opaque_type);
375 goto out;
376 }
377 }
378
379 if ((new = XCALLOC (MTYPE_OSPF_OPAQUE_FUNCTAB,
380 sizeof (struct ospf_opaque_functab))) == NULL)
381 {
382 zlog_warn ("ospf_register_opaque_functab: XMALLOC: %s", strerror (errno));
383 goto out;
384 }
385
386 new->opaque_type = opaque_type;
387 new->oipt = NULL;
388 new->new_if_hook = new_if_hook;
389 new->del_if_hook = del_if_hook;
390 new->ism_change_hook = ism_change_hook;
391 new->nsm_change_hook = nsm_change_hook;
392 new->config_write_router = config_write_router;
393 new->config_write_if = config_write_if;
394 new->config_write_debug = config_write_debug;
395 new->show_opaque_info = show_opaque_info;
396 new->lsa_originator = lsa_originator;
397 new->lsa_refresher = lsa_refresher;
398 new->new_lsa_hook = new_lsa_hook;
399 new->del_lsa_hook = del_lsa_hook;
400
401 listnode_add (funclist, new);
402 rc = 0;
403
404 out:
405 return rc;
406 }
407
408 void
409 ospf_delete_opaque_functab (u_char lsa_type, u_char opaque_type)
410 {
411 list funclist;
412 listnode node;
413 struct ospf_opaque_functab *functab;
414
415 if ((funclist = ospf_get_opaque_funclist (lsa_type)) != NULL)
416 for (node = listhead (funclist); node; nextnode (node))
417 {
418 if ((functab = getdata (node)) != NULL
419 && functab->opaque_type == opaque_type)
420 {
421 /* Cleanup internal control information, if it still remains. */
422 if (functab->oipt != NULL)
423 free_opaque_info_per_type (functab->oipt);
424
425 /* Dequeue listnode entry from the list. */
426 listnode_delete (funclist, functab);
427
428 /* Avoid misjudgement in the next lookup. */
429 if (listcount (funclist) == 0)
430 funclist->head = funclist->tail = NULL;
431
432 XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, functab);
433 goto out;
434 }
435 }
436 out:
437 return;
438 }
439
440 static struct ospf_opaque_functab *
441 ospf_opaque_functab_lookup (struct ospf_lsa *lsa)
442 {
443 list funclist;
444 listnode node;
445 struct ospf_opaque_functab *functab;
446 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
447
448 if ((funclist = ospf_get_opaque_funclist (lsa->data->type)) != NULL)
449 for (node = listhead (funclist); node; nextnode (node))
450 if ((functab = getdata (node)) != NULL)
451 if (functab->opaque_type == key)
452 return functab;
453
454 return NULL;
455 }
456
457 /*------------------------------------------------------------------------*
458 * Followings are management functions for self-originated LSA entries.
459 *------------------------------------------------------------------------*/
460
461 /*
462 * Opaque-LSA control information per opaque-type.
463 * Single Opaque-Type may have multiple instances; each of them will be
464 * identified by their opaque-id.
465 */
466 struct opaque_info_per_type
467 {
468 u_char lsa_type;
469 u_char opaque_type;
470
471 enum { PROC_NORMAL, PROC_SUSPEND } status;
472
473 /*
474 * Thread for (re-)origination scheduling for this opaque-type.
475 *
476 * Initial origination of Opaque-LSAs is controlled by generic
477 * Opaque-LSA handling module so that same opaque-type entries are
478 * called all at once when certain conditions are met.
479 * However, there might be cases that some Opaque-LSA clients need
480 * to (re-)originate their own Opaque-LSAs out-of-sync with others.
481 * This thread is prepared for that specific purpose.
482 */
483 struct thread *t_opaque_lsa_self;
484
485 /*
486 * Backpointer to an "owner" which is LSA-type dependent.
487 * type-9: struct ospf_interface
488 * type-10: struct ospf_area
489 * type-11: struct ospf
490 */
491 void *owner;
492
493 /* Collection of callback functions for this opaque-type. */
494 struct ospf_opaque_functab *functab;
495
496 /* List of Opaque-LSA control informations per opaque-id. */
497 list id_list;
498 };
499
500 /* Opaque-LSA control information per opaque-id. */
501 struct opaque_info_per_id
502 {
503 u_int32_t opaque_id;
504
505 /* Thread for refresh/flush scheduling for this opaque-type/id. */
506 struct thread *t_opaque_lsa_self;
507
508 /* Backpointer to Opaque-LSA control information per opaque-type. */
509 struct opaque_info_per_type *opqctl_type;
510
511 /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
512 struct ospf_lsa *lsa;
513 };
514
515 static struct opaque_info_per_type *register_opaque_info_per_type (struct ospf_opaque_functab *functab, struct ospf_lsa *new);
516 static struct opaque_info_per_type *lookup_opaque_info_by_type (struct ospf_lsa *lsa);
517 static struct opaque_info_per_id *register_opaque_info_per_id (struct opaque_info_per_type *oipt, struct ospf_lsa *new);
518 static struct opaque_info_per_id *lookup_opaque_info_by_id (struct opaque_info_per_type *oipt, 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))) == NULL)
531 {
532 zlog_warn ("register_opaque_info_per_type: XMALLOC: %s", strerror (errno));
533 goto out;
534 }
535
536 switch (new->data->type)
537 {
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 ();
548 if (new->area != NULL && (top = new->area->ospf) == NULL)
549 {
550 free_opaque_info_per_type ((void *) oipt);
551 oipt = NULL;
552 goto out; /* This case may not exist. */
553 }
554 oipt->owner = top;
555 listnode_add (top->opaque_lsa_self, oipt);
556 break;
557 default:
558 zlog_warn ("register_opaque_info_per_type: Unexpected LSA-type(%u)", new->data->type);
559 free_opaque_info_per_type ((void *) oipt);
560 oipt = NULL;
561 goto out; /* This case may not exist. */
562 }
563
564 oipt->lsa_type = new->data->type;
565 oipt->opaque_type = GET_OPAQUE_TYPE (ntohl (new->data->id.s_addr));
566 oipt->status = PROC_NORMAL;
567 oipt->t_opaque_lsa_self = NULL;
568 oipt->functab = functab;
569 functab->oipt = oipt;
570 oipt->id_list = list_new ();
571 oipt->id_list->del = free_opaque_info_per_id;
572
573 out:
574 return oipt;
575 }
576
577 static void
578 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 listnode node;
584
585 /* Control information per opaque-id may still exist. */
586 for (node = listhead (oipt->id_list); node; nextnode (node))
587 {
588 if ((oipi = getdata (node)) == NULL)
589 continue;
590 if ((lsa = oipi->lsa) == NULL)
591 continue;
592 if (IS_LSA_MAXAGE (lsa))
593 continue;
594 ospf_opaque_lsa_flush_schedule (lsa);
595 }
596
597 /* Remove "oipt" from its owner's self-originated LSA list. */
598 switch (oipt->lsa_type)
599 {
600 case OSPF_OPAQUE_LINK_LSA:
601 {
602 struct ospf_interface *oi = (struct ospf_interface *)(oipt->owner);
603 listnode_delete (oi->opaque_lsa_self, oipt);
604 break;
605 }
606 case OSPF_OPAQUE_AREA_LSA:
607 {
608 struct ospf_area *area = (struct ospf_area *)(oipt->owner);
609 listnode_delete (area->opaque_lsa_self, oipt);
610 break;
611 }
612 case OSPF_OPAQUE_AS_LSA:
613 {
614 struct ospf *top = (struct ospf *)(oipt->owner);
615 listnode_delete (top->opaque_lsa_self, oipt);
616 break;
617 }
618 default:
619 zlog_warn ("free_opaque_info_per_type: Unexpected LSA-type(%u)", oipt->lsa_type);
620 break; /* This case may not exist. */
621 }
622
623 OSPF_TIMER_OFF (oipt->t_opaque_lsa_self);
624 list_delete (oipt->id_list);
625 XFREE (MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
626 return;
627 }
628
629 static struct opaque_info_per_type *
630 lookup_opaque_info_by_type (struct ospf_lsa *lsa)
631 {
632 struct ospf *top;
633 struct ospf_area *area;
634 struct ospf_interface *oi;
635 list listtop = NULL;
636 listnode node;
637 struct opaque_info_per_type *oipt = NULL;
638 u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
639
640 switch (lsa->data->type)
641 {
642 case OSPF_OPAQUE_LINK_LSA:
643 if ((oi = lsa->oi) != NULL)
644 listtop = oi->opaque_lsa_self;
645 else
646 zlog_warn ("Type-9 Opaque-LSA: Reference to OI is missing?");
647 break;
648 case OSPF_OPAQUE_AREA_LSA:
649 if ((area = lsa->area) != NULL)
650 listtop = area->opaque_lsa_self;
651 else
652 zlog_warn ("Type-10 Opaque-LSA: Reference to AREA is missing?");
653 break;
654 case OSPF_OPAQUE_AS_LSA:
655 top = ospf_lookup ();
656 if ((area = lsa->area) != NULL && (top = area->ospf) == NULL)
657 {
658 zlog_warn ("Type-11 Opaque-LSA: Reference to OSPF is missing?");
659 break; /* Unlikely to happen. */
660 }
661 listtop = top->opaque_lsa_self;
662 break;
663 default:
664 zlog_warn ("lookup_opaque_info_by_type: Unexpected LSA-type(%u)", lsa->data->type);
665 break;
666 }
667
668 if (listtop != NULL)
669 for (node = listhead (listtop); node; nextnode (node))
670 if ((oipt = getdata (node)) != NULL)
671 if (oipt->opaque_type == key)
672 return oipt;
673
674 return NULL;
675 }
676
677 static struct opaque_info_per_id *
678 register_opaque_info_per_id (struct opaque_info_per_type *oipt,
679 struct ospf_lsa *new)
680 {
681 struct opaque_info_per_id *oipi;
682
683 if ((oipi = XCALLOC (MTYPE_OPAQUE_INFO_PER_ID,
684 sizeof (struct opaque_info_per_id))) == NULL)
685 {
686 zlog_warn ("register_opaque_info_per_id: XMALLOC: %s", strerror (errno));
687 goto out;
688 }
689 oipi->opaque_id = GET_OPAQUE_ID (ntohl (new->data->id.s_addr));
690 oipi->t_opaque_lsa_self = NULL;
691 oipi->opqctl_type = oipt;
692 oipi->lsa = ospf_lsa_lock (new);
693
694 listnode_add (oipt->id_list, oipi);
695
696 out:
697 return oipi;
698 }
699
700 static void
701 free_opaque_info_per_id (void *val)
702 {
703 struct opaque_info_per_id *oipi = (struct opaque_info_per_id *) val;
704
705 OSPF_TIMER_OFF (oipi->t_opaque_lsa_self);
706 if (oipi->lsa != NULL)
707 ospf_lsa_unlock (oipi->lsa);
708 XFREE (MTYPE_OPAQUE_INFO_PER_ID, oipi);
709 return;
710 }
711
712 static struct opaque_info_per_id *
713 lookup_opaque_info_by_id (struct opaque_info_per_type *oipt,
714 struct ospf_lsa *lsa)
715 {
716 listnode node;
717 struct opaque_info_per_id *oipi;
718 u_int32_t key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
719
720 for (node = listhead (oipt->id_list); node; nextnode (node))
721 if ((oipi = getdata (node)) != NULL)
722 if (oipi->opaque_id == key)
723 return oipi;
724
725 return NULL;
726 }
727
728 static struct opaque_info_per_id *
729 register_opaque_lsa (struct ospf_lsa *new)
730 {
731 struct ospf_opaque_functab *functab;
732 struct opaque_info_per_type *oipt;
733 struct opaque_info_per_id *oipi = NULL;
734
735 if ((functab = ospf_opaque_functab_lookup (new)) == NULL)
736 goto out;
737
738 if ((oipt = lookup_opaque_info_by_type (new)) == NULL
739 && (oipt = register_opaque_info_per_type (functab, new)) == NULL)
740 goto out;
741
742 if ((oipi = register_opaque_info_per_id (oipt, new)) == NULL)
743 goto out;
744
745 out:
746 return oipi;
747 }
748
749 /*------------------------------------------------------------------------*
750 * Followings are (vty) configuration functions for Opaque-LSAs handling.
751 *------------------------------------------------------------------------*/
752
753 DEFUN (capability_opaque,
754 capability_opaque_cmd,
755 "capability opaque",
756 "Enable specific OSPF feature\n"
757 "Opaque LSA\n")
758 {
759 struct ospf *ospf = (struct ospf *) vty->index;
760
761 /* Turn on the "master switch" of opaque-lsa capability. */
762 if (!CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
763 {
764 if (IS_DEBUG_OSPF_EVENT)
765 zlog_info ("Opaque capability: OFF -> ON");
766
767 SET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
768 ospf_renegotiate_optional_capabilities (ospf);
769 }
770 return CMD_SUCCESS;
771 }
772
773 ALIAS (capability_opaque,
774 ospf_opaque_capable_cmd,
775 "ospf opaque-lsa",
776 "OSPF specific commands\n"
777 "Enable the Opaque-LSA capability (rfc2370)\n")
778
779 DEFUN (no_capability_opaque,
780 no_capability_opaque_cmd,
781 "no capability opaque",
782 NO_STR
783 "Enable specific OSPF feature\n"
784 "Opaque LSA\n")
785 {
786 struct ospf *ospf = (struct ospf *) vty->index;
787
788 /* Turn off the "master switch" of opaque-lsa capability. */
789 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
790 {
791 if (IS_DEBUG_OSPF_EVENT)
792 zlog_info ("Opaque capability: ON -> OFF");
793
794 UNSET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
795 ospf_renegotiate_optional_capabilities (ospf);
796 }
797 return CMD_SUCCESS;
798 }
799
800 ALIAS (no_capability_opaque,
801 no_ospf_opaque_capable_cmd,
802 "no ospf opaque-lsa",
803 NO_STR
804 "OSPF specific commands\n"
805 "Disable the Opaque-LSA capability (rfc2370)\n")
806
807 static void
808 ospf_opaque_register_vty (void)
809 {
810 install_element (OSPF_NODE, &capability_opaque_cmd);
811 install_element (OSPF_NODE, &no_capability_opaque_cmd);
812 install_element (OSPF_NODE, &ospf_opaque_capable_cmd);
813 install_element (OSPF_NODE, &no_ospf_opaque_capable_cmd);
814 return;
815 }
816
817 /*------------------------------------------------------------------------*
818 * Followings are collection of user-registered function callers.
819 *------------------------------------------------------------------------*/
820
821 static int
822 opaque_lsa_new_if_callback (list funclist, struct interface *ifp)
823 {
824 listnode node;
825 struct ospf_opaque_functab *functab;
826 int rc = -1;
827
828 for (node = listhead (funclist); node; nextnode (node))
829 if ((functab = getdata (node)) != NULL)
830 if (functab->new_if_hook != NULL)
831 if ((* functab->new_if_hook)(ifp) != 0)
832 goto out;
833 rc = 0;
834 out:
835 return rc;
836 }
837
838 static int
839 opaque_lsa_del_if_callback (list funclist, struct interface *ifp)
840 {
841 listnode node;
842 struct ospf_opaque_functab *functab;
843 int rc = -1;
844
845 for (node = listhead (funclist); node; nextnode (node))
846 if ((functab = getdata (node)) != NULL)
847 if (functab->del_if_hook != NULL)
848 if ((* functab->del_if_hook)(ifp) != 0)
849 goto out;
850 rc = 0;
851 out:
852 return rc;
853 }
854
855 static void
856 opaque_lsa_ism_change_callback (list funclist,
857 struct ospf_interface *oi, int old_status)
858 {
859 listnode node;
860 struct ospf_opaque_functab *functab;
861
862 for (node = listhead (funclist); node; nextnode (node))
863 if ((functab = getdata (node)) != NULL)
864 if (functab->ism_change_hook != NULL)
865 (* functab->ism_change_hook)(oi, old_status);
866 return;
867 }
868
869 static void
870 opaque_lsa_nsm_change_callback (list funclist,
871 struct ospf_neighbor *nbr, int old_status)
872 {
873 listnode node;
874 struct ospf_opaque_functab *functab;
875
876 for (node = listhead (funclist); node; nextnode (node))
877 if ((functab = getdata (node)) != NULL)
878 if (functab->nsm_change_hook != NULL)
879 (* functab->nsm_change_hook)(nbr, old_status);
880 return;
881 }
882
883 static void
884 opaque_lsa_config_write_router_callback (list funclist, struct vty *vty)
885 {
886 listnode node;
887 struct ospf_opaque_functab *functab;
888
889 for (node = listhead (funclist); node; nextnode (node))
890 if ((functab = getdata (node)) != NULL)
891 if (functab->config_write_router != NULL)
892 (* functab->config_write_router)(vty);
893 return;
894 }
895
896 static void
897 opaque_lsa_config_write_if_callback (list funclist,
898 struct vty *vty, struct interface *ifp)
899 {
900 listnode node;
901 struct ospf_opaque_functab *functab;
902
903 for (node = listhead (funclist); node; nextnode (node))
904 if ((functab = getdata (node)) != NULL)
905 if (functab->config_write_if != NULL)
906 (* functab->config_write_if)(vty, ifp);
907 return;
908 }
909
910 static void
911 opaque_lsa_config_write_debug_callback (list funclist, struct vty *vty)
912 {
913 listnode node;
914 struct ospf_opaque_functab *functab;
915
916 for (node = listhead (funclist); node; nextnode (node))
917 if ((functab = getdata (node)) != NULL)
918 if (functab->config_write_debug != NULL)
919 (* functab->config_write_debug)(vty);
920 return;
921 }
922
923 static int
924 opaque_lsa_originate_callback (list funclist, void *lsa_type_dependent)
925 {
926 listnode node;
927 struct ospf_opaque_functab *functab;
928 int rc = -1;
929
930 for (node = listhead (funclist); node; nextnode (node))
931 if ((functab = getdata (node)) != NULL)
932 if (functab->lsa_originator != NULL)
933 if ((* functab->lsa_originator)(lsa_type_dependent) != 0)
934 goto out;
935 rc = 0;
936 out:
937 return rc;
938 }
939
940 static int
941 new_lsa_callback (list funclist, struct ospf_lsa *lsa)
942 {
943 listnode node;
944 struct ospf_opaque_functab *functab;
945 int rc = -1;
946
947 /* This function handles ALL types of LSAs, not only opaque ones. */
948 for (node = listhead (funclist); node; nextnode (node))
949 if ((functab = getdata (node)) != NULL)
950 if (functab->new_lsa_hook != NULL)
951 if ((* functab->new_lsa_hook)(lsa) != 0)
952 goto out;
953 rc = 0;
954 out:
955 return rc;
956 }
957
958 static int
959 del_lsa_callback (list funclist, struct ospf_lsa *lsa)
960 {
961 listnode node;
962 struct ospf_opaque_functab *functab;
963 int rc = -1;
964
965 /* This function handles ALL types of LSAs, not only opaque ones. */
966 for (node = listhead (funclist); node; nextnode (node))
967 if ((functab = getdata (node)) != NULL)
968 if (functab->del_lsa_hook != NULL)
969 if ((* functab->del_lsa_hook)(lsa) != 0)
970 goto out;
971 rc = 0;
972 out:
973 return rc;
974 }
975
976 /*------------------------------------------------------------------------*
977 * Followings are glue functions to call Opaque-LSA specific processing.
978 *------------------------------------------------------------------------*/
979
980 int
981 ospf_opaque_new_if (struct interface *ifp)
982 {
983 list funclist;
984 int rc = -1;
985
986 funclist = ospf_opaque_wildcard_funclist;
987 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
988 goto out;
989
990 funclist = ospf_opaque_type9_funclist;
991 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
992 goto out;
993
994 funclist = ospf_opaque_type10_funclist;
995 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
996 goto out;
997
998 funclist = ospf_opaque_type11_funclist;
999 if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
1000 goto out;
1001
1002 rc = 0;
1003 out:
1004 return rc;
1005 }
1006
1007 int
1008 ospf_opaque_del_if (struct interface *ifp)
1009 {
1010 list funclist;
1011 int rc = -1;
1012
1013 funclist = ospf_opaque_wildcard_funclist;
1014 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1015 goto out;
1016
1017 funclist = ospf_opaque_type9_funclist;
1018 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1019 goto out;
1020
1021 funclist = ospf_opaque_type10_funclist;
1022 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1023 goto out;
1024
1025 funclist = ospf_opaque_type11_funclist;
1026 if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
1027 goto out;
1028
1029 rc = 0;
1030 out:
1031 return rc;
1032 }
1033
1034 void
1035 ospf_opaque_ism_change (struct ospf_interface *oi, int old_status)
1036 {
1037 list funclist;
1038
1039 funclist = ospf_opaque_wildcard_funclist;
1040 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1041
1042 funclist = ospf_opaque_type9_funclist;
1043 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1044
1045 funclist = ospf_opaque_type10_funclist;
1046 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1047
1048 funclist = ospf_opaque_type11_funclist;
1049 opaque_lsa_ism_change_callback (funclist, oi, old_status);
1050
1051 return;
1052 }
1053
1054 void
1055 ospf_opaque_nsm_change (struct ospf_neighbor *nbr, int old_state)
1056 {
1057 struct ospf *top;
1058 list funclist;
1059
1060 if ((top = oi_to_top (nbr->oi)) == NULL)
1061 goto out;
1062
1063 if (old_state != NSM_Full && nbr->state == NSM_Full)
1064 {
1065 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
1066 {
1067 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1068 {
1069 if (IS_DEBUG_OSPF_EVENT)
1070 zlog_info ("Opaque-LSA: Now get operational!");
1071
1072 SET_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT);
1073 }
1074
1075 ospf_opaque_lsa_originate_schedule (nbr->oi, NULL);
1076 }
1077 }
1078 else
1079 if (old_state == NSM_Full && nbr->state != NSM_Full)
1080 {
1081 #ifdef NOTYET
1082 /*
1083 * If no more opaque-capable full-state neighbor remains in the
1084 * flooding scope which corresponds to Opaque-LSA type, periodic
1085 * LS flooding should be stopped.
1086 */
1087 #endif /* NOTYET */
1088 ;
1089 }
1090
1091 funclist = ospf_opaque_wildcard_funclist;
1092 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1093
1094 funclist = ospf_opaque_type9_funclist;
1095 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1096
1097 funclist = ospf_opaque_type10_funclist;
1098 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1099
1100 funclist = ospf_opaque_type11_funclist;
1101 opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
1102
1103 out:
1104 return;
1105 }
1106
1107 void
1108 ospf_opaque_config_write_router (struct vty *vty, struct ospf *ospf)
1109 {
1110 list funclist;
1111
1112 if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
1113 vty_out (vty, " capability opaque%s", VTY_NEWLINE);
1114
1115 funclist = ospf_opaque_wildcard_funclist;
1116 opaque_lsa_config_write_router_callback (funclist, vty);
1117
1118 funclist = ospf_opaque_type9_funclist;
1119 opaque_lsa_config_write_router_callback (funclist, vty);
1120
1121 funclist = ospf_opaque_type10_funclist;
1122 opaque_lsa_config_write_router_callback (funclist, vty);
1123
1124 funclist = ospf_opaque_type11_funclist;
1125 opaque_lsa_config_write_router_callback (funclist, vty);
1126
1127 return;
1128 }
1129
1130 void
1131 ospf_opaque_config_write_if (struct vty *vty, struct interface *ifp)
1132 {
1133 list funclist;
1134
1135 funclist = ospf_opaque_wildcard_funclist;
1136 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1137
1138 funclist = ospf_opaque_type9_funclist;
1139 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1140
1141 funclist = ospf_opaque_type10_funclist;
1142 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1143
1144 funclist = ospf_opaque_type11_funclist;
1145 opaque_lsa_config_write_if_callback (funclist, vty, ifp);
1146
1147 return;
1148 }
1149
1150 void
1151 ospf_opaque_config_write_debug (struct vty *vty)
1152 {
1153 list funclist;
1154
1155 funclist = ospf_opaque_wildcard_funclist;
1156 opaque_lsa_config_write_debug_callback (funclist, vty);
1157
1158 funclist = ospf_opaque_type9_funclist;
1159 opaque_lsa_config_write_debug_callback (funclist, vty);
1160
1161 funclist = ospf_opaque_type10_funclist;
1162 opaque_lsa_config_write_debug_callback (funclist, vty);
1163
1164 funclist = ospf_opaque_type11_funclist;
1165 opaque_lsa_config_write_debug_callback (funclist, vty);
1166
1167 return;
1168 }
1169
1170 void
1171 show_opaque_info_detail (struct vty *vty, struct ospf_lsa *lsa)
1172 {
1173 struct lsa_header *lsah = (struct lsa_header *) lsa->data;
1174 u_int32_t lsid = ntohl (lsah->id.s_addr);
1175 u_char opaque_type = GET_OPAQUE_TYPE (lsid);
1176 u_int32_t opaque_id = GET_OPAQUE_ID (lsid);
1177 struct ospf_opaque_functab *functab;
1178
1179 /* Switch output functionality by vty address. */
1180 if (vty != NULL)
1181 {
1182 vty_out (vty, " Opaque-Type %u (%s)%s", opaque_type,
1183 ospf_opaque_type_name (opaque_type), VTY_NEWLINE);
1184 vty_out (vty, " Opaque-ID 0x%x%s", opaque_id, VTY_NEWLINE);
1185
1186 vty_out (vty, " Opaque-Info: %u octets of data%s%s",
1187 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1188 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)",
1189 VTY_NEWLINE);
1190 }
1191 else
1192 {
1193 zlog_info (" Opaque-Type %u (%s)", opaque_type,
1194 ospf_opaque_type_name (opaque_type));
1195 zlog_info (" Opaque-ID 0x%x", opaque_id);
1196
1197 zlog_info (" Opaque-Info: %u octets of data%s",
1198 ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
1199 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)");
1200 }
1201
1202 /* Call individual output functions. */
1203 if ((functab = ospf_opaque_functab_lookup (lsa)) != NULL)
1204 if (functab->show_opaque_info != NULL)
1205 (* functab->show_opaque_info)(vty, lsa);
1206
1207 return;
1208 }
1209
1210 void
1211 ospf_opaque_lsa_dump (struct stream *s, u_int16_t length)
1212 {
1213 struct ospf_lsa lsa;
1214
1215 lsa.data = (struct lsa_header *) STREAM_PNT (s);
1216 show_opaque_info_detail (NULL, &lsa);
1217 return;
1218 }
1219
1220 static int
1221 ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa)
1222 {
1223 list funclist;
1224 int rc = -1;
1225
1226 /*
1227 * Some Opaque-LSA user may want to monitor every LSA installation
1228 * into the LSDB, regardless with target LSA type.
1229 */
1230 funclist = ospf_opaque_wildcard_funclist;
1231 if (new_lsa_callback (funclist, lsa) != 0)
1232 goto out;
1233
1234 funclist = ospf_opaque_type9_funclist;
1235 if (new_lsa_callback (funclist, lsa) != 0)
1236 goto out;
1237
1238 funclist = ospf_opaque_type10_funclist;
1239 if (new_lsa_callback (funclist, lsa) != 0)
1240 goto out;
1241
1242 funclist = ospf_opaque_type11_funclist;
1243 if (new_lsa_callback (funclist, lsa) != 0)
1244 goto out;
1245
1246 rc = 0;
1247 out:
1248 return rc;
1249 }
1250
1251 static int
1252 ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa)
1253 {
1254 list funclist;
1255 int rc = -1;
1256
1257 /*
1258 * Some Opaque-LSA user may want to monitor every LSA deletion
1259 * from the LSDB, regardless with target LSA type.
1260 */
1261 funclist = ospf_opaque_wildcard_funclist;
1262 if (del_lsa_callback (funclist, lsa) != 0)
1263 goto out;
1264
1265 funclist = ospf_opaque_type9_funclist;
1266 if (del_lsa_callback (funclist, lsa) != 0)
1267 goto out;
1268
1269 funclist = ospf_opaque_type10_funclist;
1270 if (del_lsa_callback (funclist, lsa) != 0)
1271 goto out;
1272
1273 funclist = ospf_opaque_type11_funclist;
1274 if (del_lsa_callback (funclist, lsa) != 0)
1275 goto out;
1276
1277 rc = 0;
1278 out:
1279 return rc;
1280 }
1281
1282 /*------------------------------------------------------------------------*
1283 * Followings are Opaque-LSA origination/refresh management functions.
1284 *------------------------------------------------------------------------*/
1285
1286 static int ospf_opaque_type9_lsa_originate (struct thread *t);
1287 static int ospf_opaque_type10_lsa_originate (struct thread *t);
1288 static int ospf_opaque_type11_lsa_originate (struct thread *t);
1289 static void ospf_opaque_lsa_reoriginate_resume (list listtop, void *arg);
1290
1291 void
1292 ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0)
1293 {
1294 struct ospf *top;
1295 struct ospf_area *area;
1296 listnode node;
1297 struct opaque_info_per_type *oipt;
1298 int delay = 0;
1299
1300 if ((top = oi_to_top (oi)) == NULL || (area = oi->area) == NULL)
1301 {
1302 zlog_warn ("ospf_opaque_lsa_originate_schedule: Invalid argument?");
1303 goto out;
1304 }
1305
1306 /* It may not a right time to schedule origination now. */
1307 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1308 {
1309 if (IS_DEBUG_OSPF_EVENT)
1310 zlog_info ("ospf_opaque_lsa_originate_schedule: Not operational.");
1311 goto out; /* This is not an error. */
1312 }
1313 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
1314 {
1315 if (IS_DEBUG_OSPF_EVENT)
1316 zlog_info ("ospf_opaque_lsa_originate_schedule: Under blockade.");
1317 goto out; /* This is not an error, too. */
1318 }
1319
1320 if (delay0 != NULL)
1321 delay = *delay0;
1322
1323 /*
1324 * There might be some entries that have been waiting for triggering
1325 * of per opaque-type re-origination get resumed.
1326 */
1327 ospf_opaque_lsa_reoriginate_resume ( oi->opaque_lsa_self, (void *) oi);
1328 ospf_opaque_lsa_reoriginate_resume (area->opaque_lsa_self, (void *) area);
1329 ospf_opaque_lsa_reoriginate_resume ( top->opaque_lsa_self, (void *) top);
1330
1331 /*
1332 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1333 */
1334 if (! list_isempty (ospf_opaque_type9_funclist)
1335 && list_isempty (oi->opaque_lsa_self)
1336 && oi->t_opaque_lsa_self == NULL)
1337 {
1338 if (IS_DEBUG_OSPF_EVENT)
1339 zlog_info ("Schedule Type-9 Opaque-LSA origination in %d sec later.", delay);
1340 oi->t_opaque_lsa_self =
1341 thread_add_timer (master, ospf_opaque_type9_lsa_originate, oi, delay);
1342 delay += OSPF_MIN_LS_INTERVAL;
1343 }
1344
1345 if (! list_isempty (ospf_opaque_type10_funclist)
1346 && list_isempty (area->opaque_lsa_self)
1347 && area->t_opaque_lsa_self == NULL)
1348 {
1349 /*
1350 * One AREA may contain multiple OIs, but above 2nd and 3rd
1351 * conditions prevent from scheduling the originate function
1352 * again and again.
1353 */
1354 if (IS_DEBUG_OSPF_EVENT)
1355 zlog_info ("Schedule Type-10 Opaque-LSA origination in %d sec later.", delay);
1356 area->t_opaque_lsa_self =
1357 thread_add_timer (master, ospf_opaque_type10_lsa_originate,
1358 area, delay);
1359 delay += OSPF_MIN_LS_INTERVAL;
1360 }
1361
1362 if (! list_isempty (ospf_opaque_type11_funclist)
1363 && list_isempty (top->opaque_lsa_self)
1364 && top->t_opaque_lsa_self == NULL)
1365 {
1366 /*
1367 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1368 * conditions prevent from scheduling the originate function
1369 * again and again.
1370 */
1371 if (IS_DEBUG_OSPF_EVENT)
1372 zlog_info ("Schedule Type-11 Opaque-LSA origination in %d sec later.", delay);
1373 top->t_opaque_lsa_self =
1374 thread_add_timer (master, ospf_opaque_type11_lsa_originate,
1375 top, delay);
1376 delay += OSPF_MIN_LS_INTERVAL;
1377 }
1378
1379 /*
1380 * Following section treats a special situation that this node's
1381 * opaque capability has changed as "ON -> OFF -> ON".
1382 */
1383 if (! list_isempty (ospf_opaque_type9_funclist)
1384 && ! list_isempty (oi->opaque_lsa_self))
1385 {
1386 for (node = listhead (oi->opaque_lsa_self); node; nextnode (node))
1387 {
1388 if ((oipt = getdata (node)) == NULL /* Something wrong? */
1389 || oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1390 || oipt->status == PROC_SUSPEND /* Cannot originate now. */
1391 || ! list_isempty (oipt->id_list)) /* Handler is already active. */
1392 continue;
1393
1394 ospf_opaque_lsa_reoriginate_schedule ((void *) oi,
1395 OSPF_OPAQUE_LINK_LSA, oipt->opaque_type);
1396 }
1397 }
1398
1399 if (! list_isempty (ospf_opaque_type10_funclist)
1400 && ! list_isempty (area->opaque_lsa_self))
1401 {
1402 for (node = listhead (area->opaque_lsa_self); node; nextnode (node))
1403 {
1404 if ((oipt = getdata (node)) == NULL /* Something wrong? */
1405 || oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1406 || oipt->status == PROC_SUSPEND /* Cannot originate now. */
1407 || ! list_isempty (oipt->id_list)) /* Handler is already active. */
1408 continue;
1409
1410 ospf_opaque_lsa_reoriginate_schedule ((void *) area,
1411 OSPF_OPAQUE_AREA_LSA, oipt->opaque_type);
1412 }
1413 }
1414
1415 if (! list_isempty (ospf_opaque_type11_funclist)
1416 && ! list_isempty (top->opaque_lsa_self))
1417 {
1418 for (node = listhead (top->opaque_lsa_self); node; nextnode (node))
1419 {
1420 if ((oipt = getdata (node)) == NULL /* Something wrong? */
1421 || oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
1422 || oipt->status == PROC_SUSPEND /* Cannot originate now. */
1423 || ! list_isempty (oipt->id_list)) /* Handler is already active. */
1424 continue;
1425
1426 ospf_opaque_lsa_reoriginate_schedule ((void *) top,
1427 OSPF_OPAQUE_AS_LSA, oipt->opaque_type);
1428 }
1429 }
1430
1431 if (delay0 != NULL)
1432 *delay0 = delay;
1433
1434 out:
1435 return;
1436 }
1437
1438 static int
1439 ospf_opaque_type9_lsa_originate (struct thread *t)
1440 {
1441 struct ospf_interface *oi;
1442 int rc;
1443
1444 oi = THREAD_ARG (t);
1445 oi->t_opaque_lsa_self = NULL;
1446
1447 if (IS_DEBUG_OSPF_EVENT)
1448 zlog_info ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
1449 IF_NAME (oi));
1450
1451 rc = opaque_lsa_originate_callback (ospf_opaque_type9_funclist, oi);
1452
1453 return rc;
1454 }
1455
1456 static int
1457 ospf_opaque_type10_lsa_originate (struct thread *t)
1458 {
1459 struct ospf_area *area;
1460 int rc;
1461
1462 area = THREAD_ARG (t);
1463 area->t_opaque_lsa_self = NULL;
1464
1465 if (IS_DEBUG_OSPF_EVENT)
1466 zlog_info ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
1467 inet_ntoa (area->area_id));
1468
1469 rc = opaque_lsa_originate_callback (ospf_opaque_type10_funclist, area);
1470
1471 return rc;
1472 }
1473
1474 static int
1475 ospf_opaque_type11_lsa_originate (struct thread *t)
1476 {
1477 struct ospf *top;
1478 int rc;
1479
1480 top = THREAD_ARG (t);
1481 top->t_opaque_lsa_self = NULL;
1482
1483 if (IS_DEBUG_OSPF_EVENT)
1484 zlog_info ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
1485
1486 rc = opaque_lsa_originate_callback (ospf_opaque_type11_funclist, top);
1487
1488 return rc;
1489 }
1490
1491 static void
1492 ospf_opaque_lsa_reoriginate_resume (list listtop, void *arg)
1493 {
1494 listnode node;
1495 struct opaque_info_per_type *oipt;
1496 struct ospf_opaque_functab *functab;
1497
1498 if (listtop == NULL)
1499 goto out;
1500
1501 /*
1502 * Pickup oipt entries those which in SUSPEND status, and give
1503 * them a chance to start re-origination now.
1504 */
1505 for (node = listhead (listtop); node; nextnode (node))
1506 {
1507 if ((oipt = getdata (node)) == NULL
1508 || oipt->status != PROC_SUSPEND)
1509 continue;
1510
1511 oipt->status = PROC_NORMAL;
1512
1513 if ((functab = oipt->functab) == NULL
1514 || functab->lsa_originator == NULL)
1515 continue;
1516
1517 if ((* functab->lsa_originator)(arg) != 0)
1518 {
1519 zlog_warn ("ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", oipt->opaque_type);
1520 continue;
1521 }
1522 }
1523
1524 out:
1525 return;
1526 }
1527
1528 struct ospf_lsa *
1529 ospf_opaque_lsa_install (struct ospf_lsa *lsa, int rt_recalc)
1530 {
1531 struct ospf_lsa *new = NULL;
1532 struct opaque_info_per_type *oipt;
1533 struct opaque_info_per_id *oipi;
1534 struct ospf *top;
1535
1536 /* Don't take "rt_recalc" into consideration for now. *//* XXX */
1537
1538 if (! IS_LSA_SELF (lsa))
1539 {
1540 new = lsa; /* Don't touch this LSA. */
1541 goto out;
1542 }
1543
1544 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
1545 zlog_info ("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)));
1546
1547 /* Replace the existing lsa with the new one. */
1548 if ((oipt = lookup_opaque_info_by_type (lsa)) != NULL
1549 && (oipi = lookup_opaque_info_by_id (oipt, lsa)) != NULL)
1550 {
1551 ospf_lsa_unlock (oipi->lsa);
1552 oipi->lsa = ospf_lsa_lock (lsa);
1553 }
1554 /* Register the new lsa entry and get its control info. */
1555 else
1556 if ((oipi = register_opaque_lsa (lsa)) == NULL)
1557 {
1558 zlog_warn ("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1559 goto out;
1560 }
1561
1562 /*
1563 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1564 * for periodic refresh of self-originated Opaque-LSAs.
1565 */
1566 switch (lsa->data->type)
1567 {
1568 case OSPF_OPAQUE_LINK_LSA:
1569 if ((top = oi_to_top (lsa->oi)) == NULL)
1570 {
1571 /* Above conditions must have passed. */
1572 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1573 goto out;
1574 }
1575 break;
1576 case OSPF_OPAQUE_AREA_LSA:
1577 if (lsa->area == NULL || (top = lsa->area->ospf) == NULL)
1578 {
1579 /* Above conditions must have passed. */
1580 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1581 goto out;
1582 }
1583 break;
1584 case OSPF_OPAQUE_AS_LSA:
1585 top = ospf_lookup ();
1586 if (lsa->area != NULL && (top = lsa->area->ospf) == NULL)
1587 {
1588 /* Above conditions must have passed. */
1589 zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
1590 goto out;
1591 }
1592 break;
1593 default:
1594 zlog_warn ("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", lsa->data->type);
1595 goto out;
1596 }
1597
1598 ospf_refresher_register_lsa (top, lsa);
1599 new = lsa;
1600
1601 out:
1602 return new;
1603 }
1604
1605 void
1606 ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
1607 {
1608 struct ospf *ospf;
1609 struct ospf_opaque_functab *functab;
1610
1611 ospf = ospf_lookup ();
1612
1613 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL
1614 || functab->lsa_refresher == NULL)
1615 {
1616 /*
1617 * Though this LSA seems to have originated on this node, the
1618 * handling module for this "lsa-type and opaque-type" was
1619 * already deleted sometime ago.
1620 * Anyway, this node still has a responsibility to flush this
1621 * LSA from the routing domain.
1622 */
1623 if (IS_DEBUG_OSPF_EVENT)
1624 zlog_info ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id));
1625
1626 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
1627 ospf_lsa_maxage (ospf, lsa);
1628 }
1629 else
1630 (* functab->lsa_refresher)(lsa);
1631
1632 return;
1633 }
1634
1635 /*------------------------------------------------------------------------*
1636 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1637 * triggered by external interventions (vty session, signaling, etc).
1638 *------------------------------------------------------------------------*/
1639
1640 #define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
1641 if (!(T)) \
1642 (T) = thread_add_timer (master, (F), (L), (V))
1643
1644 static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type);
1645 static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t);
1646 static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t);
1647 static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t);
1648 static int ospf_opaque_lsa_refresh_timer (struct thread *t);
1649
1650 void
1651 ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
1652 u_char lsa_type, u_char opaque_type)
1653 {
1654 struct ospf *top;
1655 struct ospf_area dummy, *area = NULL;
1656 struct ospf_interface *oi = NULL;
1657
1658 struct ospf_lsa *lsa;
1659 struct opaque_info_per_type *oipt;
1660 int (* func)(struct thread *t) = NULL;
1661 int delay;
1662
1663 switch (lsa_type)
1664 {
1665 case OSPF_OPAQUE_LINK_LSA:
1666 if ((oi = (struct ospf_interface *) lsa_type_dependent) == NULL)
1667 {
1668 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Type-9 Opaque-LSA: Invalid parameter?");
1669 goto out;
1670 }
1671 if ((top = oi_to_top (oi)) == NULL)
1672 {
1673 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?", IF_NAME (oi));
1674 goto out;
1675 }
1676 if (! list_isempty (ospf_opaque_type9_funclist)
1677 && list_isempty (oi->opaque_lsa_self)
1678 && oi->t_opaque_lsa_self != NULL)
1679 {
1680 zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u): Common origination for OI(%s) has already started", opaque_type, IF_NAME (oi));
1681 goto out;
1682 }
1683 func = ospf_opaque_type9_lsa_reoriginate_timer;
1684 break;
1685 case OSPF_OPAQUE_AREA_LSA:
1686 if ((area = (struct ospf_area *) lsa_type_dependent) == NULL)
1687 {
1688 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Type-10 Opaque-LSA: Invalid parameter?");
1689 goto out;
1690 }
1691 if ((top = area->ospf) == NULL)
1692 {
1693 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: AREA(%s) -> TOP?", inet_ntoa (area->area_id));
1694 goto out;
1695 }
1696 if (! list_isempty (ospf_opaque_type10_funclist)
1697 && list_isempty (area->opaque_lsa_self)
1698 && area->t_opaque_lsa_self != NULL)
1699 {
1700 zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u): Common origination for AREA(%s) has already started", opaque_type, inet_ntoa (area->area_id));
1701 goto out;
1702 }
1703 func = ospf_opaque_type10_lsa_reoriginate_timer;
1704 break;
1705 case OSPF_OPAQUE_AS_LSA:
1706 if ((top = (struct ospf *) lsa_type_dependent) == NULL)
1707 {
1708 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Type-11 Opaque-LSA: Invalid parameter?");
1709 goto out;
1710 }
1711 if (! list_isempty (ospf_opaque_type11_funclist)
1712 && list_isempty (top->opaque_lsa_self)
1713 && top->t_opaque_lsa_self != NULL)
1714 {
1715 zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u): Common origination has already started", opaque_type);
1716 goto out;
1717 }
1718
1719 /* Fake "area" to pass "ospf" to a lookup function later. */
1720 dummy.ospf = top;
1721 area = &dummy;
1722
1723 func = ospf_opaque_type11_lsa_reoriginate_timer;
1724 break;
1725 default:
1726 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Unexpected LSA-type(%u)", lsa_type);
1727 goto out;
1728 }
1729
1730 /* It may not a right time to schedule reorigination now. */
1731 if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
1732 {
1733 if (IS_DEBUG_OSPF_EVENT)
1734 zlog_info ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
1735 goto out; /* This is not an error. */
1736 }
1737 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
1738 {
1739 if (IS_DEBUG_OSPF_EVENT)
1740 zlog_info ("ospf_opaque_lsa_reoriginate_schedule: Under blockade.");
1741 goto out; /* This is not an error, too. */
1742 }
1743
1744 /* Generate a dummy lsa to be passed for a lookup function. */
1745 lsa = pseudo_lsa (oi, area, lsa_type, opaque_type);
1746
1747 if ((oipt = lookup_opaque_info_by_type (lsa)) == NULL)
1748 {
1749 struct ospf_opaque_functab *functab;
1750 if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL)
1751 {
1752 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: No associated function?: lsa_type(%u), opaque_type(%u)", lsa_type, opaque_type);
1753 goto out;
1754 }
1755 if ((oipt = register_opaque_info_per_type (functab, lsa)) == NULL)
1756 {
1757 zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Cannot get a control info?: lsa_type(%u), opaque_type(%u)", lsa_type, opaque_type);
1758 goto out;
1759 }
1760 }
1761
1762 if (oipt->t_opaque_lsa_self != NULL)
1763 {
1764 if (IS_DEBUG_OSPF_EVENT)
1765 zlog_info ("Type-%u Opaque-LSA has already scheduled to RE-ORIGINATE: [opaque-type=%u]", lsa_type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
1766 goto out;
1767 }
1768
1769 /*
1770 * Different from initial origination time, in which various conditions
1771 * (opaque capability, neighbor status etc) are assured by caller of
1772 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1773 * it is highly possible that these conditions might not be satisfied
1774 * at the time of re-origination function is to be called.
1775 */
1776 delay = OSPF_MIN_LS_INTERVAL; /* XXX */
1777
1778 if (IS_DEBUG_OSPF_EVENT)
1779 zlog_info ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d sec later: [opaque-type=%u]", lsa_type, delay, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
1780
1781 OSPF_OPAQUE_TIMER_ON (oipt->t_opaque_lsa_self, func, oipt, delay);
1782
1783 out:
1784 return;
1785 }
1786
1787 static struct ospf_lsa *
1788 pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area,
1789 u_char lsa_type, u_char opaque_type)
1790 {
1791 static struct ospf_lsa lsa = { 0 };
1792 static struct lsa_header lsah = { 0 };
1793 u_int32_t tmp;
1794
1795 lsa.oi = oi;
1796 lsa.area = area;
1797 lsa.data = &lsah;
1798
1799 lsah.type = lsa_type;
1800 tmp = SET_OPAQUE_LSID (opaque_type, 0); /* Opaque-ID is unused here. */
1801 lsah.id.s_addr = htonl (tmp);
1802
1803 return &lsa;
1804 }
1805
1806 static int
1807 ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t)
1808 {
1809 struct opaque_info_per_type *oipt;
1810 struct ospf_opaque_functab *functab;
1811 struct ospf *top;
1812 struct ospf_interface *oi;
1813 int rc = -1;
1814
1815 oipt = THREAD_ARG (t);
1816 oipt->t_opaque_lsa_self = NULL;
1817
1818 if ((functab = oipt->functab) == NULL
1819 || functab->lsa_originator == NULL)
1820 {
1821 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1822 goto out;
1823 }
1824
1825 oi = (struct ospf_interface *) oipt->owner;
1826 if ((top = oi_to_top (oi)) == NULL)
1827 {
1828 zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1829 goto out;
1830 }
1831
1832 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)
1833 || ! ospf_if_is_enable (oi)
1834 || ospf_nbr_count_opaque_capable (oi) == 0)
1835 {
1836 if (IS_DEBUG_OSPF_EVENT)
1837 zlog_info ("Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
1838
1839 oipt->status = PROC_SUSPEND;
1840 rc = 0;
1841 goto out;
1842 }
1843
1844 if (IS_DEBUG_OSPF_EVENT)
1845 zlog_info ("Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)", oipt->opaque_type, IF_NAME (oi));
1846
1847 rc = (* functab->lsa_originator)(oi);
1848 out:
1849 return rc;
1850 }
1851
1852 static int
1853 ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t)
1854 {
1855 struct opaque_info_per_type *oipt;
1856 struct ospf_opaque_functab *functab;
1857 listnode node;
1858 struct ospf *top;
1859 struct ospf_area *area;
1860 struct ospf_interface *oi;
1861 int n, rc = -1;
1862
1863 oipt = THREAD_ARG (t);
1864 oipt->t_opaque_lsa_self = NULL;
1865
1866 if ((functab = oipt->functab) == NULL
1867 || functab->lsa_originator == NULL)
1868 {
1869 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1870 goto out;
1871 }
1872
1873 area = (struct ospf_area *) oipt->owner;
1874 if (area == NULL || (top = area->ospf) == NULL)
1875 {
1876 zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1877 goto out;
1878 }
1879
1880 /* There must be at least one "opaque-capable, full-state" neighbor. */
1881 n = 0;
1882 for (node = listhead (area->oiflist); node; nextnode (node))
1883 {
1884 if ((oi = getdata (node)) == NULL)
1885 continue;
1886 if ((n = ospf_nbr_count_opaque_capable (oi)) > 0)
1887 break;
1888 }
1889
1890 if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1891 {
1892 if (IS_DEBUG_OSPF_EVENT)
1893 zlog_info ("Suspend re-origination of Type-10 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
1894
1895 oipt->status = PROC_SUSPEND;
1896 rc = 0;
1897 goto out;
1898 }
1899
1900 if (IS_DEBUG_OSPF_EVENT)
1901 zlog_info ("Timer[Type10-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for Area %s", oipt->opaque_type, inet_ntoa (area->area_id));
1902
1903 rc = (* functab->lsa_originator)(area);
1904 out:
1905 return rc;
1906 }
1907
1908 static int
1909 ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t)
1910 {
1911 struct opaque_info_per_type *oipt;
1912 struct ospf_opaque_functab *functab;
1913 struct ospf *top;
1914 int rc = -1;
1915
1916 oipt = THREAD_ARG (t);
1917 oipt->t_opaque_lsa_self = NULL;
1918
1919 if ((functab = oipt->functab) == NULL
1920 || functab->lsa_originator == NULL)
1921 {
1922 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: No associated function?");
1923 goto out;
1924 }
1925
1926 if ((top = (struct ospf *) oipt->owner) == NULL)
1927 {
1928 zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1929 goto out;
1930 }
1931
1932 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
1933 {
1934 if (IS_DEBUG_OSPF_EVENT)
1935 zlog_info ("Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
1936
1937 oipt->status = PROC_SUSPEND;
1938 rc = 0;
1939 goto out;
1940 }
1941
1942 if (IS_DEBUG_OSPF_EVENT)
1943 zlog_info ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type);
1944
1945 rc = (* functab->lsa_originator)(top);
1946 out:
1947 return rc;
1948 }
1949
1950 extern int ospf_lsa_refresh_delay (struct ospf_lsa *); /* ospf_lsa.c */
1951
1952 void
1953 ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
1954 {
1955 struct ospf *ospf = ospf;
1956 struct opaque_info_per_type *oipt;
1957 struct opaque_info_per_id *oipi;
1958 struct ospf_lsa *lsa;
1959 int delay;
1960
1961 ospf = ospf_lookup ();
1962
1963 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
1964 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
1965 {
1966 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
1967 goto out;
1968 }
1969
1970 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
1971 if ((lsa = oipi->lsa) == NULL)
1972 {
1973 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
1974 goto out;
1975 }
1976
1977 if (oipi->t_opaque_lsa_self != NULL)
1978 {
1979 if (IS_DEBUG_OSPF_EVENT)
1980 zlog_info ("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)));
1981 goto out;
1982 }
1983
1984 /* Delete this lsa from neighbor retransmit-list. */
1985 switch (lsa->data->type)
1986 {
1987 case OSPF_OPAQUE_LINK_LSA:
1988 case OSPF_OPAQUE_AREA_LSA:
1989 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
1990 break;
1991 case OSPF_OPAQUE_AS_LSA:
1992 ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
1993 break;
1994 default:
1995 zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type);
1996 goto out;
1997 }
1998
1999 delay = ospf_lsa_refresh_delay (lsa);
2000
2001 if (IS_DEBUG_OSPF_EVENT)
2002 zlog_info ("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)));
2003
2004 OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self,
2005 ospf_opaque_lsa_refresh_timer, oipi, delay);
2006 out:
2007 return;
2008 }
2009
2010 static int
2011 ospf_opaque_lsa_refresh_timer (struct thread *t)
2012 {
2013 struct opaque_info_per_id *oipi;
2014 struct ospf_opaque_functab *functab;
2015 struct ospf_lsa *lsa;
2016
2017 if (IS_DEBUG_OSPF_EVENT)
2018 zlog_info ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
2019
2020 oipi = THREAD_ARG (t);
2021 oipi->t_opaque_lsa_self = NULL;
2022
2023 if ((lsa = oipi->lsa) != NULL)
2024 if ((functab = oipi->opqctl_type->functab) != NULL)
2025 if (functab->lsa_refresher != NULL)
2026 (* functab->lsa_refresher)(lsa);
2027
2028 return 0;
2029 }
2030
2031 void
2032 ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
2033 {
2034 struct ospf *ospf = ospf;
2035 struct opaque_info_per_type *oipt;
2036 struct opaque_info_per_id *oipi;
2037 struct ospf_lsa *lsa;
2038
2039 ospf = ospf_lookup ();
2040
2041 if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
2042 || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
2043 {
2044 zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2045 goto out;
2046 }
2047
2048 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2049 if ((lsa = oipi->lsa) == NULL)
2050 {
2051 zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
2052 goto out;
2053 }
2054
2055 /* Delete this lsa from neighbor retransmit-list. */
2056 switch (lsa->data->type)
2057 {
2058 case OSPF_OPAQUE_LINK_LSA:
2059 case OSPF_OPAQUE_AREA_LSA:
2060 ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
2061 break;
2062 case OSPF_OPAQUE_AS_LSA:
2063 ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
2064 break;
2065 default:
2066 zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type);
2067 goto out;
2068 }
2069
2070 /* Dequeue listnode entry from the list. */
2071 listnode_delete (oipt->id_list, oipi);
2072
2073 /* Avoid misjudgement in the next lookup. */
2074 if (listcount (oipt->id_list) == 0)
2075 oipt->id_list->head = oipt->id_list->tail = NULL;
2076
2077 /* Disassociate internal control information with the given lsa. */
2078 oipi->lsa = NULL;
2079 free_opaque_info_per_id ((void *) oipi);
2080
2081 /* Force given lsa's age to MaxAge. */
2082 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2083
2084 if (IS_DEBUG_OSPF_EVENT)
2085 zlog_info ("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)));
2086
2087 /* This lsa will be flushed and removed eventually. */
2088 ospf_lsa_maxage (ospf, lsa);
2089
2090 out:
2091 return;
2092 }
2093
2094 /*------------------------------------------------------------------------*
2095 * Followings are control functions to block origination after restart.
2096 *------------------------------------------------------------------------*/
2097
2098 static void ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs, struct ospf_neighbor *inbr, struct ospf_lsa *lsa);
2099 static void ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi);
2100 static void ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area);
2101 static void ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top);
2102 static unsigned long ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type);
2103
2104 void
2105 ospf_opaque_adjust_lsreq (struct ospf_neighbor *nbr, list lsas)
2106 {
2107 struct ospf *top;
2108 struct ospf_area *area;
2109 struct ospf_interface *oi;
2110 listnode node1, node2;
2111 struct ospf_lsa *lsa;
2112
2113 if ((top = oi_to_top (nbr->oi)) == NULL)
2114 goto out;
2115
2116 /*
2117 * If an instance of self-originated Opaque-LSA is found in the given
2118 * LSA list, and it is not installed to LSDB yet, exclude it from the
2119 * list "nbr->ls_req". In this way, it is assured that an LSReq message,
2120 * which might be sent in the process of flooding, will not request for
2121 * the LSA to be flushed immediately; otherwise, depending on timing,
2122 * an LSUpd message will carry instances of target LSAs with MaxAge,
2123 * while other LSUpd message might carry old LSA instances (non-MaxAge).
2124 * Obviously, the latter would trigger miserable situations that repeat
2125 * installation and removal of unwanted LSAs indefinitely.
2126 */
2127 for (node1 = listhead (lsas); node1; nextnode (node1))
2128 {
2129 if ((lsa = getdata (node1)) == NULL)
2130 continue;
2131
2132 /* Filter out unwanted LSAs. */
2133 if (! IS_OPAQUE_LSA (lsa->data->type))
2134 continue;
2135 if (! IPV4_ADDR_SAME (&lsa->data->adv_router, &top->router_id))
2136 continue;
2137
2138 /*
2139 * Don't touch an LSA which has MaxAge; two possible cases.
2140 *
2141 * 1) This LSA has originally flushed by myself (received LSUpd
2142 * message's router-id is equal to my router-id), and flooded
2143 * back by an opaque-capable router.
2144 *
2145 * 2) This LSA has expired in an opaque-capable router and thus
2146 * flushed by the router.
2147 */
2148 if (IS_LSA_MAXAGE (lsa))
2149 continue;
2150
2151 /* If the LSA has installed in the LSDB, nothing to do here. */
2152 if (ospf_lsa_lookup_by_header (nbr->oi->area, lsa->data) != NULL)
2153 continue;
2154
2155 /* Ok, here we go. */
2156 switch (lsa->data->type)
2157 {
2158 case OSPF_OPAQUE_LINK_LSA:
2159 oi = nbr->oi;
2160 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2161 break;
2162 case OSPF_OPAQUE_AREA_LSA:
2163 area = nbr->oi->area;
2164 for (node2 = listhead (area->oiflist); node2; nextnode (node2))
2165 {
2166 if ((oi = getdata (node2)) == NULL)
2167 continue;
2168 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2169 }
2170 break;
2171 case OSPF_OPAQUE_AS_LSA:
2172 for (node2 = listhead (top->oiflist); node2; nextnode (node2))
2173 {
2174 if ((oi = getdata (node2)) == NULL)
2175 continue;
2176 ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
2177 }
2178 break;
2179 default:
2180 break;
2181 }
2182 }
2183
2184 out:
2185 return;
2186 }
2187
2188 static void
2189 ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs,
2190 struct ospf_neighbor *inbr,
2191 struct ospf_lsa *lsa)
2192 {
2193 struct route_node *rn;
2194 struct ospf_neighbor *onbr;
2195 struct ospf_lsa *ls_req;
2196
2197 for (rn = route_top (nbrs); rn; rn = route_next (rn))
2198 {
2199 if ((onbr = rn->info) == NULL)
2200 continue;
2201 if (onbr == inbr)
2202 continue;
2203 if ((ls_req = ospf_ls_request_lookup (onbr, lsa)) == NULL)
2204 continue;
2205
2206 if (IS_DEBUG_OSPF_EVENT)
2207 zlog_info ("LSA[%s]: Exclude this entry from LSReq to send.", dump_lsa_key (lsa));
2208
2209 ospf_ls_request_delete (onbr, ls_req);
2210 /* ospf_check_nbr_loading (onbr);*//* XXX */
2211 }
2212
2213 return;
2214 }
2215
2216 void
2217 ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr, list lsas)
2218 {
2219 struct ospf *top;
2220 listnode node, next;
2221 struct ospf_lsa *lsa;
2222 u_char before;
2223
2224 if ((top = oi_to_top (nbr->oi)) == NULL)
2225 goto out;
2226
2227 before = IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque);
2228
2229 for (node = listhead (lsas); node; node = next)
2230 {
2231 next = node->next;
2232
2233 if ((lsa = getdata (node)) == NULL)
2234 continue;
2235
2236 listnode_delete (lsas, lsa);
2237
2238 /*
2239 * Since these LSA entries are not yet installed into corresponding
2240 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2241 */
2242 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2243 switch (lsa->data->type)
2244 {
2245 case OSPF_OPAQUE_LINK_LSA:
2246 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
2247 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2248 break;
2249 case OSPF_OPAQUE_AREA_LSA:
2250 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
2251 ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
2252 break;
2253 case OSPF_OPAQUE_AS_LSA:
2254 SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
2255 ospf_flood_through_as (top, NULL/*inbr*/, lsa);
2256 break;
2257 default:
2258 zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
2259 goto out;
2260 }
2261
2262 ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */
2263 }
2264
2265 if (before == 0 && IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2266 {
2267 if (IS_DEBUG_OSPF_EVENT)
2268 zlog_info ("Block Opaque-LSA origination: OFF -> ON");
2269 }
2270
2271 out:
2272 return;
2273 }
2274
2275 void
2276 ospf_opaque_ls_ack_received (struct ospf_neighbor *nbr, list acks)
2277 {
2278 struct ospf *top;
2279 listnode node;
2280 struct ospf_lsa *lsa;
2281 char type9_lsa_rcv = 0, type10_lsa_rcv = 0, type11_lsa_rcv = 0;
2282
2283 if ((top = oi_to_top (nbr->oi)) == NULL)
2284 goto out;
2285
2286 for (node = listhead (acks); node; nextnode (node))
2287 {
2288 if ((lsa = getdata (node)) == NULL)
2289 continue;
2290
2291 switch (lsa->data->type)
2292 {
2293 case OSPF_OPAQUE_LINK_LSA:
2294 type9_lsa_rcv = 1;
2295 /* Callback function... */
2296 break;
2297 case OSPF_OPAQUE_AREA_LSA:
2298 type10_lsa_rcv = 1;
2299 /* Callback function... */
2300 break;
2301 case OSPF_OPAQUE_AS_LSA:
2302 type11_lsa_rcv = 1;
2303 /* Callback function... */
2304 break;
2305 default:
2306 zlog_warn ("ospf_opaque_ls_ack_received: Unexpected LSA-type(%u)", lsa->data->type);
2307 goto out;
2308 }
2309 }
2310
2311 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2312 {
2313 int delay;
2314 struct ospf_interface *oi;
2315
2316 if (type9_lsa_rcv
2317 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT))
2318 ospf_opaque_type9_lsa_rxmt_nbr_check (nbr->oi);
2319
2320 if (type10_lsa_rcv
2321 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT))
2322 ospf_opaque_type10_lsa_rxmt_nbr_check (nbr->oi->area);
2323
2324 if (type11_lsa_rcv
2325 && CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT))
2326 ospf_opaque_type11_lsa_rxmt_nbr_check (top);
2327
2328 if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
2329 goto out; /* Blocking still in progress. */
2330
2331 if (IS_DEBUG_OSPF_EVENT)
2332 zlog_info ("Block Opaque-LSA origination: ON -> OFF");
2333
2334 if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
2335 goto out; /* Opaque capability condition must have changed. */
2336
2337 /* Ok, let's start origination of Opaque-LSAs. */
2338 delay = OSPF_MIN_LS_INTERVAL;
2339 for (node = listhead (top->oiflist); node; nextnode (node))
2340 {
2341 if ((oi = getdata (node)) == NULL)
2342 continue;
2343
2344 if (! ospf_if_is_enable (oi)
2345 || ospf_nbr_count_opaque_capable (oi) == 0)
2346 continue;
2347
2348 ospf_opaque_lsa_originate_schedule (oi, &delay);
2349 }
2350 }
2351
2352 out:
2353 return;
2354 }
2355
2356 static void
2357 ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi)
2358 {
2359 unsigned long n;
2360
2361 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_LINK_LSA);
2362 if (n == 0)
2363 {
2364 if (IS_DEBUG_OSPF_EVENT)
2365 zlog_info ("Self-originated type-9 Opaque-LSAs: OI(%s): Flush completed", IF_NAME (oi));
2366
2367 UNSET_FLAG (oi->area->ospf->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
2368 }
2369 return;
2370 }
2371
2372 static void
2373 ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area)
2374 {
2375 listnode node;
2376 struct ospf_interface *oi;
2377 unsigned long n = 0;
2378
2379 for (node = listhead (area->oiflist); node; nextnode (node))
2380 {
2381 if ((oi = getdata (node)) == NULL)
2382 continue;
2383
2384 if (area->area_id.s_addr != OSPF_AREA_BACKBONE
2385 && oi->type == OSPF_IFTYPE_VIRTUALLINK)
2386 continue;
2387
2388 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AREA_LSA);
2389 if (n > 0)
2390 break;
2391 }
2392
2393 if (n == 0)
2394 {
2395 if (IS_DEBUG_OSPF_EVENT)
2396 zlog_info ("Self-originated type-10 Opaque-LSAs: AREA(%s): Flush completed", inet_ntoa (area->area_id));
2397
2398 UNSET_FLAG (area->ospf->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
2399 }
2400
2401 return;
2402 }
2403
2404 static void
2405 ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top)
2406 {
2407 listnode node;
2408 struct ospf_interface *oi;
2409 unsigned long n = 0;
2410
2411 for (node = listhead (top->oiflist); node; nextnode (node))
2412 {
2413 if ((oi = getdata (node)) == NULL)
2414 continue;
2415
2416 switch (oi->type)
2417 {
2418 case OSPF_IFTYPE_VIRTUALLINK:
2419 continue;
2420 default:
2421 break;
2422 }
2423
2424 n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AS_LSA);
2425 if (n > 0)
2426 goto out;
2427 }
2428
2429 if (n == 0)
2430 {
2431 if (IS_DEBUG_OSPF_EVENT)
2432 zlog_info ("Self-originated type-11 Opaque-LSAs: Flush completed");
2433
2434 UNSET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
2435 }
2436
2437 out:
2438 return;
2439 }
2440
2441 static unsigned long
2442 ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type)
2443 {
2444 struct route_node *rn;
2445 struct ospf_neighbor *nbr;
2446 struct ospf *top;
2447 unsigned long n = 0;
2448
2449 for (rn = route_top (nbrs); rn; rn = route_next (rn))
2450 {
2451 if ((nbr = rn->info) == NULL)
2452 continue;
2453 if ((top = oi_to_top (nbr->oi)) == NULL)
2454 continue;
2455 if (IPV4_ADDR_SAME (&nbr->router_id, &top->router_id))
2456 continue;
2457 n += ospf_ls_retransmit_count_self (nbr, lsa_type);
2458 }
2459
2460 return n;
2461 }
2462
2463 /*------------------------------------------------------------------------*
2464 * Followings are util functions; probably be used by Opaque-LSAs only...
2465 *------------------------------------------------------------------------*/
2466
2467 void
2468 htonf (float *src, float *dst)
2469 {
2470 u_int32_t lu1, lu2;
2471
2472 memcpy (&lu1, src, sizeof (u_int32_t));
2473 lu2 = htonl (lu1);
2474 memcpy (dst, &lu2, sizeof (u_int32_t));
2475 return;
2476 }
2477
2478 void
2479 ntohf (float *src, float *dst)
2480 {
2481 u_int32_t lu1, lu2;
2482
2483 memcpy (&lu1, src, sizeof (u_int32_t));
2484 lu2 = ntohl (lu1);
2485 memcpy (dst, &lu2, sizeof (u_int32_t));
2486 return;
2487 }
2488
2489 struct ospf *
2490 oi_to_top (struct ospf_interface *oi)
2491 {
2492 struct ospf *top = NULL;
2493 struct ospf_area *area;
2494
2495 if (oi == NULL || (area = oi->area) == NULL || (top = area->ospf) == NULL)
2496 zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");
2497
2498 return top;
2499 }
2500
2501 #endif /* HAVE_OPAQUE_LSA */