]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_opaque.c
Merge pull request #9324 from donaldsharp/bgp_info_cmp
[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
bf8d3d6a
DL
59DEFINE_MTYPE_STATIC(OSPFD, OSPF_OPAQUE_FUNCTAB, "OSPF opaque function table");
60DEFINE_MTYPE_STATIC(OSPFD, OPAQUE_INFO_PER_TYPE, "OSPF opaque per-type info");
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{
8db278b5 1207 struct ospf_lsa lsa = {};
718e3744 1208
2d34fb80 1209 lsa.data = (struct lsa_header *)stream_pnt(s);
8db278b5 1210 lsa.size = length;
f328dc60 1211 show_opaque_info_detail(NULL, &lsa, NULL);
d62a17ae 1212 return;
718e3744 1213}
1214
d62a17ae 1215static int ospf_opaque_lsa_install_hook(struct ospf_lsa *lsa)
718e3744 1216{
d62a17ae 1217 struct list *funclist;
1218 int rc = -1;
718e3744 1219
d62a17ae 1220 /*
1221 * Some Opaque-LSA user may want to monitor every LSA installation
1222 * into the LSDB, regardless with target LSA type.
1223 */
1224 funclist = ospf_opaque_wildcard_funclist;
1225 if (new_lsa_callback(funclist, lsa) != 0)
1226 goto out;
09e4efdc 1227
d62a17ae 1228 funclist = ospf_opaque_type9_funclist;
1229 if (new_lsa_callback(funclist, lsa) != 0)
1230 goto out;
718e3744 1231
d62a17ae 1232 funclist = ospf_opaque_type10_funclist;
1233 if (new_lsa_callback(funclist, lsa) != 0)
1234 goto out;
718e3744 1235
d62a17ae 1236 funclist = ospf_opaque_type11_funclist;
1237 if (new_lsa_callback(funclist, lsa) != 0)
1238 goto out;
718e3744 1239
d62a17ae 1240 rc = 0;
718e3744 1241out:
d62a17ae 1242 return rc;
718e3744 1243}
1244
d62a17ae 1245static int ospf_opaque_lsa_delete_hook(struct ospf_lsa *lsa)
718e3744 1246{
d62a17ae 1247 struct list *funclist;
1248 int rc = -1;
718e3744 1249
d62a17ae 1250 /*
1251 * Some Opaque-LSA user may want to monitor every LSA deletion
1252 * from the LSDB, regardless with target LSA type.
1253 */
1254 funclist = ospf_opaque_wildcard_funclist;
1255 if (del_lsa_callback(funclist, lsa) != 0)
1256 goto out;
09e4efdc 1257
d62a17ae 1258 funclist = ospf_opaque_type9_funclist;
1259 if (del_lsa_callback(funclist, lsa) != 0)
1260 goto out;
718e3744 1261
d62a17ae 1262 funclist = ospf_opaque_type10_funclist;
1263 if (del_lsa_callback(funclist, lsa) != 0)
1264 goto out;
718e3744 1265
d62a17ae 1266 funclist = ospf_opaque_type11_funclist;
1267 if (del_lsa_callback(funclist, lsa) != 0)
1268 goto out;
718e3744 1269
d62a17ae 1270 rc = 0;
718e3744 1271out:
d62a17ae 1272 return rc;
718e3744 1273}
1274
1275/*------------------------------------------------------------------------*
1276 * Followings are Opaque-LSA origination/refresh management functions.
1277 *------------------------------------------------------------------------*/
1278
d62a17ae 1279static int ospf_opaque_type9_lsa_originate(struct thread *t);
1280static int ospf_opaque_type10_lsa_originate(struct thread *t);
1281static int ospf_opaque_type11_lsa_originate(struct thread *t);
1282static void ospf_opaque_lsa_reoriginate_resume(struct list *listtop, void *arg);
1283
1284void ospf_opaque_lsa_originate_schedule(struct ospf_interface *oi, int *delay0)
1285{
1286 struct ospf *top;
1287 struct ospf_area *area;
1288 struct listnode *node, *nnode;
1289 struct opaque_info_per_type *oipt;
1290 int delay = 0;
1291
1292 if ((top = oi_to_top(oi)) == NULL || (area = oi->area) == NULL) {
34f74c7a
DS
1293 if (IS_DEBUG_OSPF_EVENT)
1294 zlog_debug(
1295 "ospf_opaque_lsa_originate_schedule: Invalid argument?");
1296 return;
d62a17ae 1297 }
1298
1299 /* It may not a right time to schedule origination now. */
1300 if (!CHECK_FLAG(top->opaque, OPAQUE_OPERATION_READY_BIT)) {
1301 if (IS_DEBUG_OSPF_EVENT)
1302 zlog_debug(
1303 "ospf_opaque_lsa_originate_schedule: Not operational.");
34f74c7a 1304 return; /* This is not an error. */
d62a17ae 1305 }
1306
1307 if (delay0 != NULL)
1308 delay = *delay0;
1309
1310 /*
1311 * There might be some entries that have been waiting for triggering
1312 * of per opaque-type re-origination get resumed.
1313 */
1314 ospf_opaque_lsa_reoriginate_resume(oi->opaque_lsa_self, (void *)oi);
1315 ospf_opaque_lsa_reoriginate_resume(area->opaque_lsa_self, (void *)area);
1316 ospf_opaque_lsa_reoriginate_resume(top->opaque_lsa_self, (void *)top);
1317
1318 /*
1319 * Now, schedule origination of all Opaque-LSAs per opaque-type.
1320 */
1321 if (!list_isempty(ospf_opaque_type9_funclist)
1322 && list_isempty(oi->opaque_lsa_self)
1323 && oi->t_opaque_lsa_self == NULL) {
1324 if (IS_DEBUG_OSPF_EVENT)
1325 zlog_debug(
1326 "Schedule Type-9 Opaque-LSA origination in %d ms later.",
1327 delay);
1328 oi->t_opaque_lsa_self = NULL;
1329 thread_add_timer_msec(master, ospf_opaque_type9_lsa_originate,
1330 oi, delay, &oi->t_opaque_lsa_self);
1331 delay += top->min_ls_interval;
1332 }
1333
1334 if (!list_isempty(ospf_opaque_type10_funclist)
1335 && list_isempty(area->opaque_lsa_self)
1336 && area->t_opaque_lsa_self == NULL) {
1337 /*
1338 * One AREA may contain multiple OIs, but above 2nd and 3rd
1339 * conditions prevent from scheduling the originate function
1340 * again and again.
1341 */
1342 if (IS_DEBUG_OSPF_EVENT)
1343 zlog_debug(
1344 "Schedule Type-10 Opaque-LSA origination in %d ms later.",
1345 delay);
1346 area->t_opaque_lsa_self = NULL;
1347 thread_add_timer_msec(master, ospf_opaque_type10_lsa_originate,
1348 area, delay, &area->t_opaque_lsa_self);
1349 delay += top->min_ls_interval;
1350 }
1351
1352 if (!list_isempty(ospf_opaque_type11_funclist)
1353 && list_isempty(top->opaque_lsa_self)
1354 && top->t_opaque_lsa_self == NULL) {
1355 /*
1356 * One OSPF may contain multiple AREAs, but above 2nd and 3rd
1357 * conditions prevent from scheduling the originate function
1358 * again and again.
1359 */
1360 if (IS_DEBUG_OSPF_EVENT)
1361 zlog_debug(
1362 "Schedule Type-11 Opaque-LSA origination in %d ms later.",
1363 delay);
1364 top->t_opaque_lsa_self = NULL;
1365 thread_add_timer_msec(master, ospf_opaque_type11_lsa_originate,
1366 top, delay, &top->t_opaque_lsa_self);
1367 delay += top->min_ls_interval;
1368 }
1369
1370 /*
1371 * Following section treats a special situation that this node's
1372 * opaque capability has changed as "ON -> OFF -> ON".
1373 */
1374 if (!list_isempty(ospf_opaque_type9_funclist)
1375 && !list_isempty(oi->opaque_lsa_self)) {
1376 for (ALL_LIST_ELEMENTS(oi->opaque_lsa_self, node, nnode,
1377 oipt)) {
1378 /*
1379 * removed the test for
1380 * (! list_isempty (oipt->id_list)) * Handler is
1381 * already active. *
1382 * because opaque cababilities ON -> OFF -> ON result in
1383 * list_isempty (oipt->id_list)
1384 * not being empty.
1385 */
996c9314
LB
1386 if (oipt->t_opaque_lsa_self
1387 != NULL /* Waiting for a thread call. */
1388 || oipt->status == PROC_SUSPEND) /* Cannot
1389 originate
1390 now. */
d62a17ae 1391 continue;
1392
1393 ospf_opaque_lsa_reoriginate_schedule(
1394 (void *)oi, OSPF_OPAQUE_LINK_LSA,
1395 oipt->opaque_type);
1396 }
1397 }
1398
1399 if (!list_isempty(ospf_opaque_type10_funclist)
1400 && !list_isempty(area->opaque_lsa_self)) {
1401 for (ALL_LIST_ELEMENTS(area->opaque_lsa_self, node, nnode,
1402 oipt)) {
1403 /*
1404 * removed the test for
1405 * (! list_isempty (oipt->id_list)) * Handler is
1406 * already active. *
1407 * because opaque cababilities ON -> OFF -> ON result in
1408 * list_isempty (oipt->id_list)
1409 * not being empty.
1410 */
996c9314
LB
1411 if (oipt->t_opaque_lsa_self
1412 != NULL /* Waiting for a thread call. */
1413 || oipt->status == PROC_SUSPEND) /* Cannot
1414 originate
1415 now. */
d62a17ae 1416 continue;
1417
1418 ospf_opaque_lsa_reoriginate_schedule(
1419 (void *)area, OSPF_OPAQUE_AREA_LSA,
1420 oipt->opaque_type);
1421 }
1422 }
1423
1424 if (!list_isempty(ospf_opaque_type11_funclist)
1425 && !list_isempty(top->opaque_lsa_self)) {
1426 for (ALL_LIST_ELEMENTS(top->opaque_lsa_self, node, nnode,
1427 oipt)) {
1428 /*
1429 * removed the test for
1430 * (! list_isempty (oipt->id_list)) * Handler is
1431 * already active. *
1432 * because opaque cababilities ON -> OFF -> ON result in
1433 * list_isempty (oipt->id_list)
1434 * not being empty.
1435 */
996c9314
LB
1436 if (oipt->t_opaque_lsa_self
1437 != NULL /* Waiting for a thread call. */
1438 || oipt->status == PROC_SUSPEND) /* Cannot
1439 originate
1440 now. */
d62a17ae 1441 continue;
1442
1443 ospf_opaque_lsa_reoriginate_schedule((void *)top,
1444 OSPF_OPAQUE_AS_LSA,
1445 oipt->opaque_type);
1446 }
1447 }
1448
1449 if (delay0 != NULL)
1450 *delay0 = delay;
718e3744 1451}
1452
d62a17ae 1453static int ospf_opaque_type9_lsa_originate(struct thread *t)
718e3744 1454{
d62a17ae 1455 struct ospf_interface *oi;
1456 int rc;
718e3744 1457
d62a17ae 1458 oi = THREAD_ARG(t);
1459 oi->t_opaque_lsa_self = NULL;
718e3744 1460
d62a17ae 1461 if (IS_DEBUG_OSPF_EVENT)
1462 zlog_debug("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
1463 IF_NAME(oi));
718e3744 1464
d62a17ae 1465 rc = opaque_lsa_originate_callback(ospf_opaque_type9_funclist, oi);
718e3744 1466
d62a17ae 1467 return rc;
718e3744 1468}
1469
d62a17ae 1470static int ospf_opaque_type10_lsa_originate(struct thread *t)
718e3744 1471{
d62a17ae 1472 struct ospf_area *area;
1473 int rc;
718e3744 1474
d62a17ae 1475 area = THREAD_ARG(t);
1476 area->t_opaque_lsa_self = NULL;
718e3744 1477
d62a17ae 1478 if (IS_DEBUG_OSPF_EVENT)
1479 zlog_debug(
96b663a3
MS
1480 "Timer[Type10-LSA]: Originate Opaque-LSAs for Area %pI4",
1481 &area->area_id);
718e3744 1482
d62a17ae 1483 rc = opaque_lsa_originate_callback(ospf_opaque_type10_funclist, area);
718e3744 1484
d62a17ae 1485 return rc;
718e3744 1486}
1487
d62a17ae 1488static int ospf_opaque_type11_lsa_originate(struct thread *t)
718e3744 1489{
d62a17ae 1490 struct ospf *top;
1491 int rc;
718e3744 1492
d62a17ae 1493 top = THREAD_ARG(t);
1494 top->t_opaque_lsa_self = NULL;
718e3744 1495
d62a17ae 1496 if (IS_DEBUG_OSPF_EVENT)
1497 zlog_debug(
1498 "Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
718e3744 1499
d62a17ae 1500 rc = opaque_lsa_originate_callback(ospf_opaque_type11_funclist, top);
718e3744 1501
d62a17ae 1502 return rc;
718e3744 1503}
1504
d62a17ae 1505static void ospf_opaque_lsa_reoriginate_resume(struct list *listtop, void *arg)
718e3744 1506{
d62a17ae 1507 struct listnode *node, *nnode;
1508 struct opaque_info_per_type *oipt;
1509 struct ospf_opaque_functab *functab;
718e3744 1510
d62a17ae 1511 if (listtop == NULL)
1512 goto out;
718e3744 1513
d62a17ae 1514 /*
1515 * Pickup oipt entries those which in SUSPEND status, and give
1516 * them a chance to start re-origination now.
1517 */
1518 for (ALL_LIST_ELEMENTS(listtop, node, nnode, oipt)) {
1519 if (oipt->status != PROC_SUSPEND)
1520 continue;
718e3744 1521
d62a17ae 1522 oipt->status = PROC_NORMAL;
718e3744 1523
d62a17ae 1524 if ((functab = oipt->functab) == NULL
1525 || functab->lsa_originator == NULL)
1526 continue;
718e3744 1527
d62a17ae 1528 if ((*functab->lsa_originator)(arg) != 0) {
34f74c7a 1529 flog_warn(
cf444bcf 1530 EC_OSPF_LSA,
d62a17ae 1531 "ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)",
1532 oipt->opaque_type);
1533 continue;
1534 }
1535 }
718e3744 1536
1537out:
d62a17ae 1538 return;
1539}
1540
1541struct ospf_lsa *ospf_opaque_lsa_install(struct ospf_lsa *lsa, int rt_recalc)
1542{
1543 struct ospf_lsa *new = NULL;
1544 struct opaque_info_per_type *oipt;
1545 struct opaque_info_per_id *oipi;
1546 struct ospf *top;
1547
1548 /* Don't take "rt_recalc" into consideration for now. */ /* XXX */
1549
1550 if (!IS_LSA_SELF(lsa)) {
1551 new = lsa; /* Don't touch this LSA. */
1552 goto out;
1553 }
1554
1555 if (IS_DEBUG_OSPF(lsa, LSA_INSTALL))
1556 zlog_debug(
1557 "Install Type-%u Opaque-LSA: [opaque-type=%u, opaque-id=%x]",
1558 lsa->data->type,
1559 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)),
1560 GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)));
1561
1562 /* Replace the existing lsa with the new one. */
1563 if ((oipt = lookup_opaque_info_by_type(lsa)) != NULL
1564 && (oipi = lookup_opaque_info_by_id(oipt, lsa)) != NULL) {
1565 ospf_lsa_unlock(&oipi->lsa);
1566 oipi->lsa = ospf_lsa_lock(lsa);
1567 }
6e3e2c6d
DS
1568 /* Register the new lsa entry */
1569 else if (register_opaque_lsa(lsa) == NULL) {
cf444bcf 1570 flog_warn(EC_OSPF_LSA,
34f74c7a 1571 "ospf_opaque_lsa_install: register_opaque_lsa() ?");
d62a17ae 1572 goto out;
1573 }
1574
1575 /*
1576 * Make use of a common mechanism (ospf_lsa_refresh_walker)
1577 * for periodic refresh of self-originated Opaque-LSAs.
1578 */
1579 switch (lsa->data->type) {
1580 case OSPF_OPAQUE_LINK_LSA:
1581 if ((top = oi_to_top(lsa->oi)) == NULL) {
1582 /* Above conditions must have passed. */
cf444bcf 1583 flog_warn(EC_OSPF_LSA,
34f74c7a 1584 "ospf_opaque_lsa_install: Something wrong?");
d62a17ae 1585 goto out;
1586 }
1587 break;
1588 case OSPF_OPAQUE_AREA_LSA:
1589 if (lsa->area == NULL || (top = lsa->area->ospf) == NULL) {
1590 /* Above conditions must have passed. */
cf444bcf 1591 flog_warn(EC_OSPF_LSA,
34f74c7a 1592 "ospf_opaque_lsa_install: Something wrong?");
d62a17ae 1593 goto out;
1594 }
1595 break;
1596 case OSPF_OPAQUE_AS_LSA:
b5a8894d 1597 top = ospf_lookup_by_vrf_id(lsa->vrf_id);
d62a17ae 1598 if (lsa->area != NULL && (top = lsa->area->ospf) == NULL) {
1599 /* Above conditions must have passed. */
cf444bcf 1600 flog_warn(EC_OSPF_LSA,
34f74c7a 1601 "ospf_opaque_lsa_install: Something wrong?");
d62a17ae 1602 goto out;
1603 }
1604 break;
1605 default:
cf444bcf 1606 flog_warn(EC_OSPF_LSA_UNEXPECTED,
34f74c7a 1607 "ospf_opaque_lsa_install: Unexpected LSA-type(%u)",
d62a17ae 1608 lsa->data->type);
1609 goto out;
1610 }
1611
1612 ospf_refresher_register_lsa(top, lsa);
1613 new = lsa;
718e3744 1614
1615out:
d62a17ae 1616 return new;
718e3744 1617}
1618
d62a17ae 1619struct ospf_lsa *ospf_opaque_lsa_refresh(struct ospf_lsa *lsa)
718e3744 1620{
d62a17ae 1621 struct ospf *ospf;
1622 struct ospf_opaque_functab *functab;
1623 struct ospf_lsa *new = NULL;
1624
b5a8894d 1625 ospf = ospf_lookup_by_vrf_id(lsa->vrf_id);
020709f9 1626
d62a17ae 1627 if ((functab = ospf_opaque_functab_lookup(lsa)) == NULL
1628 || functab->lsa_refresher == NULL) {
1629 /*
1630 * Though this LSA seems to have originated on this node, the
1631 * handling module for this "lsa-type and opaque-type" was
1632 * already deleted sometime ago.
1633 * Anyway, this node still has a responsibility to flush this
1634 * LSA from the routing domain.
1635 */
1636 if (IS_DEBUG_OSPF_EVENT)
96b663a3
MS
1637 zlog_debug("LSA[Type%d:%pI4]: Flush stray Opaque-LSA",
1638 lsa->data->type, &lsa->data->id);
718e3744 1639
d62a17ae 1640 lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
1641 ospf_lsa_flush(ospf, lsa);
1642 } else
1643 new = (*functab->lsa_refresher)(lsa);
718e3744 1644
d62a17ae 1645 return new;
718e3744 1646}
1647
1648/*------------------------------------------------------------------------*
1649 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
1650 * triggered by external interventions (vty session, signaling, etc).
1651 *------------------------------------------------------------------------*/
1652
ffa2c898 1653#define OSPF_OPAQUE_TIMER_ON(T,F,L,V) thread_add_timer_msec (master, (F), (L), (V), &(T))
718e3744 1654
d62a17ae 1655static struct ospf_lsa *pseudo_lsa(struct ospf_interface *oi,
d7c0a89a
QY
1656 struct ospf_area *area, uint8_t lsa_type,
1657 uint8_t opaque_type);
d62a17ae 1658static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread *t);
1659static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread *t);
1660static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread *t);
1661static int ospf_opaque_lsa_refresh_timer(struct thread *t);
1662
1663void ospf_opaque_lsa_reoriginate_schedule(void *lsa_type_dependent,
d7c0a89a 1664 uint8_t lsa_type, uint8_t opaque_type)
d62a17ae 1665{
b5a8894d 1666 struct ospf *top = NULL;
d62a17ae 1667 struct ospf_area dummy, *area = NULL;
1668 struct ospf_interface *oi = NULL;
1669
1670 struct ospf_lsa *lsa;
1671 struct opaque_info_per_type *oipt;
1672 int (*func)(struct thread * t) = NULL;
1673 int delay;
1674
1675 switch (lsa_type) {
1676 case OSPF_OPAQUE_LINK_LSA:
1677 if ((oi = (struct ospf_interface *)lsa_type_dependent)
1678 == NULL) {
34f74c7a 1679 flog_warn(
cf444bcf 1680 EC_OSPF_LSA,
34f74c7a 1681 "ospf_opaque_lsa_reoriginate_schedule: Type-9 Opaque-LSA: Invalid parameter?");
d62a17ae 1682 goto out;
1683 }
1684 if ((top = oi_to_top(oi)) == NULL) {
34f74c7a 1685 flog_warn(
cf444bcf 1686 EC_OSPF_LSA,
d62a17ae 1687 "ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
1688 IF_NAME(oi));
1689 goto out;
1690 }
1691 if (!list_isempty(ospf_opaque_type9_funclist)
1692 && list_isempty(oi->opaque_lsa_self)
1693 && oi->t_opaque_lsa_self != NULL) {
34f74c7a 1694 flog_warn(
cf444bcf 1695 EC_OSPF_LSA,
34f74c7a 1696 "Type-9 Opaque-LSA (opaque_type=%u): Common origination for OI(%s) has already started",
d62a17ae 1697 opaque_type, IF_NAME(oi));
1698 goto out;
1699 }
1700 func = ospf_opaque_type9_lsa_reoriginate_timer;
1701 break;
1702 case OSPF_OPAQUE_AREA_LSA:
1703 if ((area = (struct ospf_area *)lsa_type_dependent) == NULL) {
34f74c7a 1704 flog_warn(
cf444bcf 1705 EC_OSPF_LSA,
34f74c7a 1706 "ospf_opaque_lsa_reoriginate_schedule: Type-10 Opaque-LSA: Invalid parameter?");
d62a17ae 1707 goto out;
1708 }
1709 if ((top = area->ospf) == NULL) {
34f74c7a 1710 flog_warn(
cf444bcf 1711 EC_OSPF_LSA,
96b663a3
MS
1712 "ospf_opaque_lsa_reoriginate_schedule: AREA(%pI4) -> TOP?",
1713 &area->area_id);
d62a17ae 1714 goto out;
1715 }
1716 if (!list_isempty(ospf_opaque_type10_funclist)
1717 && list_isempty(area->opaque_lsa_self)
1718 && area->t_opaque_lsa_self != NULL) {
34f74c7a 1719 flog_warn(
cf444bcf 1720 EC_OSPF_LSA,
96b663a3
MS
1721 "Type-10 Opaque-LSA (opaque_type=%u): Common origination for AREA(%pI4) has already started",
1722 opaque_type, &area->area_id);
d62a17ae 1723 goto out;
1724 }
1725 func = ospf_opaque_type10_lsa_reoriginate_timer;
1726 break;
1727 case OSPF_OPAQUE_AS_LSA:
1728 if ((top = (struct ospf *)lsa_type_dependent) == NULL) {
34f74c7a 1729 flog_warn(
cf444bcf 1730 EC_OSPF_LSA,
34f74c7a 1731 "ospf_opaque_lsa_reoriginate_schedule: Type-11 Opaque-LSA: Invalid parameter?");
d62a17ae 1732 goto out;
1733 }
1734 if (!list_isempty(ospf_opaque_type11_funclist)
1735 && list_isempty(top->opaque_lsa_self)
1736 && top->t_opaque_lsa_self != NULL) {
34f74c7a 1737 flog_warn(
cf444bcf 1738 EC_OSPF_LSA,
34f74c7a 1739 "Type-11 Opaque-LSA (opaque_type=%u): Common origination has already started",
d62a17ae 1740 opaque_type);
1741 goto out;
1742 }
1743
1744 /* Fake "area" to pass "ospf" to a lookup function later. */
1745 dummy.ospf = top;
1746 area = &dummy;
1747
1748 func = ospf_opaque_type11_lsa_reoriginate_timer;
1749 break;
1750 default:
34f74c7a 1751 flog_warn(
cf444bcf 1752 EC_OSPF_LSA_UNEXPECTED,
34f74c7a 1753 "ospf_opaque_lsa_reoriginate_schedule: Unexpected LSA-type(%u)",
d62a17ae 1754 lsa_type);
1755 goto out;
1756 }
1757
1758 /* It may not a right time to schedule reorigination now. */
1759 if (!CHECK_FLAG(top->opaque, OPAQUE_OPERATION_READY_BIT)) {
1760 if (IS_DEBUG_OSPF_EVENT)
1761 zlog_debug(
1762 "ospf_opaque_lsa_reoriginate_schedule: Not operational.");
1763 goto out; /* This is not an error. */
1764 }
1765
1766 /* Generate a dummy lsa to be passed for a lookup function. */
1767 lsa = pseudo_lsa(oi, area, lsa_type, opaque_type);
b5a8894d 1768 lsa->vrf_id = top->vrf_id;
d62a17ae 1769
1770 if ((oipt = lookup_opaque_info_by_type(lsa)) == NULL) {
1771 struct ospf_opaque_functab *functab;
1772 if ((functab = ospf_opaque_functab_lookup(lsa)) == NULL) {
34f74c7a 1773 flog_warn(
cf444bcf 1774 EC_OSPF_LSA,
34f74c7a 1775 "ospf_opaque_lsa_reoriginate_schedule: No associated function?: lsa_type(%u), opaque_type(%u)",
d62a17ae 1776 lsa_type, opaque_type);
1777 goto out;
1778 }
1779 if ((oipt = register_opaque_info_per_type(functab, lsa))
1780 == NULL) {
34f74c7a 1781 flog_warn(
cf444bcf 1782 EC_OSPF_LSA,
34f74c7a 1783 "ospf_opaque_lsa_reoriginate_schedule: Cannot get a control info?: lsa_type(%u), opaque_type(%u)",
d62a17ae 1784 lsa_type, opaque_type);
1785 goto out;
1786 }
1787 }
1788
1789 if (oipt->t_opaque_lsa_self != NULL) {
1790 if (IS_DEBUG_OSPF_EVENT)
1791 zlog_debug(
3efd0893 1792 "Type-%u Opaque-LSA has already scheduled to RE-ORIGINATE: [opaque-type=%u]",
d62a17ae 1793 lsa_type,
1794 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)));
1795 goto out;
1796 }
1797
1798 /*
1799 * Different from initial origination time, in which various conditions
1800 * (opaque capability, neighbor status etc) are assured by caller of
1801 * the originating function "ospf_opaque_lsa_originate_schedule ()",
1802 * it is highly possible that these conditions might not be satisfied
1803 * at the time of re-origination function is to be called.
1804 */
1805 delay = top->min_ls_interval; /* XXX */
1806
1807 if (IS_DEBUG_OSPF_EVENT)
1808 zlog_debug(
3efd0893 1809 "Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d ms later: [opaque-type=%u]",
d62a17ae 1810 lsa_type, delay,
1811 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)));
1812
62c99790 1813 OSPF_OPAQUE_TIMER_ON(oipt->t_opaque_lsa_self, func, oipt, delay);
718e3744 1814
1815out:
d62a17ae 1816 return;
1817}
1818
1819static struct ospf_lsa *pseudo_lsa(struct ospf_interface *oi,
d7c0a89a
QY
1820 struct ospf_area *area, uint8_t lsa_type,
1821 uint8_t opaque_type)
d62a17ae 1822{
1823 static struct ospf_lsa lsa = {0};
1824 static struct lsa_header lsah = {0};
d7c0a89a 1825 uint32_t tmp;
d62a17ae 1826
1827 lsa.oi = oi;
1828 lsa.area = area;
1829 lsa.data = &lsah;
b5a8894d 1830 lsa.vrf_id = VRF_DEFAULT;
d62a17ae 1831
1832 lsah.type = lsa_type;
1833 tmp = SET_OPAQUE_LSID(opaque_type, 0); /* Opaque-ID is unused here. */
1834 lsah.id.s_addr = htonl(tmp);
1835
1836 return &lsa;
1837}
1838
1839static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread *t)
1840{
1841 struct opaque_info_per_type *oipt;
1842 struct ospf_opaque_functab *functab;
1843 struct ospf *top;
1844 struct ospf_interface *oi;
1845 int rc = -1;
1846
1847 oipt = THREAD_ARG(t);
1848 oipt->t_opaque_lsa_self = NULL;
1849
1850 if ((functab = oipt->functab) == NULL
1851 || functab->lsa_originator == NULL) {
34f74c7a 1852 flog_warn(
cf444bcf 1853 EC_OSPF_LSA,
d62a17ae 1854 "ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
1855 goto out;
1856 }
1857
1858 oi = (struct ospf_interface *)oipt->owner;
1859 if ((top = oi_to_top(oi)) == NULL) {
34f74c7a 1860 flog_warn(
cf444bcf 1861 EC_OSPF_LSA,
d62a17ae 1862 "ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
1863 goto out;
1864 }
1865
1866 if (!CHECK_FLAG(top->config, OSPF_OPAQUE_CAPABLE)
1867 || !ospf_if_is_enable(oi)
1868 || ospf_nbr_count_opaque_capable(oi) == 0) {
1869 if (IS_DEBUG_OSPF_EVENT)
1870 zlog_debug(
1871 "Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...",
1872 oipt->opaque_type);
1873
1874 oipt->status = PROC_SUSPEND;
1875 rc = 0;
1876 goto out;
1877 }
1878
1879 if (IS_DEBUG_OSPF_EVENT)
1880 zlog_debug(
1881 "Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)",
1882 oipt->opaque_type, IF_NAME(oi));
1883
1884 rc = (*functab->lsa_originator)(oi);
718e3744 1885out:
d62a17ae 1886 return rc;
1887}
1888
1889static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread *t)
1890{
1891 struct opaque_info_per_type *oipt;
1892 struct ospf_opaque_functab *functab;
1893 struct listnode *node, *nnode;
1894 struct ospf *top;
1895 struct ospf_area *area;
1896 struct ospf_interface *oi;
1897 int n, rc = -1;
1898
1899 oipt = THREAD_ARG(t);
1900 oipt->t_opaque_lsa_self = NULL;
1901
1902 if ((functab = oipt->functab) == NULL
1903 || functab->lsa_originator == NULL) {
34f74c7a 1904 flog_warn(
cf444bcf 1905 EC_OSPF_LSA,
d62a17ae 1906 "ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
1907 goto out;
1908 }
1909
1910 area = (struct ospf_area *)oipt->owner;
1911 if (area == NULL || (top = area->ospf) == NULL) {
34f74c7a 1912 flog_warn(
cf444bcf 1913 EC_OSPF_LSA,
d62a17ae 1914 "ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
1915 goto out;
1916 }
1917
1918 /* There must be at least one "opaque-capable, full-state" neighbor. */
1919 n = 0;
1920 for (ALL_LIST_ELEMENTS(area->oiflist, node, nnode, oi)) {
1921 if ((n = ospf_nbr_count_opaque_capable(oi)) > 0)
1922 break;
1923 }
1924
1925 if (n == 0 || !CHECK_FLAG(top->config, OSPF_OPAQUE_CAPABLE)) {
1926 if (IS_DEBUG_OSPF_EVENT)
1927 zlog_debug(
3efd0893 1928 "Suspend re-origination of Type-10 Opaque-LSAs (opaque-type=%u) for a while...",
d62a17ae 1929 oipt->opaque_type);
1930
1931 oipt->status = PROC_SUSPEND;
1932 rc = 0;
1933 goto out;
1934 }
1935
1936 if (IS_DEBUG_OSPF_EVENT)
1937 zlog_debug(
96b663a3
MS
1938 "Timer[Type10-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for Area %pI4",
1939 oipt->opaque_type, &area->area_id);
d62a17ae 1940
1941 rc = (*functab->lsa_originator)(area);
718e3744 1942out:
d62a17ae 1943 return rc;
1944}
1945
1946static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread *t)
1947{
1948 struct opaque_info_per_type *oipt;
1949 struct ospf_opaque_functab *functab;
1950 struct ospf *top;
1951 int rc = -1;
1952
1953 oipt = THREAD_ARG(t);
1954 oipt->t_opaque_lsa_self = NULL;
1955
1956 if ((functab = oipt->functab) == NULL
1957 || functab->lsa_originator == NULL) {
34f74c7a 1958 flog_warn(
cf444bcf 1959 EC_OSPF_LSA,
34f74c7a 1960 "ospf_opaque_type11_lsa_reoriginate_timer: No associated function?");
d62a17ae 1961 goto out;
1962 }
1963
1964 if ((top = (struct ospf *)oipt->owner) == NULL) {
34f74c7a 1965 flog_warn(
cf444bcf 1966 EC_OSPF_LSA,
d62a17ae 1967 "ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
1968 goto out;
1969 }
1970
1971 if (!CHECK_FLAG(top->config, OSPF_OPAQUE_CAPABLE)) {
1972 if (IS_DEBUG_OSPF_EVENT)
1973 zlog_debug(
1974 "Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...",
1975 oipt->opaque_type);
1976
1977 oipt->status = PROC_SUSPEND;
1978 rc = 0;
1979 goto out;
1980 }
1981
1982 if (IS_DEBUG_OSPF_EVENT)
1983 zlog_debug(
1984 "Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).",
1985 oipt->opaque_type);
1986
1987 rc = (*functab->lsa_originator)(top);
718e3744 1988out:
d62a17ae 1989 return rc;
1990}
1991
1992void ospf_opaque_lsa_refresh_schedule(struct ospf_lsa *lsa0)
1993{
1994 struct opaque_info_per_type *oipt;
1995 struct opaque_info_per_id *oipi;
1996 struct ospf_lsa *lsa;
1997 struct ospf *top;
1998 int delay;
1999
2000 if ((oipt = lookup_opaque_info_by_type(lsa0)) == NULL
2001 || (oipi = lookup_opaque_info_by_id(oipt, lsa0)) == NULL) {
34f74c7a 2002 flog_warn(
cf444bcf 2003 EC_OSPF_LSA,
d62a17ae 2004 "ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
2005 goto out;
2006 }
2007
2008 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2009 if ((lsa = oipi->lsa) == NULL) {
cf444bcf 2010 flog_warn(EC_OSPF_LSA,
34f74c7a 2011 "ospf_opaque_lsa_refresh_schedule: Something wrong?");
d62a17ae 2012 goto out;
2013 }
2014
2015 if (oipi->t_opaque_lsa_self != NULL) {
2016 if (IS_DEBUG_OSPF_EVENT)
2017 zlog_debug(
2018 "Type-%u Opaque-LSA has already scheduled to REFRESH: [opaque-type=%u, opaque-id=%x]",
2019 lsa->data->type,
2020 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)),
2021 GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)));
2022 goto out;
2023 }
2024
2025 /* Delete this lsa from neighbor retransmit-list. */
2026 switch (lsa->data->type) {
2027 case OSPF_OPAQUE_LINK_LSA:
2028 case OSPF_OPAQUE_AREA_LSA:
2029 ospf_ls_retransmit_delete_nbr_area(lsa->area, lsa);
2030 break;
2031 case OSPF_OPAQUE_AS_LSA:
b5a8894d 2032 top = ospf_lookup_by_vrf_id(lsa0->vrf_id);
d62a17ae 2033 if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
2034 top = lsa0->area->ospf;
2035 ospf_ls_retransmit_delete_nbr_as(top, lsa);
2036 break;
2037 default:
34f74c7a 2038 flog_warn(
cf444bcf 2039 EC_OSPF_LSA_UNEXPECTED,
d62a17ae 2040 "ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)",
2041 lsa->data->type);
2042 goto out;
2043 }
2044
2045 delay = ospf_lsa_refresh_delay(lsa);
2046
2047 if (IS_DEBUG_OSPF_EVENT)
2048 zlog_debug(
2049 "Schedule Type-%u Opaque-LSA to REFRESH in %d sec later: [opaque-type=%u, opaque-id=%x]",
2050 lsa->data->type, delay,
2051 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)),
2052 GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)));
2053
2054 OSPF_OPAQUE_TIMER_ON(oipi->t_opaque_lsa_self,
2055 ospf_opaque_lsa_refresh_timer, oipi, delay * 1000);
718e3744 2056out:
d62a17ae 2057 return;
718e3744 2058}
2059
d62a17ae 2060static int ospf_opaque_lsa_refresh_timer(struct thread *t)
718e3744 2061{
d62a17ae 2062 struct opaque_info_per_id *oipi;
2063 struct ospf_opaque_functab *functab;
2064 struct ospf_lsa *lsa;
718e3744 2065
d62a17ae 2066 if (IS_DEBUG_OSPF_EVENT)
2067 zlog_debug("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
718e3744 2068
d62a17ae 2069 oipi = THREAD_ARG(t);
2070 oipi->t_opaque_lsa_self = NULL;
718e3744 2071
d62a17ae 2072 if ((lsa = oipi->lsa) != NULL)
2073 if ((functab = oipi->opqctl_type->functab) != NULL)
2074 if (functab->lsa_refresher != NULL)
2075 (*functab->lsa_refresher)(lsa);
718e3744 2076
d62a17ae 2077 return 0;
718e3744 2078}
2079
d62a17ae 2080void ospf_opaque_lsa_flush_schedule(struct ospf_lsa *lsa0)
718e3744 2081{
d62a17ae 2082 struct opaque_info_per_type *oipt;
2083 struct opaque_info_per_id *oipi;
2084 struct ospf_lsa *lsa;
2085 struct ospf *top;
16f1b9ee 2086
b5a8894d 2087 top = ospf_lookup_by_vrf_id(lsa0->vrf_id);
718e3744 2088
d62a17ae 2089 if ((oipt = lookup_opaque_info_by_type(lsa0)) == NULL
2090 || (oipi = lookup_opaque_info_by_id(oipt, lsa0)) == NULL) {
cf444bcf 2091 flog_warn(EC_OSPF_LSA,
34f74c7a 2092 "ospf_opaque_lsa_flush_schedule: Invalid parameter?");
d62a17ae 2093 goto out;
2094 }
718e3744 2095
d62a17ae 2096 /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
2097 if ((lsa = oipi->lsa) == NULL) {
cf444bcf 2098 flog_warn(EC_OSPF_LSA,
34f74c7a 2099 "ospf_opaque_lsa_flush_schedule: Something wrong?");
d62a17ae 2100 goto out;
2101 }
718e3744 2102
d62a17ae 2103 /* Delete this lsa from neighbor retransmit-list. */
2104 switch (lsa->data->type) {
2105 case OSPF_OPAQUE_LINK_LSA:
2106 case OSPF_OPAQUE_AREA_LSA:
2107 ospf_ls_retransmit_delete_nbr_area(lsa->area, lsa);
2108 break;
2109 case OSPF_OPAQUE_AS_LSA:
2110 if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
2111 top = lsa0->area->ospf;
2112 ospf_ls_retransmit_delete_nbr_as(top, lsa);
2113 break;
2114 default:
34f74c7a 2115 flog_warn(
cf444bcf 2116 EC_OSPF_LSA_UNEXPECTED,
d62a17ae 2117 "ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)",
2118 lsa->data->type);
2119 goto out;
2120 }
718e3744 2121
b4a97099
RW
2122 /* This lsa will be flushed and removed eventually. */
2123 ospf_lsa_flush(top, lsa);
2124
d62a17ae 2125 /* Dequeue listnode entry from the list. */
2126 listnode_delete(oipt->id_list, oipi);
718e3744 2127
d62a17ae 2128 if (IS_DEBUG_OSPF_EVENT)
2129 zlog_debug(
2130 "Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]",
2131 lsa->data->type,
2132 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)),
2133 GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)));
718e3744 2134
b4a97099
RW
2135 /* Disassociate internal control information with the given lsa. */
2136 free_opaque_info_per_id((void *)oipi);
718e3744 2137
2138out:
d62a17ae 2139 return;
2140}
2141
2142void ospf_opaque_self_originated_lsa_received(struct ospf_neighbor *nbr,
2143 struct ospf_lsa *lsa)
2144{
2145 struct ospf *top;
2146
2147 if ((top = oi_to_top(nbr->oi)) == NULL)
2148 return;
2149
e9505bc6
RW
2150 if (IS_DEBUG_OSPF_EVENT)
2151 zlog_debug(
2152 "LSA[Type%d:%pI4]: processing self-originated Opaque-LSA",
2153 lsa->data->type, &lsa->data->id);
2154
d62a17ae 2155 /*
2156 * Since these LSA entries are not yet installed into corresponding
2157 * LSDB, just flush them without calling ospf_ls_maxage() afterward.
2158 */
2159 lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
2160 switch (lsa->data->type) {
2161 case OSPF_OPAQUE_LINK_LSA:
2162 ospf_flood_through_area(nbr->oi->area, NULL /*inbr*/, lsa);
2163 break;
2164 case OSPF_OPAQUE_AREA_LSA:
2165 ospf_flood_through_area(nbr->oi->area, NULL /*inbr*/, lsa);
2166 break;
2167 case OSPF_OPAQUE_AS_LSA:
2168 ospf_flood_through_as(top, NULL /*inbr*/, lsa);
2169 break;
2170 default:
34f74c7a 2171 flog_warn(
cf444bcf 2172 EC_OSPF_LSA_UNEXPECTED,
d62a17ae 2173 "ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)",
2174 lsa->data->type);
2175 return;
2176 }
2177 ospf_lsa_discard(lsa); /* List "lsas" will be deleted by caller. */
718e3744 2178}
2179
2180/*------------------------------------------------------------------------*
2181 * Followings are util functions; probably be used by Opaque-LSAs only...
2182 *------------------------------------------------------------------------*/
2183
d62a17ae 2184struct ospf *oi_to_top(struct ospf_interface *oi)
718e3744 2185{
d62a17ae 2186 struct ospf *top = NULL;
2187 struct ospf_area *area;
718e3744 2188
d62a17ae 2189 if (oi == NULL || (area = oi->area) == NULL
2190 || (top = area->ospf) == NULL)
cf444bcf 2191 flog_warn(EC_OSPF_LSA,
34f74c7a 2192 "Broken relationship for \"OI -> AREA -> OSPF\"?");
718e3744 2193
d62a17ae 2194 return top;
718e3744 2195}