Coverage Report

Created: 2025-10-23 06:55

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