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