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