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