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