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