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