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