]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_opaque.c
OSPFd: Update Segment Routing PR following review
[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
610 /* Remove "oipt" from its owner's self-originated LSA list. */
611 switch (oipt->lsa_type) {
612 case OSPF_OPAQUE_LINK_LSA: {
613 struct ospf_interface *oi =
614 (struct ospf_interface *)(oipt->owner);
615 listnode_delete(oi->opaque_lsa_self, oipt);
616 break;
617 }
618 case OSPF_OPAQUE_AREA_LSA: {
619 struct ospf_area *area = (struct ospf_area *)(oipt->owner);
620 listnode_delete(area->opaque_lsa_self, oipt);
621 break;
622 }
623 case OSPF_OPAQUE_AS_LSA: {
624 struct ospf *top = (struct ospf *)(oipt->owner);
625 listnode_delete(top->opaque_lsa_self, oipt);
626 break;
627 }
628 default:
629 zlog_warn("free_opaque_info_per_type: Unexpected LSA-type(%u)",
630 oipt->lsa_type);
631 break; /* This case may not exist. */
632 }
633
634 OSPF_TIMER_OFF(oipt->t_opaque_lsa_self);
affe9e99 635 list_delete_and_null(&oipt->id_list);
d62a17ae 636 XFREE(MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
637 return;
718e3744 638}
639
640static struct opaque_info_per_type *
d62a17ae 641lookup_opaque_info_by_type(struct ospf_lsa *lsa)
642{
643 struct ospf *top;
644 struct ospf_area *area;
645 struct ospf_interface *oi;
646 struct list *listtop = NULL;
647 struct listnode *node, *nnode;
648 struct opaque_info_per_type *oipt = NULL;
649 u_char key = GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr));
650
651 switch (lsa->data->type) {
652 case OSPF_OPAQUE_LINK_LSA:
653 if ((oi = lsa->oi) != NULL)
654 listtop = oi->opaque_lsa_self;
655 else
656 zlog_warn(
657 "Type-9 Opaque-LSA: Reference to OI is missing?");
658 break;
659 case OSPF_OPAQUE_AREA_LSA:
660 if ((area = lsa->area) != NULL)
661 listtop = area->opaque_lsa_self;
662 else
663 zlog_warn(
664 "Type-10 Opaque-LSA: Reference to AREA is missing?");
665 break;
666 case OSPF_OPAQUE_AS_LSA:
b5a8894d 667 top = ospf_lookup_by_vrf_id(lsa->vrf_id);
d62a17ae 668 if ((area = lsa->area) != NULL && (top = area->ospf) == NULL) {
669 zlog_warn(
670 "Type-11 Opaque-LSA: Reference to OSPF is missing?");
671 break; /* Unlikely to happen. */
672 }
673 listtop = top->opaque_lsa_self;
674 break;
675 default:
676 zlog_warn("lookup_opaque_info_by_type: Unexpected LSA-type(%u)",
677 lsa->data->type);
678 break;
679 }
680
681 if (listtop != NULL)
682 for (ALL_LIST_ELEMENTS(listtop, node, nnode, oipt))
683 if (oipt->opaque_type == key)
684 return oipt;
685
686 return NULL;
718e3744 687}
688
689static struct opaque_info_per_id *
d62a17ae 690register_opaque_info_per_id(struct opaque_info_per_type *oipt,
691 struct ospf_lsa *new)
718e3744 692{
d62a17ae 693 struct opaque_info_per_id *oipi;
718e3744 694
d62a17ae 695 if ((oipi = XCALLOC(MTYPE_OPAQUE_INFO_PER_ID,
696 sizeof(struct opaque_info_per_id)))
697 == NULL) {
698 zlog_warn("register_opaque_info_per_id: XMALLOC: %s",
699 safe_strerror(errno));
700 goto out;
701 }
702 oipi->opaque_id = GET_OPAQUE_ID(ntohl(new->data->id.s_addr));
703 oipi->t_opaque_lsa_self = NULL;
704 oipi->opqctl_type = oipt;
705 oipi->lsa = ospf_lsa_lock(new);
718e3744 706
d62a17ae 707 listnode_add(oipt->id_list, oipi);
718e3744 708
709out:
d62a17ae 710 return oipi;
718e3744 711}
712
d62a17ae 713static void free_opaque_info_per_id(void *val)
718e3744 714{
d62a17ae 715 struct opaque_info_per_id *oipi = (struct opaque_info_per_id *)val;
718e3744 716
d62a17ae 717 OSPF_TIMER_OFF(oipi->t_opaque_lsa_self);
718 if (oipi->lsa != NULL)
719 ospf_lsa_unlock(&oipi->lsa);
720 XFREE(MTYPE_OPAQUE_INFO_PER_ID, oipi);
721 return;
718e3744 722}
723
724static struct opaque_info_per_id *
d62a17ae 725lookup_opaque_info_by_id(struct opaque_info_per_type *oipt,
726 struct ospf_lsa *lsa)
718e3744 727{
d62a17ae 728 struct listnode *node, *nnode;
729 struct opaque_info_per_id *oipi;
730 u_int32_t key = GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr));
718e3744 731
d62a17ae 732 for (ALL_LIST_ELEMENTS(oipt->id_list, node, nnode, oipi))
733 if (oipi->opaque_id == key)
734 return oipi;
718e3744 735
d62a17ae 736 return NULL;
718e3744 737}
738
d62a17ae 739static struct opaque_info_per_id *register_opaque_lsa(struct ospf_lsa *new)
718e3744 740{
d62a17ae 741 struct ospf_opaque_functab *functab;
742 struct opaque_info_per_type *oipt;
743 struct opaque_info_per_id *oipi = NULL;
718e3744 744
d62a17ae 745 if ((functab = ospf_opaque_functab_lookup(new)) == NULL)
746 goto out;
718e3744 747
d62a17ae 748 if ((oipt = lookup_opaque_info_by_type(new)) == NULL
749 && (oipt = register_opaque_info_per_type(functab, new)) == NULL)
750 goto out;
718e3744 751
d62a17ae 752 if ((oipi = register_opaque_info_per_id(oipt, new)) == NULL)
753 goto out;
718e3744 754
755out:
d62a17ae 756 return oipi;
718e3744 757}
758
759/*------------------------------------------------------------------------*
760 * Followings are (vty) configuration functions for Opaque-LSAs handling.
761 *------------------------------------------------------------------------*/
762
763DEFUN (capability_opaque,
764 capability_opaque_cmd,
765 "capability opaque",
766 "Enable specific OSPF feature\n"
767 "Opaque LSA\n")
768{
a3d826f0 769 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
718e3744 770
d62a17ae 771 /* Turn on the "master switch" of opaque-lsa capability. */
772 if (!CHECK_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE)) {
773 if (IS_DEBUG_OSPF_EVENT)
774 zlog_debug("Opaque capability: OFF -> ON");
718e3744 775
d62a17ae 776 SET_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE);
777 ospf_renegotiate_optional_capabilities(ospf);
778 }
779 return CMD_SUCCESS;
718e3744 780}
781
692b4c65
QY
782DEFUN (ospf_opaque,
783 ospf_opaque_cmd,
784 "ospf opaque-lsa",
785 "OSPF specific commands\n"
786 "Enable the Opaque-LSA capability (rfc2370)\n")
787{
d62a17ae 788 return capability_opaque(self, vty, argc, argv);
692b4c65 789}
718e3744 790
791DEFUN (no_capability_opaque,
792 no_capability_opaque_cmd,
793 "no capability opaque",
794 NO_STR
795 "Enable specific OSPF feature\n"
796 "Opaque LSA\n")
797{
a3d826f0 798 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
718e3744 799
d62a17ae 800 /* Turn off the "master switch" of opaque-lsa capability. */
801 if (CHECK_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE)) {
802 if (IS_DEBUG_OSPF_EVENT)
803 zlog_debug("Opaque capability: ON -> OFF");
718e3744 804
d62a17ae 805 UNSET_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE);
806 ospf_renegotiate_optional_capabilities(ospf);
807 }
808 return CMD_SUCCESS;
718e3744 809}
810
692b4c65
QY
811DEFUN (no_ospf_opaque,
812 no_ospf_opaque_cmd,
813 "no ospf opaque-lsa",
814 NO_STR
815 "OSPF specific commands\n"
816 "Enable the Opaque-LSA capability (rfc2370)\n")
817{
d62a17ae 818 return no_capability_opaque(self, vty, argc, argv);
692b4c65 819}
718e3744 820
d62a17ae 821static void ospf_opaque_register_vty(void)
718e3744 822{
d62a17ae 823 install_element(OSPF_NODE, &capability_opaque_cmd);
824 install_element(OSPF_NODE, &no_capability_opaque_cmd);
825 install_element(OSPF_NODE, &ospf_opaque_cmd);
826 install_element(OSPF_NODE, &no_ospf_opaque_cmd);
827 return;
718e3744 828}
829
830/*------------------------------------------------------------------------*
831 * Followings are collection of user-registered function callers.
832 *------------------------------------------------------------------------*/
833
d62a17ae 834static int opaque_lsa_new_if_callback(struct list *funclist,
835 struct interface *ifp)
718e3744 836{
d62a17ae 837 struct listnode *node, *nnode;
838 struct ospf_opaque_functab *functab;
839 int rc = -1;
718e3744 840
d62a17ae 841 for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab))
842 if (functab->new_if_hook != NULL)
843 if ((*functab->new_if_hook)(ifp) != 0)
844 goto out;
845 rc = 0;
718e3744 846out:
d62a17ae 847 return rc;
718e3744 848}
849
d62a17ae 850static int opaque_lsa_del_if_callback(struct list *funclist,
851 struct interface *ifp)
718e3744 852{
d62a17ae 853 struct listnode *node, *nnode;
854 struct ospf_opaque_functab *functab;
855 int rc = -1;
718e3744 856
d62a17ae 857 for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab))
858 if (functab->del_if_hook != NULL)
859 if ((*functab->del_if_hook)(ifp) != 0)
860 goto out;
861 rc = 0;
718e3744 862out:
d62a17ae 863 return rc;
718e3744 864}
865
d62a17ae 866static void opaque_lsa_ism_change_callback(struct list *funclist,
867 struct ospf_interface *oi,
868 int old_status)
718e3744 869{
d62a17ae 870 struct listnode *node, *nnode;
871 struct ospf_opaque_functab *functab;
718e3744 872
d62a17ae 873 for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab))
874 if (functab->ism_change_hook != NULL)
875 (*functab->ism_change_hook)(oi, old_status);
87d6f87a 876
d62a17ae 877 return;
718e3744 878}
879
d62a17ae 880static void opaque_lsa_nsm_change_callback(struct list *funclist,
881 struct ospf_neighbor *nbr,
882 int old_status)
718e3744 883{
d62a17ae 884 struct listnode *node, *nnode;
885 struct ospf_opaque_functab *functab;
718e3744 886
d62a17ae 887 for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab))
888 if (functab->nsm_change_hook != NULL)
889 (*functab->nsm_change_hook)(nbr, old_status);
890 return;
718e3744 891}
892
d62a17ae 893static void opaque_lsa_config_write_router_callback(struct list *funclist,
894 struct vty *vty)
718e3744 895{
d62a17ae 896 struct listnode *node, *nnode;
897 struct ospf_opaque_functab *functab;
718e3744 898
d62a17ae 899 for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab))
900 if (functab->config_write_router != NULL)
901 (*functab->config_write_router)(vty);
902 return;
718e3744 903}
904
d62a17ae 905static void opaque_lsa_config_write_if_callback(struct list *funclist,
906 struct vty *vty,
907 struct interface *ifp)
718e3744 908{
d62a17ae 909 struct listnode *node, *nnode;
910 struct ospf_opaque_functab *functab;
718e3744 911
d62a17ae 912 for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab))
913 if (functab->config_write_if != NULL)
914 (*functab->config_write_if)(vty, ifp);
915 return;
718e3744 916}
917
d62a17ae 918static void opaque_lsa_config_write_debug_callback(struct list *funclist,
919 struct vty *vty)
718e3744 920{
d62a17ae 921 struct listnode *node, *nnode;
922 struct ospf_opaque_functab *functab;
718e3744 923
d62a17ae 924 for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab))
925 if (functab->config_write_debug != NULL)
926 (*functab->config_write_debug)(vty);
927 return;
718e3744 928}
929
d62a17ae 930static int opaque_lsa_originate_callback(struct list *funclist,
931 void *lsa_type_dependent)
718e3744 932{
d62a17ae 933 struct listnode *node, *nnode;
934 struct ospf_opaque_functab *functab;
935 int rc = -1;
718e3744 936
d62a17ae 937 for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab))
938 if (functab->lsa_originator != NULL)
939 if ((*functab->lsa_originator)(lsa_type_dependent) != 0)
940 goto out;
941 rc = 0;
718e3744 942out:
d62a17ae 943 return rc;
718e3744 944}
945
d62a17ae 946static int new_lsa_callback(struct list *funclist, struct ospf_lsa *lsa)
718e3744 947{
d62a17ae 948 struct listnode *node, *nnode;
949 struct ospf_opaque_functab *functab;
950 int rc = -1;
718e3744 951
d62a17ae 952 /* This function handles ALL types of LSAs, not only opaque ones. */
953 for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab))
954 if (functab->new_lsa_hook != NULL)
955 if ((*functab->new_lsa_hook)(lsa) != 0)
956 goto out;
957 rc = 0;
718e3744 958out:
d62a17ae 959 return rc;
718e3744 960}
961
d62a17ae 962static int del_lsa_callback(struct list *funclist, struct ospf_lsa *lsa)
718e3744 963{
d62a17ae 964 struct listnode *node, *nnode;
965 struct ospf_opaque_functab *functab;
966 int rc = -1;
718e3744 967
d62a17ae 968 /* This function handles ALL types of LSAs, not only opaque ones. */
969 for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab))
970 if (functab->del_lsa_hook != NULL)
971 if ((*functab->del_lsa_hook)(lsa) != 0)
972 goto out;
973 rc = 0;
718e3744 974out:
d62a17ae 975 return rc;
718e3744 976}
977
978/*------------------------------------------------------------------------*
979 * Followings are glue functions to call Opaque-LSA specific processing.
980 *------------------------------------------------------------------------*/
981
d62a17ae 982int ospf_opaque_new_if(struct interface *ifp)
718e3744 983{
d62a17ae 984 struct list *funclist;
985 int rc = -1;
718e3744 986
d62a17ae 987 funclist = ospf_opaque_wildcard_funclist;
988 if (opaque_lsa_new_if_callback(funclist, ifp) != 0)
989 goto out;
09e4efdc 990
d62a17ae 991 funclist = ospf_opaque_type9_funclist;
992 if (opaque_lsa_new_if_callback(funclist, ifp) != 0)
993 goto out;
718e3744 994
d62a17ae 995 funclist = ospf_opaque_type10_funclist;
996 if (opaque_lsa_new_if_callback(funclist, ifp) != 0)
997 goto out;
718e3744 998
d62a17ae 999 funclist = ospf_opaque_type11_funclist;
1000 if (opaque_lsa_new_if_callback(funclist, ifp) != 0)
1001 goto out;
718e3744 1002
d62a17ae 1003 rc = 0;
718e3744 1004out:
d62a17ae 1005 return rc;
718e3744 1006}
1007
d62a17ae 1008int ospf_opaque_del_if(struct interface *ifp)
718e3744 1009{
d62a17ae 1010 struct list *funclist;
1011 int rc = -1;
718e3744 1012
d62a17ae 1013 funclist = ospf_opaque_wildcard_funclist;
1014 if (opaque_lsa_del_if_callback(funclist, ifp) != 0)
1015 goto out;
09e4efdc 1016
d62a17ae 1017 funclist = ospf_opaque_type9_funclist;
1018 if (opaque_lsa_del_if_callback(funclist, ifp) != 0)
1019 goto out;
718e3744 1020
d62a17ae 1021 funclist = ospf_opaque_type10_funclist;
1022 if (opaque_lsa_del_if_callback(funclist, ifp) != 0)
1023 goto out;
718e3744 1024
d62a17ae 1025 funclist = ospf_opaque_type11_funclist;
1026 if (opaque_lsa_del_if_callback(funclist, ifp) != 0)
1027 goto out;
718e3744 1028
d62a17ae 1029 rc = 0;
718e3744 1030out:
d62a17ae 1031 return rc;
718e3744 1032}
1033
d62a17ae 1034void ospf_opaque_ism_change(struct ospf_interface *oi, int old_status)
718e3744 1035{
d62a17ae 1036 struct list *funclist;
718e3744 1037
d62a17ae 1038 funclist = ospf_opaque_wildcard_funclist;
1039 opaque_lsa_ism_change_callback(funclist, oi, old_status);
09e4efdc 1040
d62a17ae 1041 funclist = ospf_opaque_type9_funclist;
1042 opaque_lsa_ism_change_callback(funclist, oi, old_status);
718e3744 1043
d62a17ae 1044 funclist = ospf_opaque_type10_funclist;
1045 opaque_lsa_ism_change_callback(funclist, oi, old_status);
718e3744 1046
d62a17ae 1047 funclist = ospf_opaque_type11_funclist;
1048 opaque_lsa_ism_change_callback(funclist, oi, old_status);
718e3744 1049
d62a17ae 1050 return;
718e3744 1051}
1052
d62a17ae 1053void ospf_opaque_nsm_change(struct ospf_neighbor *nbr, int old_state)
718e3744 1054{
d62a17ae 1055 struct ospf *top;
1056 struct list *funclist;
718e3744 1057
d62a17ae 1058 if ((top = oi_to_top(nbr->oi)) == NULL)
1059 goto out;
718e3744 1060
d62a17ae 1061 if (old_state != NSM_Full && nbr->state == NSM_Full) {
1062 if (CHECK_FLAG(nbr->options, OSPF_OPTION_O)) {
1063 if (!CHECK_FLAG(top->opaque,
1064 OPAQUE_OPERATION_READY_BIT)) {
1065 if (IS_DEBUG_OSPF_EVENT)
1066 zlog_debug(
1067 "Opaque-LSA: Now get operational!");
718e3744 1068
d62a17ae 1069 SET_FLAG(top->opaque,
1070 OPAQUE_OPERATION_READY_BIT);
1071 }
718e3744 1072
d62a17ae 1073 ospf_opaque_lsa_originate_schedule(nbr->oi, NULL);
1074 }
1075 } else if (old_state == NSM_Full && nbr->state != NSM_Full) {
718e3744 1076#ifdef NOTYET
d62a17ae 1077/*
1078 * If no more opaque-capable full-state neighbor remains in the
1079 * flooding scope which corresponds to Opaque-LSA type, periodic
1080 * LS flooding should be stopped.
1081 */
718e3744 1082#endif /* NOTYET */
d62a17ae 1083 ;
1084 }
718e3744 1085
d62a17ae 1086 funclist = ospf_opaque_wildcard_funclist;
1087 opaque_lsa_nsm_change_callback(funclist, nbr, old_state);
09e4efdc 1088
d62a17ae 1089 funclist = ospf_opaque_type9_funclist;
1090 opaque_lsa_nsm_change_callback(funclist, nbr, old_state);
718e3744 1091
d62a17ae 1092 funclist = ospf_opaque_type10_funclist;
1093 opaque_lsa_nsm_change_callback(funclist, nbr, old_state);
718e3744 1094
d62a17ae 1095 funclist = ospf_opaque_type11_funclist;
1096 opaque_lsa_nsm_change_callback(funclist, nbr, old_state);
718e3744 1097
1098out:
d62a17ae 1099 return;
718e3744 1100}
1101
d62a17ae 1102void ospf_opaque_config_write_router(struct vty *vty, struct ospf *ospf)
718e3744 1103{
d62a17ae 1104 struct list *funclist;
718e3744 1105
d62a17ae 1106 if (CHECK_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE))
1107 vty_out(vty, " capability opaque\n");
718e3744 1108
d62a17ae 1109 funclist = ospf_opaque_wildcard_funclist;
1110 opaque_lsa_config_write_router_callback(funclist, vty);
09e4efdc 1111
d62a17ae 1112 funclist = ospf_opaque_type9_funclist;
1113 opaque_lsa_config_write_router_callback(funclist, vty);
718e3744 1114
d62a17ae 1115 funclist = ospf_opaque_type10_funclist;
1116 opaque_lsa_config_write_router_callback(funclist, vty);
718e3744 1117
d62a17ae 1118 funclist = ospf_opaque_type11_funclist;
1119 opaque_lsa_config_write_router_callback(funclist, vty);
718e3744 1120
d62a17ae 1121 return;
718e3744 1122}
1123
d62a17ae 1124void ospf_opaque_config_write_if(struct vty *vty, struct interface *ifp)
718e3744 1125{
d62a17ae 1126 struct list *funclist;
718e3744 1127
d62a17ae 1128 funclist = ospf_opaque_wildcard_funclist;
1129 opaque_lsa_config_write_if_callback(funclist, vty, ifp);
09e4efdc 1130
d62a17ae 1131 funclist = ospf_opaque_type9_funclist;
1132 opaque_lsa_config_write_if_callback(funclist, vty, ifp);
718e3744 1133
d62a17ae 1134 funclist = ospf_opaque_type10_funclist;
1135 opaque_lsa_config_write_if_callback(funclist, vty, ifp);
718e3744 1136
d62a17ae 1137 funclist = ospf_opaque_type11_funclist;
1138 opaque_lsa_config_write_if_callback(funclist, vty, ifp);
718e3744 1139
d62a17ae 1140 return;
718e3744 1141}
1142
d62a17ae 1143void ospf_opaque_config_write_debug(struct vty *vty)
718e3744 1144{
d62a17ae 1145 struct list *funclist;
718e3744 1146
d62a17ae 1147 funclist = ospf_opaque_wildcard_funclist;
1148 opaque_lsa_config_write_debug_callback(funclist, vty);
09e4efdc 1149
d62a17ae 1150 funclist = ospf_opaque_type9_funclist;
1151 opaque_lsa_config_write_debug_callback(funclist, vty);
718e3744 1152
d62a17ae 1153 funclist = ospf_opaque_type10_funclist;
1154 opaque_lsa_config_write_debug_callback(funclist, vty);
718e3744 1155
d62a17ae 1156 funclist = ospf_opaque_type11_funclist;
1157 opaque_lsa_config_write_debug_callback(funclist, vty);
718e3744 1158
d62a17ae 1159 return;
718e3744 1160}
1161
d62a17ae 1162void show_opaque_info_detail(struct vty *vty, struct ospf_lsa *lsa)
718e3744 1163{
d62a17ae 1164 struct lsa_header *lsah = (struct lsa_header *)lsa->data;
1165 u_int32_t lsid = ntohl(lsah->id.s_addr);
1166 u_char opaque_type = GET_OPAQUE_TYPE(lsid);
1167 u_int32_t opaque_id = GET_OPAQUE_ID(lsid);
1168 struct ospf_opaque_functab *functab;
718e3744 1169
d62a17ae 1170 /* Switch output functionality by vty address. */
1171 if (vty != NULL) {
1172 vty_out(vty, " Opaque-Type %u (%s)\n", opaque_type,
1173 ospf_opaque_type_name(opaque_type));
1174 vty_out(vty, " Opaque-ID 0x%x\n", opaque_id);
718e3744 1175
d62a17ae 1176 vty_out(vty, " Opaque-Info: %u octets of data%s\n",
1177 ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE,
1178 VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)");
1179 } else {
1180 zlog_debug(" Opaque-Type %u (%s)", opaque_type,
1181 ospf_opaque_type_name(opaque_type));
1182 zlog_debug(" Opaque-ID 0x%x", opaque_id);
718e3744 1183
d62a17ae 1184 zlog_debug(" Opaque-Info: %u octets of data%s",
1185 ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE,
1186 VALID_OPAQUE_INFO_LEN(lsah) ? ""
1187 : "(Invalid length?)");
1188 }
718e3744 1189
d62a17ae 1190 /* Call individual output functions. */
1191 if ((functab = ospf_opaque_functab_lookup(lsa)) != NULL)
1192 if (functab->show_opaque_info != NULL)
1193 (*functab->show_opaque_info)(vty, lsa);
718e3744 1194
d62a17ae 1195 return;
718e3744 1196}
1197
d62a17ae 1198void ospf_opaque_lsa_dump(struct stream *s, u_int16_t length)
718e3744 1199{
d62a17ae 1200 struct ospf_lsa lsa;
718e3744 1201
2d34fb80 1202 lsa.data = (struct lsa_header *)stream_pnt(s);
d62a17ae 1203 show_opaque_info_detail(NULL, &lsa);
1204 return;
718e3744 1205}
1206
d62a17ae 1207static int ospf_opaque_lsa_install_hook(struct ospf_lsa *lsa)
718e3744 1208{
d62a17ae 1209 struct list *funclist;
1210 int rc = -1;
718e3744 1211
d62a17ae 1212 /*
1213 * Some Opaque-LSA user may want to monitor every LSA installation
1214 * into the LSDB, regardless with target LSA type.
1215 */
1216 funclist = ospf_opaque_wildcard_funclist;
1217 if (new_lsa_callback(funclist, lsa) != 0)
1218 goto out;
09e4efdc 1219
d62a17ae 1220 funclist = ospf_opaque_type9_funclist;
1221 if (new_lsa_callback(funclist, lsa) != 0)
1222 goto out;
718e3744 1223
d62a17ae 1224 funclist = ospf_opaque_type10_funclist;
1225 if (new_lsa_callback(funclist, lsa) != 0)
1226 goto out;
718e3744 1227
d62a17ae 1228 funclist = ospf_opaque_type11_funclist;
1229 if (new_lsa_callback(funclist, lsa) != 0)
1230 goto out;
718e3744 1231
d62a17ae 1232 rc = 0;
718e3744 1233out:
d62a17ae 1234 return rc;
718e3744 1235}
1236
d62a17ae 1237static int ospf_opaque_lsa_delete_hook(struct ospf_lsa *lsa)
718e3744 1238{
d62a17ae 1239 struct list *funclist;
1240 int rc = -1;
718e3744 1241
d62a17ae 1242 /*
1243 * Some Opaque-LSA user may want to monitor every LSA deletion
1244 * from the LSDB, regardless with target LSA type.
1245 */
1246 funclist = ospf_opaque_wildcard_funclist;
1247 if (del_lsa_callback(funclist, lsa) != 0)
1248 goto out;
09e4efdc 1249
d62a17ae 1250 funclist = ospf_opaque_type9_funclist;
1251 if (del_lsa_callback(funclist, lsa) != 0)
1252 goto out;
718e3744 1253
d62a17ae 1254 funclist = ospf_opaque_type10_funclist;
1255 if (del_lsa_callback(funclist, lsa) != 0)
1256 goto out;
718e3744 1257
d62a17ae 1258 funclist = ospf_opaque_type11_funclist;
1259 if (del_lsa_callback(funclist, lsa) != 0)
1260 goto out;
718e3744 1261
d62a17ae 1262 rc = 0;
718e3744 1263out:
d62a17ae 1264 return rc;
718e3744 1265}
1266
1267/*------------------------------------------------------------------------*
1268 * Followings are Opaque-LSA origination/refresh management functions.
1269 *------------------------------------------------------------------------*/
1270
d62a17ae 1271static int ospf_opaque_type9_lsa_originate(struct thread *t);
1272static int ospf_opaque_type10_lsa_originate(struct thread *t);
1273static int ospf_opaque_type11_lsa_originate(struct thread *t);
1274static void ospf_opaque_lsa_reoriginate_resume(struct list *listtop, void *arg);
1275
1276void ospf_opaque_lsa_originate_schedule(struct ospf_interface *oi, int *delay0)
1277{
1278 struct ospf *top;
1279 struct ospf_area *area;
1280 struct listnode *node, *nnode;
1281 struct opaque_info_per_type *oipt;
1282 int delay = 0;
1283
1284 if ((top = oi_to_top(oi)) == NULL || (area = oi->area) == NULL) {
1285 zlog_warn(
1286 "ospf_opaque_lsa_originate_schedule: Invalid argument?");
1287 goto out;
1288 }
1289
1290 /* It may not a right time to schedule origination now. */
1291 if (!CHECK_FLAG(top->opaque, OPAQUE_OPERATION_READY_BIT)) {
1292 if (IS_DEBUG_OSPF_EVENT)
1293 zlog_debug(
1294 "ospf_opaque_lsa_originate_schedule: Not operational.");
1295 goto out; /* This is not an error. */
1296 }
1297
1298 if (delay0 != NULL)
1299 delay = *delay0;
1300
1301 /*
1302 * There might be some entries that have been waiting for triggering
1303 * of per opaque-type re-origination get resumed.
1304 */
1305 ospf_opaque_lsa_reoriginate_resume(oi->opaque_lsa_self, (void *)oi);
1306 ospf_opaque_lsa_reoriginate_resume(area->opaque_lsa_self, (void *)area);
1307 ospf_opaque_lsa_reoriginate_resume(top->opaque_lsa_self, (void *)top);
1308
1309 /*
1310 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1311 */
1312 if (!list_isempty(ospf_opaque_type9_funclist)
1313 && list_isempty(oi->opaque_lsa_self)
1314 && oi->t_opaque_lsa_self == NULL) {
1315 if (IS_DEBUG_OSPF_EVENT)
1316 zlog_debug(
1317 "Schedule Type-9 Opaque-LSA origination in %d ms later.",
1318 delay);
1319 oi->t_opaque_lsa_self = NULL;
1320 thread_add_timer_msec(master, ospf_opaque_type9_lsa_originate,
1321 oi, delay, &oi->t_opaque_lsa_self);
1322 delay += top->min_ls_interval;
1323 }
1324
1325 if (!list_isempty(ospf_opaque_type10_funclist)
1326 && list_isempty(area->opaque_lsa_self)
1327 && area->t_opaque_lsa_self == NULL) {
1328 /*
1329 * One AREA may contain multiple OIs, but above 2nd and 3rd
1330 * conditions prevent from scheduling the originate function
1331 * again and again.
1332 */
1333 if (IS_DEBUG_OSPF_EVENT)
1334 zlog_debug(
1335 "Schedule Type-10 Opaque-LSA origination in %d ms later.",
1336 delay);
1337 area->t_opaque_lsa_self = NULL;
1338 thread_add_timer_msec(master, ospf_opaque_type10_lsa_originate,
1339 area, delay, &area->t_opaque_lsa_self);
1340 delay += top->min_ls_interval;
1341 }
1342
1343 if (!list_isempty(ospf_opaque_type11_funclist)
1344 && list_isempty(top->opaque_lsa_self)
1345 && top->t_opaque_lsa_self == NULL) {
1346 /*
1347 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1348 * conditions prevent from scheduling the originate function
1349 * again and again.
1350 */
1351 if (IS_DEBUG_OSPF_EVENT)
1352 zlog_debug(
1353 "Schedule Type-11 Opaque-LSA origination in %d ms later.",
1354 delay);
1355 top->t_opaque_lsa_self = NULL;
1356 thread_add_timer_msec(master, ospf_opaque_type11_lsa_originate,
1357 top, delay, &top->t_opaque_lsa_self);
1358 delay += top->min_ls_interval;
1359 }
1360
1361 /*
1362 * Following section treats a special situation that this node's
1363 * opaque capability has changed as "ON -> OFF -> ON".
1364 */
1365 if (!list_isempty(ospf_opaque_type9_funclist)
1366 && !list_isempty(oi->opaque_lsa_self)) {
1367 for (ALL_LIST_ELEMENTS(oi->opaque_lsa_self, node, nnode,
1368 oipt)) {
1369 /*
1370 * removed the test for
1371 * (! list_isempty (oipt->id_list)) * Handler is
1372 * already active. *
1373 * because opaque cababilities ON -> OFF -> ON result in
1374 * list_isempty (oipt->id_list)
1375 * not being empty.
1376 */
9d303b37
DL
1377 if (
1378 oipt->t_opaque_lsa_self
1379 != NULL /* Waiting for a thread call. */
1380 || oipt->status == PROC_SUSPEND) /* Cannot
1381 originate
1382 now. */
d62a17ae 1383 continue;
1384
1385 ospf_opaque_lsa_reoriginate_schedule(
1386 (void *)oi, OSPF_OPAQUE_LINK_LSA,
1387 oipt->opaque_type);
1388 }
1389 }
1390
1391 if (!list_isempty(ospf_opaque_type10_funclist)
1392 && !list_isempty(area->opaque_lsa_self)) {
1393 for (ALL_LIST_ELEMENTS(area->opaque_lsa_self, node, nnode,
1394 oipt)) {
1395 /*
1396 * removed the test for
1397 * (! list_isempty (oipt->id_list)) * Handler is
1398 * already active. *
1399 * because opaque cababilities ON -> OFF -> ON result in
1400 * list_isempty (oipt->id_list)
1401 * not being empty.
1402 */
9d303b37
DL
1403 if (
1404 oipt->t_opaque_lsa_self
1405 != NULL /* Waiting for a thread call. */
1406 || oipt->status == PROC_SUSPEND) /* Cannot
1407 originate
1408 now. */
d62a17ae 1409 continue;
1410
1411 ospf_opaque_lsa_reoriginate_schedule(
1412 (void *)area, OSPF_OPAQUE_AREA_LSA,
1413 oipt->opaque_type);
1414 }
1415 }
1416
1417 if (!list_isempty(ospf_opaque_type11_funclist)
1418 && !list_isempty(top->opaque_lsa_self)) {
1419 for (ALL_LIST_ELEMENTS(top->opaque_lsa_self, node, nnode,
1420 oipt)) {
1421 /*
1422 * removed the test for
1423 * (! list_isempty (oipt->id_list)) * Handler is
1424 * already active. *
1425 * because opaque cababilities ON -> OFF -> ON result in
1426 * list_isempty (oipt->id_list)
1427 * not being empty.
1428 */
9d303b37
DL
1429 if (
1430 oipt->t_opaque_lsa_self
1431 != NULL /* Waiting for a thread call. */
1432 || oipt->status == PROC_SUSPEND) /* Cannot
1433 originate
1434 now. */
d62a17ae 1435 continue;
1436
1437 ospf_opaque_lsa_reoriginate_schedule((void *)top,
1438 OSPF_OPAQUE_AS_LSA,
1439 oipt->opaque_type);
1440 }
1441 }
1442
1443 if (delay0 != NULL)
1444 *delay0 = delay;
718e3744 1445
1446out:
d62a17ae 1447 return;
718e3744 1448}
1449
d62a17ae 1450static int ospf_opaque_type9_lsa_originate(struct thread *t)
718e3744 1451{
d62a17ae 1452 struct ospf_interface *oi;
1453 int rc;
718e3744 1454
d62a17ae 1455 oi = THREAD_ARG(t);
1456 oi->t_opaque_lsa_self = NULL;
718e3744 1457
d62a17ae 1458 if (IS_DEBUG_OSPF_EVENT)
1459 zlog_debug("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
1460 IF_NAME(oi));
718e3744 1461
d62a17ae 1462 rc = opaque_lsa_originate_callback(ospf_opaque_type9_funclist, oi);
718e3744 1463
d62a17ae 1464 return rc;
718e3744 1465}
1466
d62a17ae 1467static int ospf_opaque_type10_lsa_originate(struct thread *t)
718e3744 1468{
d62a17ae 1469 struct ospf_area *area;
1470 int rc;
718e3744 1471
d62a17ae 1472 area = THREAD_ARG(t);
1473 area->t_opaque_lsa_self = NULL;
718e3744 1474
d62a17ae 1475 if (IS_DEBUG_OSPF_EVENT)
1476 zlog_debug(
1477 "Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
1478 inet_ntoa(area->area_id));
718e3744 1479
d62a17ae 1480 rc = opaque_lsa_originate_callback(ospf_opaque_type10_funclist, area);
718e3744 1481
d62a17ae 1482 return rc;
718e3744 1483}
1484
d62a17ae 1485static int ospf_opaque_type11_lsa_originate(struct thread *t)
718e3744 1486{
d62a17ae 1487 struct ospf *top;
1488 int rc;
718e3744 1489
d62a17ae 1490 top = THREAD_ARG(t);
1491 top->t_opaque_lsa_self = NULL;
718e3744 1492
d62a17ae 1493 if (IS_DEBUG_OSPF_EVENT)
1494 zlog_debug(
1495 "Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
718e3744 1496
d62a17ae 1497 rc = opaque_lsa_originate_callback(ospf_opaque_type11_funclist, top);
718e3744 1498
d62a17ae 1499 return rc;
718e3744 1500}
1501
d62a17ae 1502static void ospf_opaque_lsa_reoriginate_resume(struct list *listtop, void *arg)
718e3744 1503{
d62a17ae 1504 struct listnode *node, *nnode;
1505 struct opaque_info_per_type *oipt;
1506 struct ospf_opaque_functab *functab;
718e3744 1507
d62a17ae 1508 if (listtop == NULL)
1509 goto out;
718e3744 1510
d62a17ae 1511 /*
1512 * Pickup oipt entries those which in SUSPEND status, and give
1513 * them a chance to start re-origination now.
1514 */
1515 for (ALL_LIST_ELEMENTS(listtop, node, nnode, oipt)) {
1516 if (oipt->status != PROC_SUSPEND)
1517 continue;
718e3744 1518
d62a17ae 1519 oipt->status = PROC_NORMAL;
718e3744 1520
d62a17ae 1521 if ((functab = oipt->functab) == NULL
1522 || functab->lsa_originator == NULL)
1523 continue;
718e3744 1524
d62a17ae 1525 if ((*functab->lsa_originator)(arg) != 0) {
1526 zlog_warn(
1527 "ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)",
1528 oipt->opaque_type);
1529 continue;
1530 }
1531 }
718e3744 1532
1533out:
d62a17ae 1534 return;
1535}
1536
1537struct ospf_lsa *ospf_opaque_lsa_install(struct ospf_lsa *lsa, int rt_recalc)
1538{
1539 struct ospf_lsa *new = NULL;
1540 struct opaque_info_per_type *oipt;
1541 struct opaque_info_per_id *oipi;
1542 struct ospf *top;
1543
1544 /* Don't take "rt_recalc" into consideration for now. */ /* XXX */
1545
1546 if (!IS_LSA_SELF(lsa)) {
1547 new = lsa; /* Don't touch this LSA. */
1548 goto out;
1549 }
1550
1551 if (IS_DEBUG_OSPF(lsa, LSA_INSTALL))
1552 zlog_debug(
1553 "Install Type-%u Opaque-LSA: [opaque-type=%u, opaque-id=%x]",
1554 lsa->data->type,
1555 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)),
1556 GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)));
1557
1558 /* Replace the existing lsa with the new one. */
1559 if ((oipt = lookup_opaque_info_by_type(lsa)) != NULL
1560 && (oipi = lookup_opaque_info_by_id(oipt, lsa)) != NULL) {
1561 ospf_lsa_unlock(&oipi->lsa);
1562 oipi->lsa = ospf_lsa_lock(lsa);
1563 }
1564 /* Register the new lsa entry and get its control info. */
1565 else if ((oipi = register_opaque_lsa(lsa)) == NULL) {
1566 zlog_warn("ospf_opaque_lsa_install: register_opaque_lsa() ?");
1567 goto out;
1568 }
1569
1570 /*
1571 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1572 * for periodic refresh of self-originated Opaque-LSAs.
1573 */
1574 switch (lsa->data->type) {
1575 case OSPF_OPAQUE_LINK_LSA:
1576 if ((top = oi_to_top(lsa->oi)) == NULL) {
1577 /* Above conditions must have passed. */
1578 zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?");
1579 goto out;
1580 }
1581 break;
1582 case OSPF_OPAQUE_AREA_LSA:
1583 if (lsa->area == NULL || (top = lsa->area->ospf) == NULL) {
1584 /* Above conditions must have passed. */
1585 zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?");
1586 goto out;
1587 }
1588 break;
1589 case OSPF_OPAQUE_AS_LSA:
b5a8894d 1590 top = ospf_lookup_by_vrf_id(lsa->vrf_id);
d62a17ae 1591 if (lsa->area != NULL && (top = lsa->area->ospf) == NULL) {
1592 /* Above conditions must have passed. */
1593 zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?");
1594 goto out;
1595 }
1596 break;
1597 default:
1598 zlog_warn("ospf_opaque_lsa_install: Unexpected LSA-type(%u)",
1599 lsa->data->type);
1600 goto out;
1601 }
1602
1603 ospf_refresher_register_lsa(top, lsa);
1604 new = lsa;
718e3744 1605
1606out:
d62a17ae 1607 return new;
718e3744 1608}
1609
d62a17ae 1610struct ospf_lsa *ospf_opaque_lsa_refresh(struct ospf_lsa *lsa)
718e3744 1611{
d62a17ae 1612 struct ospf *ospf;
1613 struct ospf_opaque_functab *functab;
1614 struct ospf_lsa *new = NULL;
1615
b5a8894d 1616 ospf = ospf_lookup_by_vrf_id(lsa->vrf_id);
020709f9 1617
d62a17ae 1618 if ((functab = ospf_opaque_functab_lookup(lsa)) == NULL
1619 || functab->lsa_refresher == NULL) {
1620 /*
1621 * Though this LSA seems to have originated on this node, the
1622 * handling module for this "lsa-type and opaque-type" was
1623 * already deleted sometime ago.
1624 * Anyway, this node still has a responsibility to flush this
1625 * LSA from the routing domain.
1626 */
1627 if (IS_DEBUG_OSPF_EVENT)
1628 zlog_debug("LSA[Type%d:%s]: Flush stray Opaque-LSA",
1629 lsa->data->type, inet_ntoa(lsa->data->id));
718e3744 1630
d62a17ae 1631 lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
1632 ospf_lsa_flush(ospf, lsa);
1633 } else
1634 new = (*functab->lsa_refresher)(lsa);
718e3744 1635
d62a17ae 1636 return new;
718e3744 1637}
1638
1639/*------------------------------------------------------------------------*
1640 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1641 * triggered by external interventions (vty session, signaling, etc).
1642 *------------------------------------------------------------------------*/
1643
ffa2c898 1644#define OSPF_OPAQUE_TIMER_ON(T,F,L,V) thread_add_timer_msec (master, (F), (L), (V), &(T))
718e3744 1645
d62a17ae 1646static struct ospf_lsa *pseudo_lsa(struct ospf_interface *oi,
1647 struct ospf_area *area, u_char lsa_type,
1648 u_char opaque_type);
1649static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread *t);
1650static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread *t);
1651static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread *t);
1652static int ospf_opaque_lsa_refresh_timer(struct thread *t);
1653
1654void ospf_opaque_lsa_reoriginate_schedule(void *lsa_type_dependent,
1655 u_char lsa_type, u_char opaque_type)
1656{
b5a8894d 1657 struct ospf *top = NULL;
d62a17ae 1658 struct ospf_area dummy, *area = NULL;
1659 struct ospf_interface *oi = NULL;
1660
1661 struct ospf_lsa *lsa;
1662 struct opaque_info_per_type *oipt;
1663 int (*func)(struct thread * t) = NULL;
1664 int delay;
1665
1666 switch (lsa_type) {
1667 case OSPF_OPAQUE_LINK_LSA:
1668 if ((oi = (struct ospf_interface *)lsa_type_dependent)
1669 == NULL) {
1670 zlog_warn(
1671 "ospf_opaque_lsa_reoriginate_schedule:"
1672 " Type-9 Opaque-LSA: Invalid parameter?");
1673 goto out;
1674 }
1675 if ((top = oi_to_top(oi)) == NULL) {
1676 zlog_warn(
1677 "ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1678 IF_NAME(oi));
1679 goto out;
1680 }
1681 if (!list_isempty(ospf_opaque_type9_funclist)
1682 && list_isempty(oi->opaque_lsa_self)
1683 && oi->t_opaque_lsa_self != NULL) {
1684 zlog_warn(
1685 "Type-9 Opaque-LSA (opaque_type=%u):"
1686 " Common origination for OI(%s) has already started",
1687 opaque_type, IF_NAME(oi));
1688 goto out;
1689 }
1690 func = ospf_opaque_type9_lsa_reoriginate_timer;
1691 break;
1692 case OSPF_OPAQUE_AREA_LSA:
1693 if ((area = (struct ospf_area *)lsa_type_dependent) == NULL) {
1694 zlog_warn(
1695 "ospf_opaque_lsa_reoriginate_schedule:"
1696 " Type-10 Opaque-LSA: Invalid parameter?");
1697 goto out;
1698 }
1699 if ((top = area->ospf) == NULL) {
1700 zlog_warn(
1701 "ospf_opaque_lsa_reoriginate_schedule:"
1702 " AREA(%s) -> TOP?",
1703 inet_ntoa(area->area_id));
1704 goto out;
1705 }
1706 if (!list_isempty(ospf_opaque_type10_funclist)
1707 && list_isempty(area->opaque_lsa_self)
1708 && area->t_opaque_lsa_self != NULL) {
1709 zlog_warn(
1710 "Type-10 Opaque-LSA (opaque_type=%u):"
1711 " Common origination for AREA(%s) has already started",
1712 opaque_type, inet_ntoa(area->area_id));
1713 goto out;
1714 }
1715 func = ospf_opaque_type10_lsa_reoriginate_timer;
1716 break;
1717 case OSPF_OPAQUE_AS_LSA:
1718 if ((top = (struct ospf *)lsa_type_dependent) == NULL) {
1719 zlog_warn(
1720 "ospf_opaque_lsa_reoriginate_schedule:"
1721 " Type-11 Opaque-LSA: Invalid parameter?");
1722 goto out;
1723 }
1724 if (!list_isempty(ospf_opaque_type11_funclist)
1725 && list_isempty(top->opaque_lsa_self)
1726 && top->t_opaque_lsa_self != NULL) {
1727 zlog_warn(
1728 "Type-11 Opaque-LSA (opaque_type=%u):"
1729 " Common origination has already started",
1730 opaque_type);
1731 goto out;
1732 }
1733
1734 /* Fake "area" to pass "ospf" to a lookup function later. */
1735 dummy.ospf = top;
1736 area = &dummy;
1737
1738 func = ospf_opaque_type11_lsa_reoriginate_timer;
1739 break;
1740 default:
1741 zlog_warn(
1742 "ospf_opaque_lsa_reoriginate_schedule:"
1743 " Unexpected LSA-type(%u)",
1744 lsa_type);
1745 goto out;
1746 }
1747
1748 /* It may not a right time to schedule reorigination now. */
1749 if (!CHECK_FLAG(top->opaque, OPAQUE_OPERATION_READY_BIT)) {
1750 if (IS_DEBUG_OSPF_EVENT)
1751 zlog_debug(
1752 "ospf_opaque_lsa_reoriginate_schedule: Not operational.");
1753 goto out; /* This is not an error. */
1754 }
1755
1756 /* Generate a dummy lsa to be passed for a lookup function. */
1757 lsa = pseudo_lsa(oi, area, lsa_type, opaque_type);
b5a8894d 1758 lsa->vrf_id = top->vrf_id;
d62a17ae 1759
1760 if ((oipt = lookup_opaque_info_by_type(lsa)) == NULL) {
1761 struct ospf_opaque_functab *functab;
1762 if ((functab = ospf_opaque_functab_lookup(lsa)) == NULL) {
1763 zlog_warn(
1764 "ospf_opaque_lsa_reoriginate_schedule:"
1765 " No associated function?: lsa_type(%u),"
1766 " opaque_type(%u)",
1767 lsa_type, opaque_type);
1768 goto out;
1769 }
1770 if ((oipt = register_opaque_info_per_type(functab, lsa))
1771 == NULL) {
1772 zlog_warn(
1773 "ospf_opaque_lsa_reoriginate_schedule:"
1774 " Cannot get a control info?: lsa_type(%u),"
1775 " opaque_type(%u)",
1776 lsa_type, opaque_type);
1777 goto out;
1778 }
1779 }
1780
1781 if (oipt->t_opaque_lsa_self != NULL) {
1782 if (IS_DEBUG_OSPF_EVENT)
1783 zlog_debug(
1784 "Type-%u Opaque-LSA has already scheduled to"
1785 " RE-ORIGINATE: [opaque-type=%u]",
1786 lsa_type,
1787 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)));
1788 goto out;
1789 }
1790
1791 /*
1792 * Different from initial origination time, in which various conditions
1793 * (opaque capability, neighbor status etc) are assured by caller of
1794 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1795 * it is highly possible that these conditions might not be satisfied
1796 * at the time of re-origination function is to be called.
1797 */
1798 delay = top->min_ls_interval; /* XXX */
1799
1800 if (IS_DEBUG_OSPF_EVENT)
1801 zlog_debug(
1802 "Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
1803 " ms later: [opaque-type=%u]",
1804 lsa_type, delay,
1805 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)));
1806
1807 OSPF_OPAQUE_TIMER_ON(oipt->t_opaque_lsa_self, func, oipt, delay * 1000);
718e3744 1808
1809out:
d62a17ae 1810 return;
1811}
1812
1813static struct ospf_lsa *pseudo_lsa(struct ospf_interface *oi,
1814 struct ospf_area *area, u_char lsa_type,
1815 u_char opaque_type)
1816{
1817 static struct ospf_lsa lsa = {0};
1818 static struct lsa_header lsah = {0};
1819 u_int32_t tmp;
1820
1821 lsa.oi = oi;
1822 lsa.area = area;
1823 lsa.data = &lsah;
b5a8894d 1824 lsa.vrf_id = VRF_DEFAULT;
d62a17ae 1825
1826 lsah.type = lsa_type;
1827 tmp = SET_OPAQUE_LSID(opaque_type, 0); /* Opaque-ID is unused here. */
1828 lsah.id.s_addr = htonl(tmp);
1829
1830 return &lsa;
1831}
1832
1833static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread *t)
1834{
1835 struct opaque_info_per_type *oipt;
1836 struct ospf_opaque_functab *functab;
1837 struct ospf *top;
1838 struct ospf_interface *oi;
1839 int rc = -1;
1840
1841 oipt = THREAD_ARG(t);
1842 oipt->t_opaque_lsa_self = NULL;
1843
1844 if ((functab = oipt->functab) == NULL
1845 || functab->lsa_originator == NULL) {
1846 zlog_warn(
1847 "ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1848 goto out;
1849 }
1850
1851 oi = (struct ospf_interface *)oipt->owner;
1852 if ((top = oi_to_top(oi)) == NULL) {
1853 zlog_warn(
1854 "ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1855 goto out;
1856 }
1857
1858 if (!CHECK_FLAG(top->config, OSPF_OPAQUE_CAPABLE)
1859 || !ospf_if_is_enable(oi)
1860 || ospf_nbr_count_opaque_capable(oi) == 0) {
1861 if (IS_DEBUG_OSPF_EVENT)
1862 zlog_debug(
1863 "Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...",
1864 oipt->opaque_type);
1865
1866 oipt->status = PROC_SUSPEND;
1867 rc = 0;
1868 goto out;
1869 }
1870
1871 if (IS_DEBUG_OSPF_EVENT)
1872 zlog_debug(
1873 "Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)",
1874 oipt->opaque_type, IF_NAME(oi));
1875
1876 rc = (*functab->lsa_originator)(oi);
718e3744 1877out:
d62a17ae 1878 return rc;
1879}
1880
1881static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread *t)
1882{
1883 struct opaque_info_per_type *oipt;
1884 struct ospf_opaque_functab *functab;
1885 struct listnode *node, *nnode;
1886 struct ospf *top;
1887 struct ospf_area *area;
1888 struct ospf_interface *oi;
1889 int n, rc = -1;
1890
1891 oipt = THREAD_ARG(t);
1892 oipt->t_opaque_lsa_self = NULL;
1893
1894 if ((functab = oipt->functab) == NULL
1895 || functab->lsa_originator == NULL) {
1896 zlog_warn(
1897 "ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1898 goto out;
1899 }
1900
1901 area = (struct ospf_area *)oipt->owner;
1902 if (area == NULL || (top = area->ospf) == NULL) {
1903 zlog_warn(
1904 "ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1905 goto out;
1906 }
1907
1908 /* There must be at least one "opaque-capable, full-state" neighbor. */
1909 n = 0;
1910 for (ALL_LIST_ELEMENTS(area->oiflist, node, nnode, oi)) {
1911 if ((n = ospf_nbr_count_opaque_capable(oi)) > 0)
1912 break;
1913 }
1914
1915 if (n == 0 || !CHECK_FLAG(top->config, OSPF_OPAQUE_CAPABLE)) {
1916 if (IS_DEBUG_OSPF_EVENT)
1917 zlog_debug(
1918 "Suspend re-origination of Type-10 Opaque-LSAs"
1919 " (opaque-type=%u) for a while...",
1920 oipt->opaque_type);
1921
1922 oipt->status = PROC_SUSPEND;
1923 rc = 0;
1924 goto out;
1925 }
1926
1927 if (IS_DEBUG_OSPF_EVENT)
1928 zlog_debug(
1929 "Timer[Type10-LSA]: Re-originate Opaque-LSAs"
1930 " (opaque-type=%u) for Area %s",
1931 oipt->opaque_type, inet_ntoa(area->area_id));
1932
1933 rc = (*functab->lsa_originator)(area);
718e3744 1934out:
d62a17ae 1935 return rc;
1936}
1937
1938static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread *t)
1939{
1940 struct opaque_info_per_type *oipt;
1941 struct ospf_opaque_functab *functab;
1942 struct ospf *top;
1943 int rc = -1;
1944
1945 oipt = THREAD_ARG(t);
1946 oipt->t_opaque_lsa_self = NULL;
1947
1948 if ((functab = oipt->functab) == NULL
1949 || functab->lsa_originator == NULL) {
1950 zlog_warn(
1951 "ospf_opaque_type11_lsa_reoriginate_timer:"
1952 " No associated function?");
1953 goto out;
1954 }
1955
1956 if ((top = (struct ospf *)oipt->owner) == NULL) {
1957 zlog_warn(
1958 "ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1959 goto out;
1960 }
1961
1962 if (!CHECK_FLAG(top->config, OSPF_OPAQUE_CAPABLE)) {
1963 if (IS_DEBUG_OSPF_EVENT)
1964 zlog_debug(
1965 "Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...",
1966 oipt->opaque_type);
1967
1968 oipt->status = PROC_SUSPEND;
1969 rc = 0;
1970 goto out;
1971 }
1972
1973 if (IS_DEBUG_OSPF_EVENT)
1974 zlog_debug(
1975 "Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).",
1976 oipt->opaque_type);
1977
1978 rc = (*functab->lsa_originator)(top);
718e3744 1979out:
d62a17ae 1980 return rc;
1981}
1982
1983void ospf_opaque_lsa_refresh_schedule(struct ospf_lsa *lsa0)
1984{
1985 struct opaque_info_per_type *oipt;
1986 struct opaque_info_per_id *oipi;
1987 struct ospf_lsa *lsa;
1988 struct ospf *top;
1989 int delay;
1990
1991 if ((oipt = lookup_opaque_info_by_type(lsa0)) == NULL
1992 || (oipi = lookup_opaque_info_by_id(oipt, lsa0)) == NULL) {
1993 zlog_warn(
1994 "ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
1995 goto out;
1996 }
1997
1998 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
1999 if ((lsa = oipi->lsa) == NULL) {
2000 zlog_warn("ospf_opaque_lsa_refresh_schedule: Something wrong?");
2001 goto out;
2002 }
2003
2004 if (oipi->t_opaque_lsa_self != NULL) {
2005 if (IS_DEBUG_OSPF_EVENT)
2006 zlog_debug(
2007 "Type-%u Opaque-LSA has already scheduled to REFRESH: [opaque-type=%u, opaque-id=%x]",
2008 lsa->data->type,
2009 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)),
2010 GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)));
2011 goto out;
2012 }
2013
2014 /* Delete this lsa from neighbor retransmit-list. */
2015 switch (lsa->data->type) {
2016 case OSPF_OPAQUE_LINK_LSA:
2017 case OSPF_OPAQUE_AREA_LSA:
2018 ospf_ls_retransmit_delete_nbr_area(lsa->area, lsa);
2019 break;
2020 case OSPF_OPAQUE_AS_LSA:
b5a8894d 2021 top = ospf_lookup_by_vrf_id(lsa0->vrf_id);
d62a17ae 2022 if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
2023 top = lsa0->area->ospf;
2024 ospf_ls_retransmit_delete_nbr_as(top, lsa);
2025 break;
2026 default:
2027 zlog_warn(
2028 "ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)",
2029 lsa->data->type);
2030 goto out;
2031 }
2032
2033 delay = ospf_lsa_refresh_delay(lsa);
2034
2035 if (IS_DEBUG_OSPF_EVENT)
2036 zlog_debug(
2037 "Schedule Type-%u Opaque-LSA to REFRESH in %d sec later: [opaque-type=%u, opaque-id=%x]",
2038 lsa->data->type, delay,
2039 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)),
2040 GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)));
2041
2042 OSPF_OPAQUE_TIMER_ON(oipi->t_opaque_lsa_self,
2043 ospf_opaque_lsa_refresh_timer, oipi, delay * 1000);
718e3744 2044out:
d62a17ae 2045 return;
718e3744 2046}
2047
d62a17ae 2048static int ospf_opaque_lsa_refresh_timer(struct thread *t)
718e3744 2049{
d62a17ae 2050 struct opaque_info_per_id *oipi;
2051 struct ospf_opaque_functab *functab;
2052 struct ospf_lsa *lsa;
718e3744 2053
d62a17ae 2054 if (IS_DEBUG_OSPF_EVENT)
2055 zlog_debug("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
718e3744 2056
d62a17ae 2057 oipi = THREAD_ARG(t);
2058 oipi->t_opaque_lsa_self = NULL;
718e3744 2059
d62a17ae 2060 if ((lsa = oipi->lsa) != NULL)
2061 if ((functab = oipi->opqctl_type->functab) != NULL)
2062 if (functab->lsa_refresher != NULL)
2063 (*functab->lsa_refresher)(lsa);
718e3744 2064
d62a17ae 2065 return 0;
718e3744 2066}
2067
d62a17ae 2068void ospf_opaque_lsa_flush_schedule(struct ospf_lsa *lsa0)
718e3744 2069{
d62a17ae 2070 struct opaque_info_per_type *oipt;
2071 struct opaque_info_per_id *oipi;
2072 struct ospf_lsa *lsa;
2073 struct ospf *top;
16f1b9ee 2074
b5a8894d 2075 top = ospf_lookup_by_vrf_id(lsa0->vrf_id);
718e3744 2076
d62a17ae 2077 if ((oipt = lookup_opaque_info_by_type(lsa0)) == NULL
2078 || (oipi = lookup_opaque_info_by_id(oipt, lsa0)) == NULL) {
2079 zlog_warn("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
2080 goto out;
2081 }
718e3744 2082
d62a17ae 2083 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2084 if ((lsa = oipi->lsa) == NULL) {
2085 zlog_warn("ospf_opaque_lsa_flush_schedule: Something wrong?");
2086 goto out;
2087 }
718e3744 2088
d62a17ae 2089 /* Delete this lsa from neighbor retransmit-list. */
2090 switch (lsa->data->type) {
2091 case OSPF_OPAQUE_LINK_LSA:
2092 case OSPF_OPAQUE_AREA_LSA:
2093 ospf_ls_retransmit_delete_nbr_area(lsa->area, lsa);
2094 break;
2095 case OSPF_OPAQUE_AS_LSA:
2096 if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
2097 top = lsa0->area->ospf;
2098 ospf_ls_retransmit_delete_nbr_as(top, lsa);
2099 break;
2100 default:
2101 zlog_warn(
2102 "ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)",
2103 lsa->data->type);
2104 goto out;
2105 }
718e3744 2106
d62a17ae 2107 /* Dequeue listnode entry from the list. */
2108 listnode_delete(oipt->id_list, oipi);
718e3744 2109
d62a17ae 2110 /* Avoid misjudgement in the next lookup. */
2111 if (listcount(oipt->id_list) == 0)
2112 oipt->id_list->head = oipt->id_list->tail = NULL;
718e3744 2113
d62a17ae 2114 /* Disassociate internal control information with the given lsa. */
2115 free_opaque_info_per_id((void *)oipi);
718e3744 2116
d62a17ae 2117 /* Force given lsa's age to MaxAge. */
2118 lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
718e3744 2119
d62a17ae 2120 if (IS_DEBUG_OSPF_EVENT)
2121 zlog_debug(
2122 "Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]",
2123 lsa->data->type,
2124 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)),
2125 GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)));
718e3744 2126
d62a17ae 2127 /* This lsa will be flushed and removed eventually. */
2128 ospf_lsa_flush(top, lsa);
718e3744 2129
2130out:
d62a17ae 2131 return;
2132}
2133
2134void ospf_opaque_self_originated_lsa_received(struct ospf_neighbor *nbr,
2135 struct ospf_lsa *lsa)
2136{
2137 struct ospf *top;
2138
2139 if ((top = oi_to_top(nbr->oi)) == NULL)
2140 return;
2141
2142 /*
2143 * Since these LSA entries are not yet installed into corresponding
2144 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2145 */
2146 lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
2147 switch (lsa->data->type) {
2148 case OSPF_OPAQUE_LINK_LSA:
2149 ospf_flood_through_area(nbr->oi->area, NULL /*inbr*/, lsa);
2150 break;
2151 case OSPF_OPAQUE_AREA_LSA:
2152 ospf_flood_through_area(nbr->oi->area, NULL /*inbr*/, lsa);
2153 break;
2154 case OSPF_OPAQUE_AS_LSA:
2155 ospf_flood_through_as(top, NULL /*inbr*/, lsa);
2156 break;
2157 default:
2158 zlog_warn(
2159 "ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)",
2160 lsa->data->type);
2161 return;
2162 }
2163 ospf_lsa_discard(lsa); /* List "lsas" will be deleted by caller. */
718e3744 2164}
2165
2166/*------------------------------------------------------------------------*
2167 * Followings are util functions; probably be used by Opaque-LSAs only...
2168 *------------------------------------------------------------------------*/
2169
d62a17ae 2170struct ospf *oi_to_top(struct ospf_interface *oi)
718e3744 2171{
d62a17ae 2172 struct ospf *top = NULL;
2173 struct ospf_area *area;
718e3744 2174
d62a17ae 2175 if (oi == NULL || (area = oi->area) == NULL
2176 || (top = area->ospf) == NULL)
2177 zlog_warn("Broken relationship for \"OI -> AREA -> OSPF\"?");
718e3744 2178
d62a17ae 2179 return top;
718e3744 2180}