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