Line data Source code
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 12 : DEFINE_MTYPE_STATIC(OSPFD, OSPF_OPAQUE_FUNCTAB, "OSPF opaque function table");
60 12 : DEFINE_MTYPE_STATIC(OSPFD, OPAQUE_INFO_PER_TYPE, "OSPF opaque per-type info");
61 12 : 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 4 : void ospf_opaque_init(void)
83 : {
84 4 : ospf_opaque_register_vty();
85 4 : ospf_opaque_funclist_init();
86 :
87 4 : if (ospf_mpls_te_init() != 0)
88 0 : exit(1);
89 :
90 : /* Segment Routing init */
91 4 : if (ospf_sr_init() != 0)
92 0 : exit(1);
93 :
94 4 : if (ospf_router_info_init() != 0)
95 0 : exit(1);
96 :
97 4 : if (ospf_ext_init() != 0)
98 0 : exit(1);
99 :
100 : #ifdef SUPPORT_OSPF_API
101 4 : if ((ospf_apiserver_enable) && (ospf_apiserver_init() != 0))
102 0 : exit(1);
103 : #endif /* SUPPORT_OSPF_API */
104 :
105 4 : return;
106 : }
107 :
108 0 : void ospf_opaque_term(void)
109 : {
110 0 : ospf_mpls_te_term();
111 :
112 0 : ospf_router_info_term();
113 :
114 0 : ospf_ext_term();
115 :
116 0 : ospf_sr_term();
117 :
118 : #ifdef SUPPORT_OSPF_API
119 0 : ospf_apiserver_term();
120 : #endif /* SUPPORT_OSPF_API */
121 :
122 0 : ospf_opaque_funclist_term();
123 0 : return;
124 : }
125 :
126 4 : void ospf_opaque_finish(void)
127 : {
128 4 : ospf_mpls_te_finish();
129 :
130 4 : ospf_router_info_finish();
131 :
132 4 : ospf_ext_finish();
133 :
134 4 : ospf_sr_finish();
135 4 : }
136 :
137 18 : int ospf_opaque_type9_lsa_init(struct ospf_interface *oi)
138 : {
139 18 : if (oi->opaque_lsa_self != NULL)
140 0 : list_delete(&oi->opaque_lsa_self);
141 :
142 18 : oi->opaque_lsa_self = list_new();
143 18 : oi->opaque_lsa_self->del = free_opaque_info_per_type_del;
144 18 : oi->t_opaque_lsa_self = NULL;
145 18 : return 0;
146 : }
147 :
148 18 : void ospf_opaque_type9_lsa_term(struct ospf_interface *oi)
149 : {
150 18 : THREAD_OFF(oi->t_opaque_lsa_self);
151 18 : if (oi->opaque_lsa_self != NULL)
152 18 : list_delete(&oi->opaque_lsa_self);
153 18 : oi->opaque_lsa_self = NULL;
154 18 : return;
155 : }
156 :
157 11 : int ospf_opaque_type10_lsa_init(struct ospf_area *area)
158 : {
159 11 : if (area->opaque_lsa_self != NULL)
160 0 : list_delete(&area->opaque_lsa_self);
161 :
162 11 : area->opaque_lsa_self = list_new();
163 11 : area->opaque_lsa_self->del = free_opaque_info_per_type_del;
164 11 : area->t_opaque_lsa_self = NULL;
165 :
166 : #ifdef MONITOR_LSDB_CHANGE
167 11 : area->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
168 11 : area->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
169 : #endif /* MONITOR_LSDB_CHANGE */
170 11 : return 0;
171 : }
172 :
173 11 : void ospf_opaque_type10_lsa_term(struct ospf_area *area)
174 : {
175 : #ifdef MONITOR_LSDB_CHANGE
176 11 : area->lsdb->new_lsa_hook = area->lsdb->del_lsa_hook = NULL;
177 : #endif /* MONITOR_LSDB_CHANGE */
178 :
179 11 : THREAD_OFF(area->t_opaque_lsa_self);
180 11 : if (area->opaque_lsa_self != NULL)
181 11 : list_delete(&area->opaque_lsa_self);
182 11 : return;
183 : }
184 :
185 4 : int ospf_opaque_type11_lsa_init(struct ospf *top)
186 : {
187 4 : if (top->opaque_lsa_self != NULL)
188 0 : list_delete(&top->opaque_lsa_self);
189 :
190 4 : top->opaque_lsa_self = list_new();
191 4 : top->opaque_lsa_self->del = free_opaque_info_per_type_del;
192 4 : top->t_opaque_lsa_self = NULL;
193 :
194 : #ifdef MONITOR_LSDB_CHANGE
195 4 : top->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
196 4 : top->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
197 : #endif /* MONITOR_LSDB_CHANGE */
198 4 : return 0;
199 : }
200 :
201 4 : void ospf_opaque_type11_lsa_term(struct ospf *top)
202 : {
203 : #ifdef MONITOR_LSDB_CHANGE
204 4 : top->lsdb->new_lsa_hook = top->lsdb->del_lsa_hook = NULL;
205 : #endif /* MONITOR_LSDB_CHANGE */
206 :
207 4 : THREAD_OFF(top->t_opaque_lsa_self);
208 4 : if (top->opaque_lsa_self != NULL)
209 4 : list_delete(&top->opaque_lsa_self);
210 4 : return;
211 : }
212 :
213 0 : static const char *ospf_opaque_type_name(uint8_t opaque_type)
214 : {
215 0 : const char *name = "Unknown";
216 :
217 0 : switch (opaque_type) {
218 : case OPAQUE_TYPE_WILDCARD: /* This is a special assignment! */
219 : name = "Wildcard";
220 : break;
221 0 : case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA:
222 0 : name = "Traffic Engineering LSA";
223 0 : break;
224 0 : case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC:
225 0 : name = "Sycamore optical topology description";
226 0 : break;
227 0 : case OPAQUE_TYPE_GRACE_LSA:
228 0 : name = "Grace-LSA";
229 0 : break;
230 0 : case OPAQUE_TYPE_INTER_AS_LSA:
231 0 : name = "Inter-AS TE-v2 LSA";
232 0 : break;
233 0 : case OPAQUE_TYPE_ROUTER_INFORMATION_LSA:
234 0 : name = "Router Information LSA";
235 0 : break;
236 0 : case OPAQUE_TYPE_EXTENDED_PREFIX_LSA:
237 0 : name = "Extended Prefix Opaque LSA";
238 0 : break;
239 0 : case OPAQUE_TYPE_EXTENDED_LINK_LSA:
240 0 : name = "Extended Link Opaque LSA";
241 0 : break;
242 0 : default:
243 0 : if (OPAQUE_TYPE_RANGE_UNASSIGNED(opaque_type))
244 : name = "Unassigned";
245 : else {
246 0 : 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 0 : if (OPAQUE_TYPE_RANGE_RESERVED(bigger_range))
252 0 : name = "Private/Experimental";
253 : }
254 : break;
255 : }
256 0 : 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 0 : static void ospf_opaque_del_functab(void *val)
294 : {
295 0 : XFREE(MTYPE_OSPF_OPAQUE_FUNCTAB, val);
296 0 : return;
297 : }
298 :
299 4 : static void ospf_opaque_funclist_init(void)
300 : {
301 4 : struct list *funclist;
302 :
303 4 : funclist = ospf_opaque_wildcard_funclist = list_new();
304 4 : funclist->del = ospf_opaque_del_functab;
305 :
306 4 : funclist = ospf_opaque_type9_funclist = list_new();
307 4 : funclist->del = ospf_opaque_del_functab;
308 :
309 4 : funclist = ospf_opaque_type10_funclist = list_new();
310 4 : funclist->del = ospf_opaque_del_functab;
311 :
312 4 : funclist = ospf_opaque_type11_funclist = list_new();
313 4 : funclist->del = ospf_opaque_del_functab;
314 4 : return;
315 : }
316 :
317 0 : static void ospf_opaque_funclist_term(void)
318 : {
319 0 : struct list *funclist;
320 :
321 0 : funclist = ospf_opaque_wildcard_funclist;
322 0 : list_delete(&funclist);
323 :
324 0 : funclist = ospf_opaque_type9_funclist;
325 0 : list_delete(&funclist);
326 :
327 0 : funclist = ospf_opaque_type10_funclist;
328 0 : list_delete(&funclist);
329 :
330 0 : funclist = ospf_opaque_type11_funclist;
331 0 : list_delete(&funclist);
332 0 : return;
333 : }
334 :
335 24 : static struct list *ospf_get_opaque_funclist(uint8_t lsa_type)
336 : {
337 24 : struct list *funclist = NULL;
338 :
339 24 : switch (lsa_type) {
340 0 : 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 0 : funclist = ospf_opaque_wildcard_funclist;
350 0 : break;
351 4 : case OSPF_OPAQUE_LINK_LSA:
352 4 : funclist = ospf_opaque_type9_funclist;
353 4 : break;
354 16 : case OSPF_OPAQUE_AREA_LSA:
355 16 : funclist = ospf_opaque_type10_funclist;
356 16 : break;
357 4 : case OSPF_OPAQUE_AS_LSA:
358 4 : funclist = ospf_opaque_type11_funclist;
359 4 : break;
360 0 : default:
361 0 : flog_warn(EC_OSPF_LSA_UNEXPECTED, "%s: Unexpected LSA-type(%u)",
362 : __func__, lsa_type);
363 0 : break;
364 : }
365 24 : return funclist;
366 : }
367 :
368 : /* XXX: such a huge argument list can /not/ be healthy... */
369 24 : 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 24 : struct list *funclist;
386 24 : struct ospf_opaque_functab *new;
387 :
388 24 : if ((funclist = ospf_get_opaque_funclist(lsa_type)) == NULL)
389 : return -1;
390 :
391 24 : struct listnode *node, *nnode;
392 24 : struct ospf_opaque_functab *functab;
393 :
394 48 : for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab))
395 24 : if (functab->opaque_type == opaque_type) {
396 0 : flog_warn(
397 : EC_OSPF_LSA,
398 : "%s: Duplicated entry?: lsa_type(%u), opaque_type(%u)",
399 : __func__, lsa_type, opaque_type);
400 0 : return -1;
401 : }
402 :
403 24 : new = XCALLOC(MTYPE_OSPF_OPAQUE_FUNCTAB,
404 : sizeof(struct ospf_opaque_functab));
405 :
406 24 : new->opaque_type = opaque_type;
407 24 : new->oipt = NULL;
408 24 : new->new_if_hook = new_if_hook;
409 24 : new->del_if_hook = del_if_hook;
410 24 : new->ism_change_hook = ism_change_hook;
411 24 : new->nsm_change_hook = nsm_change_hook;
412 24 : new->config_write_router = config_write_router;
413 24 : new->config_write_if = config_write_if;
414 24 : new->config_write_debug = config_write_debug;
415 24 : new->show_opaque_info = show_opaque_info;
416 24 : new->lsa_originator = lsa_originator;
417 24 : new->lsa_refresher = lsa_refresher;
418 24 : new->new_lsa_hook = new_lsa_hook;
419 24 : new->del_lsa_hook = del_lsa_hook;
420 :
421 24 : listnode_add(funclist, new);
422 :
423 24 : return 0;
424 : }
425 :
426 0 : void ospf_delete_opaque_functab(uint8_t lsa_type, uint8_t opaque_type)
427 : {
428 0 : struct list *funclist;
429 0 : struct listnode *node, *nnode;
430 0 : struct ospf_opaque_functab *functab;
431 :
432 0 : if ((funclist = ospf_get_opaque_funclist(lsa_type)) != NULL)
433 0 : for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab)) {
434 0 : if (functab->opaque_type == opaque_type) {
435 : /* Cleanup internal control information, if it
436 : * still remains. */
437 0 : if (functab->oipt != NULL)
438 0 : free_opaque_info_per_type(functab->oipt,
439 : true);
440 : /* Dequeue listnode entry from the list. */
441 0 : listnode_delete(funclist, functab);
442 :
443 0 : XFREE(MTYPE_OSPF_OPAQUE_FUNCTAB, functab);
444 0 : break;
445 : }
446 : }
447 :
448 0 : return;
449 : }
450 :
451 : static struct ospf_opaque_functab *
452 0 : ospf_opaque_functab_lookup(struct ospf_lsa *lsa)
453 : {
454 0 : struct list *funclist;
455 0 : struct listnode *node;
456 0 : struct ospf_opaque_functab *functab;
457 0 : uint8_t key = GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr));
458 :
459 0 : if ((funclist = ospf_get_opaque_funclist(lsa->data->type)) != NULL)
460 0 : for (ALL_LIST_ELEMENTS_RO(funclist, node, functab))
461 0 : if (functab->opaque_type == key)
462 0 : 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 0 : register_opaque_info_per_type(struct ospf_opaque_functab *functab,
539 : struct ospf_lsa *new)
540 : {
541 0 : struct ospf *top;
542 0 : struct opaque_info_per_type *oipt;
543 :
544 0 : oipt = XCALLOC(MTYPE_OPAQUE_INFO_PER_TYPE,
545 : sizeof(struct opaque_info_per_type));
546 :
547 0 : switch (new->data->type) {
548 0 : case OSPF_OPAQUE_LINK_LSA:
549 0 : oipt->owner = new->oi;
550 0 : listnode_add(new->oi->opaque_lsa_self, oipt);
551 0 : break;
552 0 : case OSPF_OPAQUE_AREA_LSA:
553 0 : oipt->owner = new->area;
554 0 : listnode_add(new->area->opaque_lsa_self, oipt);
555 0 : break;
556 0 : case OSPF_OPAQUE_AS_LSA:
557 0 : top = ospf_lookup_by_vrf_id(new->vrf_id);
558 0 : if (new->area != NULL && (top = new->area->ospf) == NULL) {
559 0 : free_opaque_info_per_type(oipt, true);
560 0 : oipt = NULL;
561 0 : goto out; /* This case may not exist. */
562 : }
563 0 : oipt->owner = top;
564 0 : listnode_add(top->opaque_lsa_self, oipt);
565 0 : break;
566 0 : default:
567 0 : flog_warn(EC_OSPF_LSA_UNEXPECTED, "%s: Unexpected LSA-type(%u)",
568 : __func__, new->data->type);
569 0 : free_opaque_info_per_type(oipt, true);
570 0 : oipt = NULL;
571 0 : goto out; /* This case may not exist. */
572 : }
573 :
574 0 : oipt->lsa_type = new->data->type;
575 0 : oipt->opaque_type = GET_OPAQUE_TYPE(ntohl(new->data->id.s_addr));
576 0 : oipt->status = PROC_NORMAL;
577 0 : oipt->functab = functab;
578 0 : functab->oipt = oipt;
579 0 : oipt->id_list = list_new();
580 0 : oipt->id_list->del = free_opaque_info_per_id;
581 :
582 0 : out:
583 0 : return oipt;
584 : }
585 :
586 0 : static void free_opaque_info_per_type(struct opaque_info_per_type *oipt,
587 : bool cleanup_owner)
588 : {
589 0 : struct opaque_info_per_id *oipi;
590 0 : struct ospf_lsa *lsa;
591 0 : struct listnode *node, *nnode;
592 0 : struct list *l;
593 :
594 : /* Control information per opaque-id may still exist. */
595 0 : for (ALL_LIST_ELEMENTS(oipt->id_list, node, nnode, oipi)) {
596 0 : if ((lsa = oipi->lsa) == NULL)
597 0 : continue;
598 0 : if (IS_LSA_MAXAGE(lsa))
599 0 : continue;
600 0 : ospf_opaque_lsa_flush_schedule(lsa);
601 : }
602 :
603 0 : THREAD_OFF(oipt->t_opaque_lsa_self);
604 0 : list_delete(&oipt->id_list);
605 0 : if (cleanup_owner) {
606 : /* Remove from its owner's self-originated LSA list. */
607 0 : switch (oipt->lsa_type) {
608 0 : case OSPF_OPAQUE_LINK_LSA:
609 0 : l = ((struct ospf_interface *)oipt->owner)
610 : ->opaque_lsa_self;
611 0 : break;
612 0 : case OSPF_OPAQUE_AREA_LSA:
613 0 : l = ((struct ospf_area *)oipt->owner)->opaque_lsa_self;
614 0 : break;
615 0 : case OSPF_OPAQUE_AS_LSA:
616 0 : l = ((struct ospf *)oipt->owner)->opaque_lsa_self;
617 0 : break;
618 0 : default:
619 0 : flog_warn(
620 : EC_OSPF_LSA_UNEXPECTED,
621 : "free_opaque_info_owner: Unexpected LSA-type(%u)",
622 : oipt->lsa_type);
623 0 : return;
624 : }
625 0 : listnode_delete(l, oipt);
626 : }
627 0 : XFREE(MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
628 0 : return;
629 : }
630 :
631 0 : static void free_opaque_info_per_type_del(void *val)
632 : {
633 0 : free_opaque_info_per_type((struct opaque_info_per_type *)val, false);
634 0 : }
635 :
636 : static struct opaque_info_per_type *
637 0 : lookup_opaque_info_by_type(struct ospf_lsa *lsa)
638 : {
639 0 : struct ospf *top;
640 0 : struct ospf_area *area;
641 0 : struct ospf_interface *oi;
642 0 : struct list *listtop = NULL;
643 0 : struct listnode *node, *nnode;
644 0 : struct opaque_info_per_type *oipt = NULL;
645 0 : uint8_t key = GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr));
646 :
647 0 : switch (lsa->data->type) {
648 0 : case OSPF_OPAQUE_LINK_LSA:
649 0 : if ((oi = lsa->oi) != NULL)
650 0 : listtop = oi->opaque_lsa_self;
651 : else
652 0 : flog_warn(
653 : EC_OSPF_LSA,
654 : "Type-9 Opaque-LSA: Reference to OI is missing?");
655 : break;
656 0 : case OSPF_OPAQUE_AREA_LSA:
657 0 : if ((area = lsa->area) != NULL)
658 0 : listtop = area->opaque_lsa_self;
659 : else
660 0 : flog_warn(
661 : EC_OSPF_LSA,
662 : "Type-10 Opaque-LSA: Reference to AREA is missing?");
663 : break;
664 0 : case OSPF_OPAQUE_AS_LSA:
665 0 : top = ospf_lookup_by_vrf_id(lsa->vrf_id);
666 0 : if ((area = lsa->area) != NULL && (top = area->ospf) == NULL) {
667 0 : flog_warn(
668 : EC_OSPF_LSA,
669 : "Type-11 Opaque-LSA: Reference to OSPF is missing?");
670 0 : break; /* Unlikely to happen. */
671 : }
672 0 : listtop = top->opaque_lsa_self;
673 0 : break;
674 0 : default:
675 0 : flog_warn(EC_OSPF_LSA_UNEXPECTED, "%s: Unexpected LSA-type(%u)",
676 : __func__, lsa->data->type);
677 0 : break;
678 : }
679 :
680 0 : if (listtop != NULL)
681 0 : for (ALL_LIST_ELEMENTS(listtop, node, nnode, oipt))
682 0 : if (oipt->opaque_type == key)
683 0 : return oipt;
684 :
685 : return NULL;
686 : }
687 :
688 : static struct opaque_info_per_id *
689 0 : register_opaque_info_per_id(struct opaque_info_per_type *oipt,
690 : struct ospf_lsa *new)
691 : {
692 0 : struct opaque_info_per_id *oipi;
693 :
694 0 : oipi = XCALLOC(MTYPE_OPAQUE_INFO_PER_ID,
695 : sizeof(struct opaque_info_per_id));
696 :
697 0 : oipi->opaque_id = GET_OPAQUE_ID(ntohl(new->data->id.s_addr));
698 0 : oipi->opqctl_type = oipt;
699 0 : oipi->lsa = ospf_lsa_lock(new);
700 :
701 0 : listnode_add(oipt->id_list, oipi);
702 :
703 0 : return oipi;
704 : }
705 :
706 0 : static void free_opaque_info_per_id(void *val)
707 : {
708 0 : struct opaque_info_per_id *oipi = (struct opaque_info_per_id *)val;
709 :
710 0 : THREAD_OFF(oipi->t_opaque_lsa_self);
711 0 : if (oipi->lsa != NULL)
712 0 : ospf_lsa_unlock(&oipi->lsa);
713 0 : XFREE(MTYPE_OPAQUE_INFO_PER_ID, oipi);
714 0 : return;
715 : }
716 :
717 : static struct opaque_info_per_id *
718 0 : lookup_opaque_info_by_id(struct opaque_info_per_type *oipt,
719 : struct ospf_lsa *lsa)
720 : {
721 0 : struct listnode *node, *nnode;
722 0 : struct opaque_info_per_id *oipi;
723 0 : uint32_t key = GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr));
724 :
725 0 : for (ALL_LIST_ELEMENTS(oipt->id_list, node, nnode, oipi))
726 0 : if (oipi->opaque_id == key)
727 0 : return oipi;
728 :
729 : return NULL;
730 : }
731 :
732 0 : static struct opaque_info_per_id *register_opaque_lsa(struct ospf_lsa *new)
733 : {
734 0 : struct ospf_opaque_functab *functab;
735 0 : struct opaque_info_per_type *oipt;
736 0 : struct opaque_info_per_id *oipi = NULL;
737 :
738 0 : if ((functab = ospf_opaque_functab_lookup(new)) == NULL)
739 0 : goto out;
740 :
741 0 : if ((oipt = lookup_opaque_info_by_type(new)) == NULL
742 0 : && (oipt = register_opaque_info_per_type(functab, new)) == NULL)
743 0 : goto out;
744 :
745 0 : if ((oipi = register_opaque_info_per_id(oipt, new)) == NULL)
746 0 : goto out;
747 :
748 0 : out:
749 0 : return oipi;
750 : }
751 :
752 0 : int ospf_opaque_is_owned(struct ospf_lsa *lsa)
753 : {
754 0 : struct opaque_info_per_type *oipt = lookup_opaque_info_by_type(lsa);
755 :
756 0 : 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 0 : DEFUN (capability_opaque,
764 : capability_opaque_cmd,
765 : "capability opaque",
766 : "Enable specific OSPF feature\n"
767 : "Opaque LSA\n")
768 : {
769 0 : VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
770 :
771 : /* Turn on the "master switch" of opaque-lsa capability. */
772 0 : if (!CHECK_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE)) {
773 0 : if (IS_DEBUG_OSPF_EVENT)
774 0 : zlog_debug("Opaque capability: OFF -> ON");
775 :
776 0 : SET_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE);
777 0 : ospf_renegotiate_optional_capabilities(ospf);
778 : }
779 : return CMD_SUCCESS;
780 : }
781 :
782 0 : 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 0 : return capability_opaque(self, vty, argc, argv);
789 : }
790 :
791 0 : 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 0 : VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
799 :
800 : /* Turn off the "master switch" of opaque-lsa capability. */
801 0 : if (CHECK_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE)) {
802 0 : if (IS_DEBUG_OSPF_EVENT)
803 0 : zlog_debug("Opaque capability: ON -> OFF");
804 :
805 0 : UNSET_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE);
806 0 : ospf_renegotiate_optional_capabilities(ospf);
807 : }
808 : return CMD_SUCCESS;
809 : }
810 :
811 0 : 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 0 : return no_capability_opaque(self, vty, argc, argv);
819 : }
820 :
821 4 : static void ospf_opaque_register_vty(void)
822 : {
823 4 : install_element(OSPF_NODE, &capability_opaque_cmd);
824 4 : install_element(OSPF_NODE, &no_capability_opaque_cmd);
825 4 : install_element(OSPF_NODE, &ospf_opaque_cmd);
826 4 : install_element(OSPF_NODE, &no_ospf_opaque_cmd);
827 4 : return;
828 : }
829 :
830 : /*------------------------------------------------------------------------*
831 : * Following are collection of user-registered function callers.
832 : *------------------------------------------------------------------------*/
833 :
834 52 : static int opaque_lsa_new_if_callback(struct list *funclist,
835 : struct interface *ifp)
836 : {
837 52 : struct listnode *node, *nnode;
838 52 : struct ospf_opaque_functab *functab;
839 52 : int rc = -1;
840 :
841 182 : for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab))
842 78 : if (functab->new_if_hook != NULL)
843 26 : if ((*functab->new_if_hook)(ifp) != 0)
844 0 : goto out;
845 : rc = 0;
846 52 : out:
847 52 : return rc;
848 : }
849 :
850 0 : static int opaque_lsa_del_if_callback(struct list *funclist,
851 : struct interface *ifp)
852 : {
853 0 : struct listnode *node, *nnode;
854 0 : struct ospf_opaque_functab *functab;
855 0 : int rc = -1;
856 :
857 0 : for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab))
858 0 : if (functab->del_if_hook != NULL)
859 0 : if ((*functab->del_if_hook)(ifp) != 0)
860 0 : goto out;
861 : rc = 0;
862 0 : out:
863 0 : return rc;
864 : }
865 :
866 204 : static void opaque_lsa_ism_change_callback(struct list *funclist,
867 : struct ospf_interface *oi,
868 : int old_status)
869 : {
870 204 : struct listnode *node, *nnode;
871 204 : struct ospf_opaque_functab *functab;
872 :
873 714 : for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab))
874 306 : if (functab->ism_change_hook != NULL)
875 102 : (*functab->ism_change_hook)(oi, old_status);
876 :
877 204 : return;
878 : }
879 :
880 208 : static void opaque_lsa_nsm_change_callback(struct list *funclist,
881 : struct ospf_neighbor *nbr,
882 : int old_status)
883 : {
884 208 : struct listnode *node, *nnode;
885 208 : struct ospf_opaque_functab *functab;
886 :
887 728 : for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab))
888 312 : if (functab->nsm_change_hook != NULL)
889 104 : (*functab->nsm_change_hook)(nbr, old_status);
890 208 : return;
891 : }
892 :
893 0 : static void opaque_lsa_config_write_router_callback(struct list *funclist,
894 : struct vty *vty)
895 : {
896 0 : struct listnode *node, *nnode;
897 0 : struct ospf_opaque_functab *functab;
898 :
899 0 : for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab))
900 0 : if (functab->config_write_router != NULL)
901 0 : (*functab->config_write_router)(vty);
902 0 : return;
903 : }
904 :
905 0 : static void opaque_lsa_config_write_if_callback(struct list *funclist,
906 : struct vty *vty,
907 : struct interface *ifp)
908 : {
909 0 : struct listnode *node, *nnode;
910 0 : struct ospf_opaque_functab *functab;
911 :
912 0 : for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab))
913 0 : if (functab->config_write_if != NULL)
914 0 : (*functab->config_write_if)(vty, ifp);
915 0 : return;
916 : }
917 :
918 0 : static void opaque_lsa_config_write_debug_callback(struct list *funclist,
919 : struct vty *vty)
920 : {
921 0 : struct listnode *node, *nnode;
922 0 : struct ospf_opaque_functab *functab;
923 :
924 0 : for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab))
925 0 : if (functab->config_write_debug != NULL)
926 0 : (*functab->config_write_debug)(vty);
927 0 : return;
928 : }
929 :
930 0 : static int opaque_lsa_originate_callback(struct list *funclist,
931 : void *lsa_type_dependent)
932 : {
933 0 : struct listnode *node, *nnode;
934 0 : struct ospf_opaque_functab *functab;
935 0 : int rc = -1;
936 :
937 0 : for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab))
938 0 : if (functab->lsa_originator != NULL)
939 0 : if ((*functab->lsa_originator)(lsa_type_dependent) != 0)
940 0 : goto out;
941 : rc = 0;
942 0 : out:
943 0 : return rc;
944 : }
945 :
946 644 : static int new_lsa_callback(struct list *funclist, struct ospf_lsa *lsa)
947 : {
948 644 : struct listnode *node, *nnode;
949 644 : struct ospf_opaque_functab *functab;
950 644 : int rc = -1;
951 :
952 : /* This function handles ALL types of LSAs, not only opaque ones. */
953 2254 : for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab))
954 966 : if (functab->new_lsa_hook != NULL)
955 483 : if ((*functab->new_lsa_hook)(lsa) != 0)
956 0 : goto out;
957 : rc = 0;
958 644 : out:
959 644 : return rc;
960 : }
961 :
962 456 : static int del_lsa_callback(struct list *funclist, struct ospf_lsa *lsa)
963 : {
964 456 : struct listnode *node, *nnode;
965 456 : struct ospf_opaque_functab *functab;
966 456 : int rc = -1;
967 :
968 : /* This function handles ALL types of LSAs, not only opaque ones. */
969 1596 : for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab))
970 684 : if (functab->del_lsa_hook != NULL)
971 114 : if ((*functab->del_lsa_hook)(lsa) != 0)
972 0 : goto out;
973 : rc = 0;
974 456 : out:
975 456 : return rc;
976 : }
977 :
978 : /*------------------------------------------------------------------------*
979 : * Following are glue functions to call Opaque-LSA specific processing.
980 : *------------------------------------------------------------------------*/
981 :
982 13 : int ospf_opaque_new_if(struct interface *ifp)
983 : {
984 13 : struct list *funclist;
985 13 : int rc = -1;
986 :
987 13 : funclist = ospf_opaque_wildcard_funclist;
988 13 : if (opaque_lsa_new_if_callback(funclist, ifp) != 0)
989 0 : goto out;
990 :
991 13 : funclist = ospf_opaque_type9_funclist;
992 13 : if (opaque_lsa_new_if_callback(funclist, ifp) != 0)
993 0 : goto out;
994 :
995 13 : funclist = ospf_opaque_type10_funclist;
996 13 : if (opaque_lsa_new_if_callback(funclist, ifp) != 0)
997 0 : goto out;
998 :
999 13 : funclist = ospf_opaque_type11_funclist;
1000 13 : if (opaque_lsa_new_if_callback(funclist, ifp) != 0)
1001 0 : goto out;
1002 :
1003 : rc = 0;
1004 13 : out:
1005 13 : return rc;
1006 : }
1007 :
1008 0 : int ospf_opaque_del_if(struct interface *ifp)
1009 : {
1010 0 : struct list *funclist;
1011 0 : int rc = -1;
1012 :
1013 0 : funclist = ospf_opaque_wildcard_funclist;
1014 0 : if (opaque_lsa_del_if_callback(funclist, ifp) != 0)
1015 0 : goto out;
1016 :
1017 0 : funclist = ospf_opaque_type9_funclist;
1018 0 : if (opaque_lsa_del_if_callback(funclist, ifp) != 0)
1019 0 : goto out;
1020 :
1021 0 : funclist = ospf_opaque_type10_funclist;
1022 0 : if (opaque_lsa_del_if_callback(funclist, ifp) != 0)
1023 0 : goto out;
1024 :
1025 0 : funclist = ospf_opaque_type11_funclist;
1026 0 : if (opaque_lsa_del_if_callback(funclist, ifp) != 0)
1027 0 : goto out;
1028 :
1029 : rc = 0;
1030 0 : out:
1031 0 : return rc;
1032 : }
1033 :
1034 51 : void ospf_opaque_ism_change(struct ospf_interface *oi, int old_status)
1035 : {
1036 51 : struct list *funclist;
1037 :
1038 51 : funclist = ospf_opaque_wildcard_funclist;
1039 51 : opaque_lsa_ism_change_callback(funclist, oi, old_status);
1040 :
1041 51 : funclist = ospf_opaque_type9_funclist;
1042 51 : opaque_lsa_ism_change_callback(funclist, oi, old_status);
1043 :
1044 51 : funclist = ospf_opaque_type10_funclist;
1045 51 : opaque_lsa_ism_change_callback(funclist, oi, old_status);
1046 :
1047 51 : funclist = ospf_opaque_type11_funclist;
1048 51 : opaque_lsa_ism_change_callback(funclist, oi, old_status);
1049 :
1050 51 : return;
1051 : }
1052 :
1053 52 : void ospf_opaque_nsm_change(struct ospf_neighbor *nbr, int old_state)
1054 : {
1055 52 : struct ospf *top;
1056 52 : struct list *funclist;
1057 :
1058 52 : if ((top = oi_to_top(nbr->oi)) == NULL)
1059 0 : goto out;
1060 :
1061 52 : if (old_state != NSM_Full && nbr->state == NSM_Full) {
1062 8 : if (CHECK_FLAG(nbr->options, OSPF_OPTION_O)) {
1063 0 : if (!CHECK_FLAG(top->opaque,
1064 : OPAQUE_OPERATION_READY_BIT)) {
1065 0 : if (IS_DEBUG_OSPF_EVENT)
1066 0 : zlog_debug(
1067 : "Opaque-LSA: Now get operational!");
1068 :
1069 0 : SET_FLAG(top->opaque,
1070 : OPAQUE_OPERATION_READY_BIT);
1071 : }
1072 :
1073 0 : 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 52 : ;
1084 : }
1085 :
1086 52 : funclist = ospf_opaque_wildcard_funclist;
1087 52 : opaque_lsa_nsm_change_callback(funclist, nbr, old_state);
1088 :
1089 52 : funclist = ospf_opaque_type9_funclist;
1090 52 : opaque_lsa_nsm_change_callback(funclist, nbr, old_state);
1091 :
1092 52 : funclist = ospf_opaque_type10_funclist;
1093 52 : opaque_lsa_nsm_change_callback(funclist, nbr, old_state);
1094 :
1095 52 : funclist = ospf_opaque_type11_funclist;
1096 52 : opaque_lsa_nsm_change_callback(funclist, nbr, old_state);
1097 :
1098 52 : out:
1099 52 : return;
1100 : }
1101 :
1102 0 : void ospf_opaque_config_write_router(struct vty *vty, struct ospf *ospf)
1103 : {
1104 0 : struct list *funclist;
1105 :
1106 0 : if (CHECK_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE))
1107 0 : vty_out(vty, " capability opaque\n");
1108 :
1109 0 : funclist = ospf_opaque_wildcard_funclist;
1110 0 : opaque_lsa_config_write_router_callback(funclist, vty);
1111 :
1112 0 : funclist = ospf_opaque_type9_funclist;
1113 0 : opaque_lsa_config_write_router_callback(funclist, vty);
1114 :
1115 0 : funclist = ospf_opaque_type10_funclist;
1116 0 : opaque_lsa_config_write_router_callback(funclist, vty);
1117 :
1118 0 : funclist = ospf_opaque_type11_funclist;
1119 0 : opaque_lsa_config_write_router_callback(funclist, vty);
1120 :
1121 0 : return;
1122 : }
1123 :
1124 0 : void ospf_opaque_config_write_if(struct vty *vty, struct interface *ifp)
1125 : {
1126 0 : struct list *funclist;
1127 :
1128 0 : funclist = ospf_opaque_wildcard_funclist;
1129 0 : opaque_lsa_config_write_if_callback(funclist, vty, ifp);
1130 :
1131 0 : funclist = ospf_opaque_type9_funclist;
1132 0 : opaque_lsa_config_write_if_callback(funclist, vty, ifp);
1133 :
1134 0 : funclist = ospf_opaque_type10_funclist;
1135 0 : opaque_lsa_config_write_if_callback(funclist, vty, ifp);
1136 :
1137 0 : funclist = ospf_opaque_type11_funclist;
1138 0 : opaque_lsa_config_write_if_callback(funclist, vty, ifp);
1139 :
1140 0 : return;
1141 : }
1142 :
1143 0 : void ospf_opaque_config_write_debug(struct vty *vty)
1144 : {
1145 0 : struct list *funclist;
1146 :
1147 0 : funclist = ospf_opaque_wildcard_funclist;
1148 0 : opaque_lsa_config_write_debug_callback(funclist, vty);
1149 :
1150 0 : funclist = ospf_opaque_type9_funclist;
1151 0 : opaque_lsa_config_write_debug_callback(funclist, vty);
1152 :
1153 0 : funclist = ospf_opaque_type10_funclist;
1154 0 : opaque_lsa_config_write_debug_callback(funclist, vty);
1155 :
1156 0 : funclist = ospf_opaque_type11_funclist;
1157 0 : opaque_lsa_config_write_debug_callback(funclist, vty);
1158 :
1159 0 : return;
1160 : }
1161 :
1162 0 : void show_opaque_info_detail(struct vty *vty, struct ospf_lsa *lsa,
1163 : json_object *json)
1164 : {
1165 0 : struct lsa_header *lsah = lsa->data;
1166 0 : uint32_t lsid = ntohl(lsah->id.s_addr);
1167 0 : uint8_t opaque_type = GET_OPAQUE_TYPE(lsid);
1168 0 : uint32_t opaque_id = GET_OPAQUE_ID(lsid);
1169 0 : struct ospf_opaque_functab *functab;
1170 :
1171 : /* Switch output functionality by vty address. */
1172 0 : if (vty != NULL) {
1173 0 : if (!json) {
1174 0 : vty_out(vty, " Opaque-Type %u (%s)\n", opaque_type,
1175 : ospf_opaque_type_name(opaque_type));
1176 0 : vty_out(vty, " Opaque-ID 0x%x\n", opaque_id);
1177 :
1178 0 : vty_out(vty, " Opaque-Info: %u octets of data%s\n",
1179 0 : ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE,
1180 0 : VALID_OPAQUE_INFO_LEN(lsah)
1181 : ? ""
1182 : : "(Invalid length?)");
1183 : } else {
1184 0 : json_object_string_add(
1185 : json, "opaqueType",
1186 : ospf_opaque_type_name(opaque_type));
1187 0 : json_object_int_add(json, "opaqueId", opaque_id);
1188 0 : json_object_int_add(json, "opaqueDataLength",
1189 0 : ntohs(lsah->length)
1190 0 : - OSPF_LSA_HEADER_SIZE);
1191 0 : json_object_boolean_add(json, "opaqueDataLengthValid",
1192 0 : VALID_OPAQUE_INFO_LEN(lsah));
1193 : }
1194 : } else {
1195 0 : zlog_debug(" Opaque-Type %u (%s)", opaque_type,
1196 : ospf_opaque_type_name(opaque_type));
1197 0 : zlog_debug(" Opaque-ID 0x%x", opaque_id);
1198 :
1199 0 : 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 0 : if ((functab = ospf_opaque_functab_lookup(lsa)) != NULL)
1207 0 : if (functab->show_opaque_info != NULL)
1208 0 : (*functab->show_opaque_info)(vty, json, lsa);
1209 :
1210 0 : return;
1211 : }
1212 :
1213 0 : void ospf_opaque_lsa_dump(struct stream *s, uint16_t length)
1214 : {
1215 0 : struct ospf_lsa lsa = {};
1216 :
1217 0 : lsa.data = (struct lsa_header *)stream_pnt(s);
1218 0 : lsa.size = length;
1219 0 : show_opaque_info_detail(NULL, &lsa, NULL);
1220 0 : return;
1221 : }
1222 :
1223 161 : static int ospf_opaque_lsa_install_hook(struct ospf_lsa *lsa)
1224 : {
1225 161 : struct list *funclist;
1226 161 : 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 161 : funclist = ospf_opaque_wildcard_funclist;
1233 161 : if (new_lsa_callback(funclist, lsa) != 0)
1234 0 : goto out;
1235 :
1236 161 : funclist = ospf_opaque_type9_funclist;
1237 161 : if (new_lsa_callback(funclist, lsa) != 0)
1238 0 : goto out;
1239 :
1240 161 : funclist = ospf_opaque_type10_funclist;
1241 161 : if (new_lsa_callback(funclist, lsa) != 0)
1242 0 : goto out;
1243 :
1244 161 : funclist = ospf_opaque_type11_funclist;
1245 161 : if (new_lsa_callback(funclist, lsa) != 0)
1246 0 : goto out;
1247 :
1248 : rc = 0;
1249 161 : out:
1250 161 : return rc;
1251 : }
1252 :
1253 114 : static int ospf_opaque_lsa_delete_hook(struct ospf_lsa *lsa)
1254 : {
1255 114 : struct list *funclist;
1256 114 : 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 114 : funclist = ospf_opaque_wildcard_funclist;
1263 114 : if (del_lsa_callback(funclist, lsa) != 0)
1264 0 : goto out;
1265 :
1266 114 : funclist = ospf_opaque_type9_funclist;
1267 114 : if (del_lsa_callback(funclist, lsa) != 0)
1268 0 : goto out;
1269 :
1270 114 : funclist = ospf_opaque_type10_funclist;
1271 114 : if (del_lsa_callback(funclist, lsa) != 0)
1272 0 : goto out;
1273 :
1274 114 : funclist = ospf_opaque_type11_funclist;
1275 114 : if (del_lsa_callback(funclist, lsa) != 0)
1276 0 : goto out;
1277 :
1278 : rc = 0;
1279 114 : out:
1280 114 : 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 0 : void ospf_opaque_lsa_originate_schedule(struct ospf_interface *oi, int *delay0)
1293 : {
1294 0 : struct ospf *top;
1295 0 : struct ospf_area *area;
1296 0 : struct listnode *node, *nnode;
1297 0 : struct opaque_info_per_type *oipt;
1298 0 : int delay = 0;
1299 :
1300 0 : if ((top = oi_to_top(oi)) == NULL || (area = oi->area) == NULL) {
1301 0 : if (IS_DEBUG_OSPF_EVENT)
1302 0 : zlog_debug("%s: Invalid argument?", __func__);
1303 0 : return;
1304 : }
1305 :
1306 : /* It may not a right time to schedule origination now. */
1307 0 : if (!CHECK_FLAG(top->opaque, OPAQUE_OPERATION_READY_BIT)) {
1308 0 : if (IS_DEBUG_OSPF_EVENT)
1309 0 : zlog_debug("%s: Not operational.", __func__);
1310 0 : return; /* This is not an error. */
1311 : }
1312 :
1313 0 : if (delay0 != NULL)
1314 0 : 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 0 : ospf_opaque_lsa_reoriginate_resume(oi->opaque_lsa_self, (void *)oi);
1321 0 : ospf_opaque_lsa_reoriginate_resume(area->opaque_lsa_self, (void *)area);
1322 0 : 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 0 : if (!list_isempty(ospf_opaque_type9_funclist)
1328 0 : && list_isempty(oi->opaque_lsa_self)
1329 0 : && oi->t_opaque_lsa_self == NULL) {
1330 0 : if (IS_DEBUG_OSPF_EVENT)
1331 0 : zlog_debug(
1332 : "Schedule Type-9 Opaque-LSA origination in %d ms later.",
1333 : delay);
1334 0 : oi->t_opaque_lsa_self = NULL;
1335 0 : thread_add_timer_msec(master, ospf_opaque_type9_lsa_originate,
1336 : oi, delay, &oi->t_opaque_lsa_self);
1337 0 : delay += top->min_ls_interval;
1338 : }
1339 :
1340 0 : if (!list_isempty(ospf_opaque_type10_funclist)
1341 0 : && list_isempty(area->opaque_lsa_self)
1342 0 : && 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 0 : if (IS_DEBUG_OSPF_EVENT)
1349 0 : zlog_debug(
1350 : "Schedule Type-10 Opaque-LSA origination in %d ms later.",
1351 : delay);
1352 0 : area->t_opaque_lsa_self = NULL;
1353 0 : thread_add_timer_msec(master, ospf_opaque_type10_lsa_originate,
1354 : area, delay, &area->t_opaque_lsa_self);
1355 0 : delay += top->min_ls_interval;
1356 : }
1357 :
1358 0 : if (!list_isempty(ospf_opaque_type11_funclist)
1359 0 : && list_isempty(top->opaque_lsa_self)
1360 0 : && 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 0 : if (IS_DEBUG_OSPF_EVENT)
1367 0 : zlog_debug(
1368 : "Schedule Type-11 Opaque-LSA origination in %d ms later.",
1369 : delay);
1370 0 : top->t_opaque_lsa_self = NULL;
1371 0 : thread_add_timer_msec(master, ospf_opaque_type11_lsa_originate,
1372 : top, delay, &top->t_opaque_lsa_self);
1373 0 : 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 0 : if (!list_isempty(ospf_opaque_type9_funclist)
1381 0 : && !list_isempty(oi->opaque_lsa_self)) {
1382 0 : 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 0 : if (oipt->t_opaque_lsa_self
1393 : != NULL /* Waiting for a thread call. */
1394 0 : || oipt->status == PROC_SUSPEND) /* Cannot
1395 : originate
1396 : now. */
1397 0 : continue;
1398 :
1399 0 : ospf_opaque_lsa_reoriginate_schedule(
1400 : (void *)oi, OSPF_OPAQUE_LINK_LSA,
1401 0 : oipt->opaque_type);
1402 : }
1403 : }
1404 :
1405 0 : if (!list_isempty(ospf_opaque_type10_funclist)
1406 0 : && !list_isempty(area->opaque_lsa_self)) {
1407 0 : 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 0 : if (oipt->t_opaque_lsa_self
1418 : != NULL /* Waiting for a thread call. */
1419 0 : || oipt->status == PROC_SUSPEND) /* Cannot
1420 : originate
1421 : now. */
1422 0 : continue;
1423 :
1424 0 : ospf_opaque_lsa_reoriginate_schedule(
1425 : (void *)area, OSPF_OPAQUE_AREA_LSA,
1426 0 : oipt->opaque_type);
1427 : }
1428 : }
1429 :
1430 0 : if (!list_isempty(ospf_opaque_type11_funclist)
1431 0 : && !list_isempty(top->opaque_lsa_self)) {
1432 0 : 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 0 : if (oipt->t_opaque_lsa_self
1443 : != NULL /* Waiting for a thread call. */
1444 0 : || oipt->status == PROC_SUSPEND) /* Cannot
1445 : originate
1446 : now. */
1447 0 : continue;
1448 :
1449 0 : ospf_opaque_lsa_reoriginate_schedule((void *)top,
1450 : OSPF_OPAQUE_AS_LSA,
1451 0 : oipt->opaque_type);
1452 : }
1453 : }
1454 :
1455 0 : if (delay0 != NULL)
1456 0 : *delay0 = delay;
1457 : }
1458 :
1459 0 : static void ospf_opaque_type9_lsa_originate(struct thread *t)
1460 : {
1461 0 : struct ospf_interface *oi;
1462 :
1463 0 : oi = THREAD_ARG(t);
1464 0 : oi->t_opaque_lsa_self = NULL;
1465 :
1466 0 : if (IS_DEBUG_OSPF_EVENT)
1467 0 : zlog_debug("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
1468 : IF_NAME(oi));
1469 :
1470 0 : opaque_lsa_originate_callback(ospf_opaque_type9_funclist, oi);
1471 0 : }
1472 :
1473 0 : static void ospf_opaque_type10_lsa_originate(struct thread *t)
1474 : {
1475 0 : struct ospf_area *area;
1476 :
1477 0 : area = THREAD_ARG(t);
1478 0 : area->t_opaque_lsa_self = NULL;
1479 :
1480 0 : if (IS_DEBUG_OSPF_EVENT)
1481 0 : zlog_debug(
1482 : "Timer[Type10-LSA]: Originate Opaque-LSAs for Area %pI4",
1483 : &area->area_id);
1484 :
1485 0 : opaque_lsa_originate_callback(ospf_opaque_type10_funclist, area);
1486 0 : }
1487 :
1488 0 : static void ospf_opaque_type11_lsa_originate(struct thread *t)
1489 : {
1490 0 : struct ospf *top;
1491 :
1492 0 : top = THREAD_ARG(t);
1493 0 : top->t_opaque_lsa_self = NULL;
1494 :
1495 0 : if (IS_DEBUG_OSPF_EVENT)
1496 0 : zlog_debug(
1497 : "Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
1498 :
1499 0 : opaque_lsa_originate_callback(ospf_opaque_type11_funclist, top);
1500 0 : }
1501 :
1502 0 : static void ospf_opaque_lsa_reoriginate_resume(struct list *listtop, void *arg)
1503 : {
1504 0 : struct listnode *node, *nnode;
1505 0 : struct opaque_info_per_type *oipt;
1506 0 : struct ospf_opaque_functab *functab;
1507 :
1508 0 : if (listtop == NULL)
1509 0 : 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 0 : for (ALL_LIST_ELEMENTS(listtop, node, nnode, oipt)) {
1516 0 : if (oipt->status != PROC_SUSPEND)
1517 0 : continue;
1518 :
1519 0 : oipt->status = PROC_NORMAL;
1520 :
1521 0 : if ((functab = oipt->functab) == NULL
1522 0 : || functab->lsa_originator == NULL)
1523 0 : continue;
1524 :
1525 0 : if ((*functab->lsa_originator)(arg) != 0) {
1526 0 : flog_warn(EC_OSPF_LSA, "%s: Failed (opaque-type=%u)",
1527 : __func__, oipt->opaque_type);
1528 0 : continue;
1529 : }
1530 : }
1531 :
1532 0 : out:
1533 0 : return;
1534 : }
1535 :
1536 0 : struct ospf_lsa *ospf_opaque_lsa_install(struct ospf_lsa *lsa, int rt_recalc)
1537 : {
1538 0 : struct ospf_lsa *new = NULL;
1539 0 : struct opaque_info_per_type *oipt;
1540 0 : struct opaque_info_per_id *oipi;
1541 0 : struct ospf *top;
1542 :
1543 : /* Don't take "rt_recalc" into consideration for now. */ /* XXX */
1544 :
1545 0 : if (!IS_LSA_SELF(lsa)) {
1546 0 : new = lsa; /* Don't touch this LSA. */
1547 0 : goto out;
1548 : }
1549 :
1550 0 : if (IS_DEBUG_OSPF(lsa, LSA_INSTALL))
1551 0 : 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 0 : if ((oipt = lookup_opaque_info_by_type(lsa)) != NULL
1559 0 : && (oipi = lookup_opaque_info_by_id(oipt, lsa)) != NULL) {
1560 0 : ospf_lsa_unlock(&oipi->lsa);
1561 0 : oipi->lsa = ospf_lsa_lock(lsa);
1562 : }
1563 : /* Register the new lsa entry */
1564 0 : else if (register_opaque_lsa(lsa) == NULL) {
1565 0 : flog_warn(EC_OSPF_LSA, "%s: register_opaque_lsa() ?", __func__);
1566 0 : 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 0 : switch (lsa->data->type) {
1574 0 : case OSPF_OPAQUE_LINK_LSA:
1575 0 : if ((top = oi_to_top(lsa->oi)) == NULL) {
1576 : /* Above conditions must have passed. */
1577 0 : flog_warn(EC_OSPF_LSA, "%s: Something wrong?",
1578 : __func__);
1579 0 : goto out;
1580 : }
1581 : break;
1582 0 : case OSPF_OPAQUE_AREA_LSA:
1583 0 : if (lsa->area == NULL || (top = lsa->area->ospf) == NULL) {
1584 : /* Above conditions must have passed. */
1585 0 : flog_warn(EC_OSPF_LSA, "%s: Something wrong?",
1586 : __func__);
1587 0 : goto out;
1588 : }
1589 : break;
1590 0 : case OSPF_OPAQUE_AS_LSA:
1591 0 : top = ospf_lookup_by_vrf_id(lsa->vrf_id);
1592 0 : if (lsa->area != NULL && (top = lsa->area->ospf) == NULL) {
1593 : /* Above conditions must have passed. */
1594 0 : flog_warn(EC_OSPF_LSA, "%s: Something wrong?",
1595 : __func__);
1596 0 : goto out;
1597 : }
1598 : break;
1599 0 : default:
1600 0 : flog_warn(EC_OSPF_LSA_UNEXPECTED, "%s: Unexpected LSA-type(%u)",
1601 : __func__, lsa->data->type);
1602 0 : goto out;
1603 : }
1604 :
1605 0 : ospf_refresher_register_lsa(top, lsa);
1606 0 : new = lsa;
1607 :
1608 0 : out:
1609 0 : return new;
1610 : }
1611 :
1612 0 : struct ospf_lsa *ospf_opaque_lsa_refresh(struct ospf_lsa *lsa)
1613 : {
1614 0 : struct ospf *ospf;
1615 0 : struct ospf_opaque_functab *functab;
1616 0 : struct ospf_lsa *new = NULL;
1617 :
1618 0 : ospf = ospf_lookup_by_vrf_id(lsa->vrf_id);
1619 :
1620 0 : if ((functab = ospf_opaque_functab_lookup(lsa)) == NULL
1621 0 : || 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 0 : if (IS_DEBUG_OSPF_EVENT)
1630 0 : zlog_debug("LSA[Type%d:%pI4]: Flush stray Opaque-LSA",
1631 : lsa->data->type, &lsa->data->id);
1632 :
1633 0 : lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
1634 0 : ospf_lsa_flush(ospf, lsa);
1635 : } else
1636 0 : new = (*functab->lsa_refresher)(lsa);
1637 :
1638 0 : 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 0 : void ospf_opaque_lsa_reoriginate_schedule(void *lsa_type_dependent,
1657 : uint8_t lsa_type, uint8_t opaque_type)
1658 : {
1659 0 : struct ospf *top = NULL;
1660 0 : struct ospf_area dummy, *area = NULL;
1661 0 : struct ospf_interface *oi = NULL;
1662 :
1663 0 : struct ospf_lsa *lsa;
1664 0 : struct opaque_info_per_type *oipt;
1665 0 : void (*func)(struct thread * t) = NULL;
1666 0 : int delay;
1667 :
1668 0 : switch (lsa_type) {
1669 0 : case OSPF_OPAQUE_LINK_LSA:
1670 0 : if ((oi = (struct ospf_interface *)lsa_type_dependent)
1671 : == NULL) {
1672 0 : flog_warn(EC_OSPF_LSA,
1673 : "%s: Type-9 Opaque-LSA: Invalid parameter?",
1674 : __func__);
1675 0 : goto out;
1676 : }
1677 0 : if ((top = oi_to_top(oi)) == NULL) {
1678 0 : flog_warn(EC_OSPF_LSA, "%s: OI(%s) -> TOP?", __func__,
1679 : IF_NAME(oi));
1680 0 : goto out;
1681 : }
1682 0 : if (!list_isempty(ospf_opaque_type9_funclist)
1683 0 : && list_isempty(oi->opaque_lsa_self)
1684 0 : && oi->t_opaque_lsa_self != NULL) {
1685 0 : 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 0 : goto out;
1690 : }
1691 : func = ospf_opaque_type9_lsa_reoriginate_timer;
1692 : break;
1693 0 : case OSPF_OPAQUE_AREA_LSA:
1694 0 : if ((area = (struct ospf_area *)lsa_type_dependent) == NULL) {
1695 0 : flog_warn(EC_OSPF_LSA,
1696 : "%s: Type-10 Opaque-LSA: Invalid parameter?",
1697 : __func__);
1698 0 : goto out;
1699 : }
1700 0 : if ((top = area->ospf) == NULL) {
1701 0 : flog_warn(EC_OSPF_LSA, "%s: AREA(%pI4) -> TOP?",
1702 : __func__, &area->area_id);
1703 0 : goto out;
1704 : }
1705 0 : if (!list_isempty(ospf_opaque_type10_funclist)
1706 0 : && list_isempty(area->opaque_lsa_self)
1707 0 : && area->t_opaque_lsa_self != NULL) {
1708 0 : 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 0 : goto out;
1713 : }
1714 : func = ospf_opaque_type10_lsa_reoriginate_timer;
1715 : break;
1716 0 : case OSPF_OPAQUE_AS_LSA:
1717 0 : if ((top = (struct ospf *)lsa_type_dependent) == NULL) {
1718 0 : flog_warn(EC_OSPF_LSA,
1719 : "%s: Type-11 Opaque-LSA: Invalid parameter?",
1720 : __func__);
1721 0 : goto out;
1722 : }
1723 0 : if (!list_isempty(ospf_opaque_type11_funclist)
1724 0 : && list_isempty(top->opaque_lsa_self)
1725 0 : && top->t_opaque_lsa_self != NULL) {
1726 0 : flog_warn(
1727 : EC_OSPF_LSA,
1728 : "Type-11 Opaque-LSA (opaque_type=%u): Common origination has already started",
1729 : opaque_type);
1730 0 : goto out;
1731 : }
1732 :
1733 : /* Fake "area" to pass "ospf" to a lookup function later. */
1734 0 : dummy.ospf = top;
1735 0 : area = &dummy;
1736 :
1737 0 : func = ospf_opaque_type11_lsa_reoriginate_timer;
1738 0 : break;
1739 0 : default:
1740 0 : flog_warn(EC_OSPF_LSA_UNEXPECTED, "%s: Unexpected LSA-type(%u)",
1741 : __func__, lsa_type);
1742 0 : goto out;
1743 : }
1744 :
1745 : /* It may not a right time to schedule reorigination now. */
1746 0 : if (!CHECK_FLAG(top->opaque, OPAQUE_OPERATION_READY_BIT)) {
1747 0 : if (IS_DEBUG_OSPF_EVENT)
1748 0 : zlog_debug("%s: Not operational.", __func__);
1749 0 : goto out; /* This is not an error. */
1750 : }
1751 :
1752 : /* Generate a dummy lsa to be passed for a lookup function. */
1753 0 : lsa = pseudo_lsa(oi, area, lsa_type, opaque_type);
1754 0 : lsa->vrf_id = top->vrf_id;
1755 :
1756 0 : if ((oipt = lookup_opaque_info_by_type(lsa)) == NULL) {
1757 0 : struct ospf_opaque_functab *functab;
1758 0 : if ((functab = ospf_opaque_functab_lookup(lsa)) == NULL) {
1759 0 : flog_warn(
1760 : EC_OSPF_LSA,
1761 : "%s: No associated function?: lsa_type(%u), opaque_type(%u)",
1762 : __func__, lsa_type, opaque_type);
1763 0 : goto out;
1764 : }
1765 0 : if ((oipt = register_opaque_info_per_type(functab, lsa))
1766 : == NULL) {
1767 0 : 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 0 : goto out;
1772 : }
1773 : }
1774 :
1775 0 : if (oipt->t_opaque_lsa_self != NULL) {
1776 0 : if (IS_DEBUG_OSPF_EVENT)
1777 0 : 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 0 : 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 0 : delay = top->min_ls_interval; /* XXX */
1792 :
1793 0 : if (IS_DEBUG_OSPF_EVENT)
1794 0 : 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 0 : OSPF_OPAQUE_TIMER_ON(oipt->t_opaque_lsa_self, func, oipt, delay);
1800 :
1801 0 : out:
1802 0 : return;
1803 : }
1804 :
1805 0 : 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 0 : static struct ospf_lsa lsa = {0};
1810 0 : static struct lsa_header lsah = {0};
1811 0 : uint32_t tmp;
1812 :
1813 0 : lsa.oi = oi;
1814 0 : lsa.area = area;
1815 0 : lsa.data = &lsah;
1816 0 : lsa.vrf_id = VRF_DEFAULT;
1817 :
1818 0 : lsah.type = lsa_type;
1819 0 : tmp = SET_OPAQUE_LSID(opaque_type, 0); /* Opaque-ID is unused here. */
1820 0 : lsah.id.s_addr = htonl(tmp);
1821 :
1822 0 : return &lsa;
1823 : }
1824 :
1825 0 : static void ospf_opaque_type9_lsa_reoriginate_timer(struct thread *t)
1826 : {
1827 0 : struct opaque_info_per_type *oipt;
1828 0 : struct ospf_opaque_functab *functab;
1829 0 : struct ospf *top;
1830 0 : struct ospf_interface *oi;
1831 :
1832 0 : oipt = THREAD_ARG(t);
1833 :
1834 0 : if ((functab = oipt->functab) == NULL
1835 0 : || functab->lsa_originator == NULL) {
1836 0 : flog_warn(EC_OSPF_LSA, "%s: No associated function?", __func__);
1837 0 : return;
1838 : }
1839 :
1840 0 : oi = (struct ospf_interface *)oipt->owner;
1841 0 : if ((top = oi_to_top(oi)) == NULL) {
1842 0 : flog_warn(EC_OSPF_LSA, "%s: Something wrong?", __func__);
1843 0 : return;
1844 : }
1845 :
1846 0 : if (!CHECK_FLAG(top->config, OSPF_OPAQUE_CAPABLE)
1847 0 : || !ospf_if_is_enable(oi)
1848 0 : || ospf_nbr_count_opaque_capable(oi) == 0) {
1849 0 : if (IS_DEBUG_OSPF_EVENT)
1850 0 : zlog_debug(
1851 : "Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...",
1852 : oipt->opaque_type);
1853 :
1854 0 : oipt->status = PROC_SUSPEND;
1855 0 : return;
1856 : }
1857 :
1858 0 : if (IS_DEBUG_OSPF_EVENT)
1859 0 : 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 0 : (*functab->lsa_originator)(oi);
1864 : }
1865 :
1866 0 : static void ospf_opaque_type10_lsa_reoriginate_timer(struct thread *t)
1867 : {
1868 0 : struct opaque_info_per_type *oipt;
1869 0 : struct ospf_opaque_functab *functab;
1870 0 : struct listnode *node, *nnode;
1871 0 : struct ospf *top;
1872 0 : struct ospf_area *area;
1873 0 : struct ospf_interface *oi;
1874 0 : int n;
1875 :
1876 0 : oipt = THREAD_ARG(t);
1877 :
1878 0 : if ((functab = oipt->functab) == NULL
1879 0 : || functab->lsa_originator == NULL) {
1880 0 : flog_warn(EC_OSPF_LSA, "%s: No associated function?", __func__);
1881 0 : return;
1882 : }
1883 :
1884 0 : area = (struct ospf_area *)oipt->owner;
1885 0 : if (area == NULL || (top = area->ospf) == NULL) {
1886 0 : flog_warn(EC_OSPF_LSA, "%s: Something wrong?", __func__);
1887 0 : return;
1888 : }
1889 :
1890 : /* There must be at least one "opaque-capable, full-state" neighbor. */
1891 0 : n = 0;
1892 0 : for (ALL_LIST_ELEMENTS(area->oiflist, node, nnode, oi)) {
1893 0 : if ((n = ospf_nbr_count_opaque_capable(oi)) > 0)
1894 : break;
1895 : }
1896 :
1897 0 : if (n == 0 || !CHECK_FLAG(top->config, OSPF_OPAQUE_CAPABLE)) {
1898 0 : if (IS_DEBUG_OSPF_EVENT)
1899 0 : zlog_debug(
1900 : "Suspend re-origination of Type-10 Opaque-LSAs (opaque-type=%u) for a while...",
1901 : oipt->opaque_type);
1902 :
1903 0 : oipt->status = PROC_SUSPEND;
1904 0 : return;
1905 : }
1906 :
1907 0 : if (IS_DEBUG_OSPF_EVENT)
1908 0 : 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 0 : (*functab->lsa_originator)(area);
1913 : }
1914 :
1915 0 : static void ospf_opaque_type11_lsa_reoriginate_timer(struct thread *t)
1916 : {
1917 0 : struct opaque_info_per_type *oipt;
1918 0 : struct ospf_opaque_functab *functab;
1919 0 : struct ospf *top;
1920 :
1921 0 : oipt = THREAD_ARG(t);
1922 :
1923 0 : if ((functab = oipt->functab) == NULL
1924 0 : || functab->lsa_originator == NULL) {
1925 0 : flog_warn(EC_OSPF_LSA, "%s: No associated function?", __func__);
1926 0 : return;
1927 : }
1928 :
1929 0 : if ((top = (struct ospf *)oipt->owner) == NULL) {
1930 0 : flog_warn(EC_OSPF_LSA, "%s: Something wrong?", __func__);
1931 0 : return;
1932 : }
1933 :
1934 0 : if (!CHECK_FLAG(top->config, OSPF_OPAQUE_CAPABLE)) {
1935 0 : if (IS_DEBUG_OSPF_EVENT)
1936 0 : zlog_debug(
1937 : "Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...",
1938 : oipt->opaque_type);
1939 :
1940 0 : oipt->status = PROC_SUSPEND;
1941 0 : return;
1942 : }
1943 :
1944 0 : if (IS_DEBUG_OSPF_EVENT)
1945 0 : zlog_debug(
1946 : "Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).",
1947 : oipt->opaque_type);
1948 :
1949 0 : (*functab->lsa_originator)(top);
1950 : }
1951 :
1952 0 : void ospf_opaque_lsa_refresh_schedule(struct ospf_lsa *lsa0)
1953 : {
1954 0 : struct opaque_info_per_type *oipt;
1955 0 : struct opaque_info_per_id *oipi;
1956 0 : struct ospf_lsa *lsa;
1957 0 : struct ospf *top;
1958 0 : int delay;
1959 :
1960 0 : if ((oipt = lookup_opaque_info_by_type(lsa0)) == NULL
1961 0 : || (oipi = lookup_opaque_info_by_id(oipt, lsa0)) == NULL) {
1962 0 : flog_warn(EC_OSPF_LSA, "%s: Invalid parameter?", __func__);
1963 0 : goto out;
1964 : }
1965 :
1966 : /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
1967 0 : if ((lsa = oipi->lsa) == NULL) {
1968 0 : flog_warn(EC_OSPF_LSA, "%s: Something wrong?", __func__);
1969 0 : goto out;
1970 : }
1971 :
1972 0 : if (oipi->t_opaque_lsa_self != NULL) {
1973 0 : if (IS_DEBUG_OSPF_EVENT)
1974 0 : 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 0 : goto out;
1980 : }
1981 :
1982 : /* Delete this lsa from neighbor retransmit-list. */
1983 0 : switch (lsa->data->type) {
1984 0 : case OSPF_OPAQUE_LINK_LSA:
1985 : case OSPF_OPAQUE_AREA_LSA:
1986 0 : ospf_ls_retransmit_delete_nbr_area(lsa->area, lsa);
1987 0 : break;
1988 0 : case OSPF_OPAQUE_AS_LSA:
1989 0 : top = ospf_lookup_by_vrf_id(lsa0->vrf_id);
1990 0 : if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
1991 0 : top = lsa0->area->ospf;
1992 0 : ospf_ls_retransmit_delete_nbr_as(top, lsa);
1993 0 : break;
1994 0 : default:
1995 0 : flog_warn(EC_OSPF_LSA_UNEXPECTED, "%s: Unexpected LSA-type(%u)",
1996 : __func__, lsa->data->type);
1997 0 : goto out;
1998 : }
1999 :
2000 0 : delay = ospf_lsa_refresh_delay(lsa);
2001 :
2002 0 : if (IS_DEBUG_OSPF_EVENT)
2003 0 : 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 0 : OSPF_OPAQUE_TIMER_ON(oipi->t_opaque_lsa_self,
2010 : ospf_opaque_lsa_refresh_timer, oipi, delay * 1000);
2011 0 : out:
2012 0 : return;
2013 : }
2014 :
2015 0 : static void ospf_opaque_lsa_refresh_timer(struct thread *t)
2016 : {
2017 0 : struct opaque_info_per_id *oipi;
2018 0 : struct ospf_opaque_functab *functab;
2019 0 : struct ospf_lsa *lsa;
2020 :
2021 0 : if (IS_DEBUG_OSPF_EVENT)
2022 0 : zlog_debug("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
2023 :
2024 0 : oipi = THREAD_ARG(t);
2025 :
2026 0 : if ((lsa = oipi->lsa) != NULL)
2027 0 : if ((functab = oipi->opqctl_type->functab) != NULL)
2028 0 : if (functab->lsa_refresher != NULL)
2029 0 : (*functab->lsa_refresher)(lsa);
2030 0 : }
2031 :
2032 0 : void ospf_opaque_lsa_flush_schedule(struct ospf_lsa *lsa0)
2033 : {
2034 0 : struct opaque_info_per_type *oipt;
2035 0 : struct opaque_info_per_id *oipi;
2036 0 : struct ospf_lsa *lsa;
2037 0 : struct ospf *top;
2038 :
2039 0 : top = ospf_lookup_by_vrf_id(lsa0->vrf_id);
2040 :
2041 0 : if ((oipt = lookup_opaque_info_by_type(lsa0)) == NULL
2042 0 : || (oipi = lookup_opaque_info_by_id(oipt, lsa0)) == NULL) {
2043 0 : flog_warn(EC_OSPF_LSA, "%s: Invalid parameter?", __func__);
2044 0 : goto out;
2045 : }
2046 :
2047 : /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2048 0 : if ((lsa = oipi->lsa) == NULL) {
2049 0 : flog_warn(EC_OSPF_LSA, "%s: Something wrong?", __func__);
2050 0 : goto out;
2051 : }
2052 :
2053 0 : if (lsa->opaque_zero_len_delete &&
2054 0 : 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 0 : lsa->data->ls_seqnum = lsa_seqnum_increment(lsa);
2059 0 : lsa->data->length = htons(sizeof(struct lsa_header));
2060 0 : lsa->data->checksum = 0;
2061 0 : lsa->data->checksum = ospf_lsa_checksum(lsa->data);
2062 : }
2063 :
2064 : /* Delete this lsa from neighbor retransmit-list. */
2065 0 : switch (lsa->data->type) {
2066 0 : case OSPF_OPAQUE_LINK_LSA:
2067 : case OSPF_OPAQUE_AREA_LSA:
2068 0 : ospf_ls_retransmit_delete_nbr_area(lsa->area, lsa);
2069 0 : break;
2070 0 : case OSPF_OPAQUE_AS_LSA:
2071 0 : if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
2072 0 : top = lsa0->area->ospf;
2073 0 : ospf_ls_retransmit_delete_nbr_as(top, lsa);
2074 0 : break;
2075 0 : default:
2076 0 : flog_warn(EC_OSPF_LSA_UNEXPECTED, "%s: Unexpected LSA-type(%u)",
2077 : __func__, lsa->data->type);
2078 0 : goto out;
2079 : }
2080 :
2081 : /* This lsa will be flushed and removed eventually. */
2082 0 : ospf_lsa_flush(top, lsa);
2083 :
2084 : /* Dequeue listnode entry from the list. */
2085 0 : listnode_delete(oipt->id_list, oipi);
2086 :
2087 0 : if (IS_DEBUG_OSPF_EVENT)
2088 0 : 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 0 : free_opaque_info_per_id((void *)oipi);
2096 :
2097 0 : out:
2098 0 : return;
2099 : }
2100 :
2101 0 : void ospf_opaque_self_originated_lsa_received(struct ospf_neighbor *nbr,
2102 : struct ospf_lsa *lsa)
2103 : {
2104 0 : struct ospf *top;
2105 :
2106 0 : if ((top = oi_to_top(nbr->oi)) == NULL)
2107 : return;
2108 :
2109 0 : if (IS_DEBUG_OSPF_EVENT)
2110 0 : 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 0 : lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
2119 0 : switch (lsa->data->type) {
2120 0 : case OSPF_OPAQUE_LINK_LSA:
2121 0 : ospf_flood_through_area(nbr->oi->area, NULL /*inbr*/, lsa);
2122 0 : break;
2123 0 : case OSPF_OPAQUE_AREA_LSA:
2124 0 : ospf_flood_through_area(nbr->oi->area, NULL /*inbr*/, lsa);
2125 0 : break;
2126 0 : case OSPF_OPAQUE_AS_LSA:
2127 0 : ospf_flood_through_as(top, NULL /*inbr*/, lsa);
2128 0 : break;
2129 0 : default:
2130 0 : flog_warn(EC_OSPF_LSA_UNEXPECTED, "%s: Unexpected LSA-type(%u)",
2131 : __func__, lsa->data->type);
2132 0 : return;
2133 : }
2134 0 : 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 52 : struct ospf *oi_to_top(struct ospf_interface *oi)
2142 : {
2143 52 : struct ospf *top = NULL;
2144 52 : struct ospf_area *area;
2145 :
2146 52 : if (oi == NULL || (area = oi->area) == NULL
2147 52 : || (top = area->ospf) == NULL)
2148 0 : flog_warn(EC_OSPF_LSA,
2149 : "Broken relationship for \"OI -> AREA -> OSPF\"?");
2150 :
2151 52 : return top;
2152 : }
|