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