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