~ubuntu-branches/ubuntu/warty/quagga/warty

« back to all changes in this revision

Viewing changes to ospfd/ospf_opaque.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabio M. Di Nitto
  • Date: 2004-06-29 09:50:59 UTC
  • Revision ID: james.westby@ubuntu.com-20040629095059-px1m2m108z4qw1mr
Tags: upstream-0.96.5
ImportĀ upstreamĀ versionĀ 0.96.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This is an implementation of rfc2370.
 
3
 * Copyright (C) 2001 KDD R&D Laboratories, Inc.
 
4
 * http://www.kddlabs.co.jp/
 
5
 *
 
6
 * This file is part of GNU Zebra.
 
7
 *
 
8
 * GNU Zebra is free software; you can redistribute it and/or modify it
 
9
 * under the terms of the GNU General Public License as published by the
 
10
 * Free Software Foundation; either version 2, or (at your option) any
 
11
 * later version.
 
12
 * 
 
13
 * GNU Zebra is distributed in the hope that it will be useful, but
 
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
16
 * General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU General Public License
 
19
 * along with GNU Zebra; see the file COPYING.  If not, write to the Free
 
20
 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
21
 * 02111-1307, USA.
 
22
 */
 
23
 
 
24
/***** MTYPE definitions are not reflected to "memory.h" yet. *****/
 
25
#define MTYPE_OSPF_OPAQUE_FUNCTAB       0
 
26
#define MTYPE_OPAQUE_INFO_PER_TYPE      0
 
27
#define MTYPE_OPAQUE_INFO_PER_ID        0
 
28
 
 
29
#include <zebra.h>
 
30
#ifdef HAVE_OPAQUE_LSA
 
31
 
 
32
#include "linklist.h"
 
33
#include "prefix.h"
 
34
#include "if.h"
 
35
#include "table.h"
 
36
#include "memory.h"
 
37
#include "command.h"
 
38
#include "vty.h"
 
39
#include "stream.h"
 
40
#include "log.h"
 
41
#include "thread.h"
 
42
#include "hash.h"
 
43
#include "sockunion.h"          /* for inet_aton() */
 
44
 
 
45
#include "ospfd/ospfd.h"
 
46
#include "ospfd/ospf_interface.h"
 
47
#include "ospfd/ospf_ism.h"
 
48
#include "ospfd/ospf_asbr.h"
 
49
#include "ospfd/ospf_lsa.h"
 
50
#include "ospfd/ospf_lsdb.h"
 
51
#include "ospfd/ospf_neighbor.h"
 
52
#include "ospfd/ospf_nsm.h"
 
53
#include "ospfd/ospf_flood.h"
 
54
#include "ospfd/ospf_packet.h"
 
55
#include "ospfd/ospf_spf.h"
 
56
#include "ospfd/ospf_dump.h"
 
57
#include "ospfd/ospf_route.h"
 
58
#include "ospfd/ospf_ase.h"
 
59
#include "ospfd/ospf_zebra.h"
 
60
 
 
61
/*------------------------------------------------------------------------*
 
62
 * Followings are initialize/terminate functions for Opaque-LSAs handling.
 
63
 *------------------------------------------------------------------------*/
 
64
 
 
65
#ifdef HAVE_OSPF_TE
 
66
#include "ospfd/ospf_te.h"
 
67
#endif /* HAVE_OSPF_TE */
 
68
 
 
69
#ifdef SUPPORT_OSPF_API
 
70
int ospf_apiserver_init (void);
 
71
void ospf_apiserver_term (void); 
 
72
#endif /* SUPPORT_OSPF_API */
 
73
 
 
74
static void ospf_opaque_register_vty (void);
 
75
static void ospf_opaque_funclist_init (void);
 
76
static void ospf_opaque_funclist_term (void);
 
77
static void free_opaque_info_per_type (void *val);
 
78
static void free_opaque_info_per_id (void *val);
 
79
static int ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa);
 
80
static int ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa);
 
81
 
 
82
void
 
83
ospf_opaque_init (void)
 
84
{
 
85
  ospf_opaque_register_vty ();
 
86
  ospf_opaque_funclist_init ();
 
87
 
 
88
#ifdef HAVE_OSPF_TE
 
89
  if (ospf_mpls_te_init () != 0)
 
90
    exit (1);
 
91
#endif /* HAVE_OSPF_TE */
 
92
 
 
93
#ifdef SUPPORT_OSPF_API
 
94
  if (ospf_apiserver_init () != 0)
 
95
    exit (1);
 
96
#endif /* SUPPORT_OSPF_API */
 
97
 
 
98
  return;
 
99
}
 
100
 
 
101
void
 
102
ospf_opaque_term (void)
 
103
{
 
104
#ifdef HAVE_OSPF_TE
 
105
  ospf_mpls_te_term ();
 
106
#endif /* HAVE_OSPF_TE */
 
107
 
 
108
#ifdef SUPPORT_OSPF_API
 
109
  ospf_apiserver_term ();
 
110
#endif /* SUPPORT_OSPF_API */
 
111
 
 
112
  ospf_opaque_funclist_term ();
 
113
  return;
 
114
}
 
115
 
 
116
int
 
117
ospf_opaque_type9_lsa_init (struct ospf_interface *oi)
 
118
{
 
119
  if (oi->opaque_lsa_self != NULL)
 
120
    list_delete (oi->opaque_lsa_self);
 
121
 
 
122
  oi->opaque_lsa_self = list_new ();
 
123
  oi->opaque_lsa_self->del = free_opaque_info_per_type;
 
124
  oi->t_opaque_lsa_self = NULL;
 
125
  return 0;
 
126
}
 
127
 
 
128
void
 
129
ospf_opaque_type9_lsa_term (struct ospf_interface *oi)
 
130
{
 
131
  OSPF_TIMER_OFF (oi->t_opaque_lsa_self);
 
132
  if (oi->opaque_lsa_self != NULL)
 
133
    list_delete (oi->opaque_lsa_self);
 
134
  oi->opaque_lsa_self = NULL;
 
135
  return;
 
136
}
 
137
 
 
138
int
 
139
ospf_opaque_type10_lsa_init (struct ospf_area *area)
 
140
{
 
141
  if (area->opaque_lsa_self != NULL)
 
142
    list_delete (area->opaque_lsa_self);
 
143
 
 
144
  area->opaque_lsa_self = list_new ();
 
145
  area->opaque_lsa_self->del = free_opaque_info_per_type;
 
146
  area->t_opaque_lsa_self = NULL;
 
147
 
 
148
#ifdef MONITOR_LSDB_CHANGE
 
149
  area->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
 
150
  area->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
 
151
#endif /* MONITOR_LSDB_CHANGE */
 
152
  return 0;
 
153
}
 
154
 
 
155
void
 
156
ospf_opaque_type10_lsa_term (struct ospf_area *area)
 
157
{
 
158
#ifdef MONITOR_LSDB_CHANGE
 
159
  area->lsdb->new_lsa_hook = 
 
160
  area->lsdb->del_lsa_hook = NULL;
 
161
#endif /* MONITOR_LSDB_CHANGE */
 
162
 
 
163
  OSPF_TIMER_OFF (area->t_opaque_lsa_self);
 
164
  if (area->opaque_lsa_self != NULL)
 
165
    list_delete (area->opaque_lsa_self);
 
166
  area->opaque_lsa_self = NULL;
 
167
  return;
 
168
}
 
169
 
 
170
int
 
171
ospf_opaque_type11_lsa_init (struct ospf *top)
 
172
{
 
173
  if (top->opaque_lsa_self != NULL)
 
174
    list_delete (top->opaque_lsa_self);
 
175
 
 
176
  top->opaque_lsa_self = list_new ();
 
177
  top->opaque_lsa_self->del = free_opaque_info_per_type;
 
178
  top->t_opaque_lsa_self = NULL;
 
179
 
 
180
#ifdef MONITOR_LSDB_CHANGE
 
181
  top->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
 
182
  top->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
 
183
#endif /* MONITOR_LSDB_CHANGE */
 
184
  return 0;
 
185
}
 
186
 
 
187
void
 
188
ospf_opaque_type11_lsa_term (struct ospf *top)
 
189
{
 
190
#ifdef MONITOR_LSDB_CHANGE
 
191
  top->lsdb->new_lsa_hook = 
 
192
  top->lsdb->del_lsa_hook = NULL;
 
193
#endif /* MONITOR_LSDB_CHANGE */
 
194
 
 
195
  OSPF_TIMER_OFF (top->t_opaque_lsa_self);
 
196
  if (top->opaque_lsa_self != NULL)
 
197
    list_delete (top->opaque_lsa_self);
 
198
  top->opaque_lsa_self = NULL;
 
199
  return;
 
200
}
 
201
 
 
202
static const char *
 
203
ospf_opaque_type_name (u_char opaque_type)
 
204
{
 
205
  const char *name = "Unknown";
 
206
 
 
207
  switch (opaque_type)
 
208
    {
 
209
    case OPAQUE_TYPE_WILDCARD: /* This is a special assignment! */
 
210
      name = "Wildcard";
 
211
      break;
 
212
    case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA:
 
213
      name = "Traffic Engineering LSA";
 
214
      break;
 
215
    case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC:
 
216
      name = "Sycamore optical topology description";
 
217
      break;
 
218
    case OPAQUE_TYPE_GRACE_LSA:
 
219
      name = "Grace-LSA";
 
220
      break;
 
221
    default:
 
222
      if (OPAQUE_TYPE_RANGE_UNASSIGNED (opaque_type))
 
223
        name = "Unassigned";
 
224
      else if (OPAQUE_TYPE_RANGE_RESERVED (opaque_type))
 
225
        name = "Private/Experimental";
 
226
      break;
 
227
    }
 
228
  return name;
 
229
}
 
230
 
 
231
/*------------------------------------------------------------------------*
 
232
 * Followings are management functions to store user specified callbacks.
 
233
 *------------------------------------------------------------------------*/
 
234
 
 
235
struct opaque_info_per_type; /* Forward declaration. */
 
236
 
 
237
struct ospf_opaque_functab
 
238
{
 
239
  u_char opaque_type;
 
240
  struct opaque_info_per_type *oipt;
 
241
 
 
242
  int (* new_if_hook)(struct interface *ifp);
 
243
  int (* del_if_hook)(struct interface *ifp);
 
244
  void (* ism_change_hook)(struct ospf_interface *oi, int old_status);
 
245
  void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status);
 
246
  void (* config_write_router)(struct vty *vty);
 
247
  void (* config_write_if    )(struct vty *vty, struct interface *ifp);
 
248
  void (* config_write_debug )(struct vty *vty);
 
249
  void (* show_opaque_info   )(struct vty *vty, struct ospf_lsa *lsa);
 
250
  int  (* lsa_originator)(void *arg);
 
251
  void (* lsa_refresher )(struct ospf_lsa *lsa);
 
252
  int (* new_lsa_hook)(struct ospf_lsa *lsa);
 
253
  int (* del_lsa_hook)(struct ospf_lsa *lsa);
 
254
};
 
255
 
 
256
static list ospf_opaque_wildcard_funclist; /* Handle LSA-9/10/11 altogether. */
 
257
static list ospf_opaque_type9_funclist;
 
258
static list ospf_opaque_type10_funclist;
 
259
static list ospf_opaque_type11_funclist;
 
260
 
 
261
static void
 
262
ospf_opaque_del_functab (void *val)
 
263
{
 
264
  XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, val);
 
265
  return;
 
266
}
 
267
 
 
268
static void
 
269
ospf_opaque_funclist_init (void)
 
270
{
 
271
  list funclist;
 
272
 
 
273
  funclist = ospf_opaque_wildcard_funclist = list_new ();
 
274
  funclist->del = ospf_opaque_del_functab;
 
275
 
 
276
  funclist = ospf_opaque_type9_funclist  = list_new ();
 
277
  funclist->del = ospf_opaque_del_functab;
 
278
 
 
279
  funclist = ospf_opaque_type10_funclist = list_new ();
 
280
  funclist->del = ospf_opaque_del_functab;
 
281
 
 
282
  funclist = ospf_opaque_type11_funclist = list_new ();
 
283
  funclist->del = ospf_opaque_del_functab;
 
284
  return;
 
285
}
 
286
 
 
287
static void
 
288
ospf_opaque_funclist_term (void)
 
289
{
 
290
  list funclist;
 
291
 
 
292
  funclist = ospf_opaque_wildcard_funclist;
 
293
  list_delete (funclist);
 
294
 
 
295
  funclist = ospf_opaque_type9_funclist;
 
296
  list_delete (funclist);
 
297
 
 
298
  funclist = ospf_opaque_type10_funclist;
 
299
  list_delete (funclist);
 
300
 
 
301
  funclist = ospf_opaque_type11_funclist;
 
302
  list_delete (funclist);
 
303
  return;
 
304
}
 
305
 
 
306
static list
 
307
ospf_get_opaque_funclist (u_char lsa_type)
 
308
{
 
309
  list funclist = NULL;
 
310
 
 
311
  switch (lsa_type)
 
312
    {
 
313
    case OPAQUE_TYPE_WILDCARD:
 
314
      /* XXX
 
315
       * This is an ugly trick to handle type-9/10/11 LSA altogether.
 
316
       * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor
 
317
       * an officially assigned opaque-type.
 
318
       * Though it is possible that the value might be officially used
 
319
       * in the future, we use it internally as a special label, for now.
 
320
       */
 
321
      funclist = ospf_opaque_wildcard_funclist;
 
322
      break;
 
323
    case OSPF_OPAQUE_LINK_LSA:
 
324
      funclist = ospf_opaque_type9_funclist;
 
325
      break;
 
326
    case OSPF_OPAQUE_AREA_LSA:
 
327
      funclist = ospf_opaque_type10_funclist;
 
328
      break;
 
329
    case OSPF_OPAQUE_AS_LSA:
 
330
      funclist = ospf_opaque_type11_funclist;
 
331
      break;
 
332
    default:
 
333
      zlog_warn ("ospf_get_opaque_funclist: Unexpected LSA-type(%u)", lsa_type);
 
334
      break;
 
335
    }
 
336
  return funclist;
 
337
}
 
338
 
 
339
int
 
340
ospf_register_opaque_functab (
 
341
  u_char lsa_type,
 
342
  u_char opaque_type,
 
343
  int (* new_if_hook)(struct interface *ifp),
 
344
  int (* del_if_hook)(struct interface *ifp),
 
345
  void (* ism_change_hook)(struct ospf_interface *oi, int old_status),
 
346
  void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status),
 
347
  void (* config_write_router)(struct vty *vty),
 
348
  void (* config_write_if    )(struct vty *vty, struct interface *ifp),
 
349
  void (* config_write_debug )(struct vty *vty),
 
350
  void (* show_opaque_info   )(struct vty *vty, struct ospf_lsa *lsa),
 
351
  int  (* lsa_originator)(void *arg),
 
352
  void (* lsa_refresher )(struct ospf_lsa *lsa),
 
353
  int (* new_lsa_hook)(struct ospf_lsa *lsa),
 
354
  int (* del_lsa_hook)(struct ospf_lsa *lsa))
 
355
{
 
356
  list funclist;
 
357
  struct ospf_opaque_functab *new;
 
358
  int rc = -1;
 
359
 
 
360
  if ((funclist = ospf_get_opaque_funclist (lsa_type)) == NULL)
 
361
    {
 
362
      zlog_warn ("ospf_register_opaque_functab: Cannot get funclist for Type-%u LSAs?", lsa_type);
 
363
      goto out;
 
364
    }
 
365
  else
 
366
    {
 
367
      listnode node;
 
368
      struct ospf_opaque_functab *functab;
 
369
 
 
370
      for (node = listhead (funclist); node; nextnode (node))
 
371
        if ((functab = getdata (node)) != NULL)
 
372
          if (functab->opaque_type == opaque_type)
 
373
            {
 
374
              zlog_warn ("ospf_register_opaque_functab: Duplicated entry?: lsa_type(%u), opaque_type(%u)", lsa_type, opaque_type);
 
375
              goto out;
 
376
            }
 
377
    }
 
378
 
 
379
  if ((new = XCALLOC (MTYPE_OSPF_OPAQUE_FUNCTAB,
 
380
                      sizeof (struct ospf_opaque_functab))) == NULL)
 
381
    {
 
382
      zlog_warn ("ospf_register_opaque_functab: XMALLOC: %s", strerror (errno));
 
383
      goto out;
 
384
    }
 
385
 
 
386
  new->opaque_type    = opaque_type;
 
387
  new->oipt           = NULL;
 
388
  new->new_if_hook    = new_if_hook;
 
389
  new->del_if_hook    = del_if_hook;
 
390
  new->ism_change_hook     = ism_change_hook;
 
391
  new->nsm_change_hook     = nsm_change_hook;
 
392
  new->config_write_router = config_write_router;
 
393
  new->config_write_if     = config_write_if;
 
394
  new->config_write_debug  = config_write_debug;
 
395
  new->show_opaque_info    = show_opaque_info;
 
396
  new->lsa_originator = lsa_originator;
 
397
  new->lsa_refresher  = lsa_refresher;
 
398
  new->new_lsa_hook   = new_lsa_hook;
 
399
  new->del_lsa_hook   = del_lsa_hook;
 
400
 
 
401
  listnode_add (funclist, new);
 
402
  rc = 0;
 
403
 
 
404
out:
 
405
  return rc;
 
406
}
 
407
 
 
408
void
 
409
ospf_delete_opaque_functab (u_char lsa_type, u_char opaque_type)
 
410
{
 
411
  list funclist;
 
412
  listnode node;
 
413
  struct ospf_opaque_functab *functab;
 
414
 
 
415
  if ((funclist = ospf_get_opaque_funclist (lsa_type)) != NULL)
 
416
    for (node = listhead (funclist); node; nextnode (node))
 
417
      {
 
418
        if ((functab = getdata (node)) != NULL
 
419
        &&   functab->opaque_type == opaque_type)
 
420
          {
 
421
            /* Cleanup internal control information, if it still remains. */
 
422
            if (functab->oipt != NULL)
 
423
              free_opaque_info_per_type (functab->oipt);
 
424
 
 
425
            /* Dequeue listnode entry from the list. */
 
426
            listnode_delete (funclist, functab);
 
427
 
 
428
            /* Avoid misjudgement in the next lookup. */
 
429
            if (listcount (funclist) == 0)
 
430
              funclist->head = funclist->tail = NULL;
 
431
 
 
432
            XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, functab);
 
433
            goto out;
 
434
          }
 
435
      }
 
436
out:
 
437
  return;
 
438
}
 
439
 
 
440
static struct ospf_opaque_functab *
 
441
ospf_opaque_functab_lookup (struct ospf_lsa *lsa)
 
442
{
 
443
  list funclist;
 
444
  listnode node;
 
445
  struct ospf_opaque_functab *functab;
 
446
  u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
 
447
 
 
448
  if ((funclist = ospf_get_opaque_funclist (lsa->data->type)) != NULL)
 
449
    for (node = listhead (funclist); node; nextnode (node))
 
450
      if ((functab = getdata (node)) != NULL)
 
451
        if (functab->opaque_type == key)
 
452
          return functab;
 
453
 
 
454
  return NULL;
 
455
}
 
456
 
 
457
/*------------------------------------------------------------------------*
 
458
 * Followings 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
{
 
468
  u_char lsa_type;
 
469
  u_char opaque_type;
 
470
 
 
471
  enum { PROC_NORMAL, PROC_SUSPEND } status;
 
472
 
 
473
  /*
 
474
   * Thread for (re-)origination scheduling for this opaque-type.
 
475
   *
 
476
   * Initial origination of Opaque-LSAs is controlled by generic
 
477
   * Opaque-LSA handling module so that same opaque-type entries are
 
478
   * called all at once when certain conditions are met.
 
479
   * However, there might be cases that some Opaque-LSA clients need
 
480
   * to (re-)originate their own Opaque-LSAs out-of-sync with others.
 
481
   * This thread is prepared for that specific purpose.
 
482
   */
 
483
  struct thread *t_opaque_lsa_self;
 
484
 
 
485
  /*
 
486
   * Backpointer to an "owner" which is LSA-type dependent.
 
487
   *   type-9:  struct ospf_interface
 
488
   *   type-10: struct ospf_area
 
489
   *   type-11: struct ospf
 
490
   */
 
491
  void *owner;
 
492
 
 
493
  /* Collection of callback functions for this opaque-type. */
 
494
  struct ospf_opaque_functab *functab;
 
495
 
 
496
  /* List of Opaque-LSA control informations per opaque-id. */
 
497
  list id_list;
 
498
};
 
499
 
 
500
/* Opaque-LSA control information per opaque-id. */
 
501
struct opaque_info_per_id
 
502
{
 
503
  u_int32_t opaque_id;
 
504
 
 
505
  /* Thread for refresh/flush scheduling for this opaque-type/id. */
 
506
  struct thread *t_opaque_lsa_self;
 
507
 
 
508
  /* Backpointer to Opaque-LSA control information per opaque-type. */
 
509
  struct opaque_info_per_type *opqctl_type;
 
510
 
 
511
  /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
 
512
  struct ospf_lsa *lsa;
 
513
};
 
514
 
 
515
static struct opaque_info_per_type *register_opaque_info_per_type (struct ospf_opaque_functab *functab, struct ospf_lsa *new);
 
516
static struct opaque_info_per_type *lookup_opaque_info_by_type (struct ospf_lsa *lsa);
 
517
static struct opaque_info_per_id *register_opaque_info_per_id (struct opaque_info_per_type *oipt, struct ospf_lsa *new);
 
518
static struct opaque_info_per_id *lookup_opaque_info_by_id (struct opaque_info_per_type *oipt, struct ospf_lsa *lsa);
 
519
static struct opaque_info_per_id *register_opaque_lsa (struct ospf_lsa *new);
 
520
 
 
521
 
 
522
static struct opaque_info_per_type *
 
523
register_opaque_info_per_type (struct ospf_opaque_functab *functab,
 
524
                               struct ospf_lsa *new)
 
525
{
 
526
  struct ospf *top;
 
527
  struct opaque_info_per_type *oipt;
 
528
 
 
529
  if ((oipt = XCALLOC (MTYPE_OPAQUE_INFO_PER_TYPE,
 
530
                       sizeof (struct opaque_info_per_type))) == NULL)
 
531
    {
 
532
      zlog_warn ("register_opaque_info_per_type: XMALLOC: %s", strerror (errno));
 
533
      goto out;
 
534
    }
 
535
 
 
536
  switch (new->data->type)
 
537
    {
 
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:
 
547
      top = ospf_lookup ();
 
548
      if (new->area != NULL && (top = new->area->ospf) == NULL)
 
549
        {
 
550
          free_opaque_info_per_type ((void *) oipt);
 
551
          oipt = NULL;
 
552
          goto out; /* This case may not exist. */
 
553
        }
 
554
      oipt->owner = top;
 
555
      listnode_add (top->opaque_lsa_self, oipt);
 
556
      break;
 
557
    default:
 
558
      zlog_warn ("register_opaque_info_per_type: Unexpected LSA-type(%u)", new->data->type);
 
559
      free_opaque_info_per_type ((void *) oipt);
 
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;
 
567
  oipt->t_opaque_lsa_self = NULL;
 
568
  oipt->functab = functab;
 
569
  functab->oipt = oipt;
 
570
  oipt->id_list = list_new ();
 
571
  oipt->id_list->del = free_opaque_info_per_id;
 
572
 
 
573
out:
 
574
  return oipt;
 
575
}
 
576
 
 
577
static void
 
578
free_opaque_info_per_type (void *val)
 
579
{
 
580
  struct opaque_info_per_type *oipt = (struct opaque_info_per_type *) val;
 
581
  struct opaque_info_per_id *oipi;
 
582
  struct ospf_lsa *lsa;
 
583
  listnode node;
 
584
 
 
585
  /* Control information per opaque-id may still exist. */
 
586
  for (node = listhead (oipt->id_list); node; nextnode (node))
 
587
    {
 
588
      if ((oipi = getdata (node)) == NULL)
 
589
        continue;
 
590
      if ((lsa = oipi->lsa) == NULL)
 
591
        continue;
 
592
      if (IS_LSA_MAXAGE (lsa))
 
593
        continue;
 
594
      ospf_opaque_lsa_flush_schedule (lsa);
 
595
    }
 
596
 
 
597
  /* Remove "oipt" from its owner's self-originated LSA list. */
 
598
  switch (oipt->lsa_type)
 
599
    {
 
600
    case OSPF_OPAQUE_LINK_LSA:
 
601
      {
 
602
        struct ospf_interface *oi = (struct ospf_interface *)(oipt->owner);
 
603
        listnode_delete (oi->opaque_lsa_self, oipt);
 
604
        break;
 
605
      }
 
606
    case OSPF_OPAQUE_AREA_LSA:
 
607
      {
 
608
        struct ospf_area *area = (struct ospf_area *)(oipt->owner);
 
609
        listnode_delete (area->opaque_lsa_self, oipt);
 
610
        break;
 
611
      }
 
612
    case OSPF_OPAQUE_AS_LSA:
 
613
      {
 
614
        struct ospf *top = (struct ospf *)(oipt->owner);
 
615
        listnode_delete (top->opaque_lsa_self, oipt);
 
616
        break;
 
617
      }
 
618
    default:
 
619
      zlog_warn ("free_opaque_info_per_type: Unexpected LSA-type(%u)", oipt->lsa_type);
 
620
      break; /* This case may not exist. */
 
621
    }
 
622
 
 
623
  OSPF_TIMER_OFF (oipt->t_opaque_lsa_self);
 
624
  list_delete (oipt->id_list);
 
625
  XFREE (MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
 
626
  return;
 
627
}
 
628
 
 
629
static struct opaque_info_per_type *
 
630
lookup_opaque_info_by_type (struct ospf_lsa *lsa)
 
631
{
 
632
  struct ospf *top;
 
633
  struct ospf_area *area;
 
634
  struct ospf_interface *oi;
 
635
  list listtop = NULL;
 
636
  listnode node;
 
637
  struct opaque_info_per_type *oipt = NULL;
 
638
  u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
 
639
 
 
640
  switch (lsa->data->type)
 
641
    {
 
642
    case OSPF_OPAQUE_LINK_LSA:
 
643
      if ((oi = lsa->oi) != NULL)
 
644
        listtop = oi->opaque_lsa_self;
 
645
      else
 
646
        zlog_warn ("Type-9 Opaque-LSA: Reference to OI is missing?");
 
647
      break;
 
648
    case OSPF_OPAQUE_AREA_LSA:
 
649
      if ((area = lsa->area) != NULL)
 
650
        listtop = area->opaque_lsa_self;
 
651
      else
 
652
        zlog_warn ("Type-10 Opaque-LSA: Reference to AREA is missing?");
 
653
      break;
 
654
    case OSPF_OPAQUE_AS_LSA:
 
655
      top = ospf_lookup ();
 
656
      if ((area = lsa->area) != NULL && (top = area->ospf) == NULL)
 
657
        {
 
658
          zlog_warn ("Type-11 Opaque-LSA: Reference to OSPF is missing?");
 
659
          break; /* Unlikely to happen. */
 
660
        }
 
661
      listtop = top->opaque_lsa_self;
 
662
      break;
 
663
    default:
 
664
      zlog_warn ("lookup_opaque_info_by_type: Unexpected LSA-type(%u)", lsa->data->type);
 
665
      break;
 
666
    }
 
667
 
 
668
  if (listtop != NULL)
 
669
    for (node = listhead (listtop); node; nextnode (node))
 
670
      if ((oipt = getdata (node)) != NULL)
 
671
        if (oipt->opaque_type == key)
 
672
          return oipt;
 
673
 
 
674
  return NULL;
 
675
}
 
676
 
 
677
static struct opaque_info_per_id *
 
678
register_opaque_info_per_id (struct opaque_info_per_type *oipt,
 
679
                             struct ospf_lsa *new)
 
680
{
 
681
  struct opaque_info_per_id *oipi;
 
682
 
 
683
  if ((oipi = XCALLOC (MTYPE_OPAQUE_INFO_PER_ID,
 
684
                       sizeof (struct opaque_info_per_id))) == NULL)
 
685
    {
 
686
      zlog_warn ("register_opaque_info_per_id: XMALLOC: %s", strerror (errno));
 
687
      goto out;
 
688
    }
 
689
  oipi->opaque_id = GET_OPAQUE_ID (ntohl (new->data->id.s_addr));
 
690
  oipi->t_opaque_lsa_self = NULL;
 
691
  oipi->opqctl_type = oipt;
 
692
  oipi->lsa = ospf_lsa_lock (new);
 
693
 
 
694
  listnode_add (oipt->id_list, oipi);
 
695
 
 
696
out:
 
697
  return oipi;
 
698
}
 
699
 
 
700
static void
 
701
free_opaque_info_per_id (void *val)
 
702
{
 
703
  struct opaque_info_per_id *oipi = (struct opaque_info_per_id *) val;
 
704
 
 
705
  OSPF_TIMER_OFF (oipi->t_opaque_lsa_self);
 
706
  if (oipi->lsa != NULL)
 
707
    ospf_lsa_unlock (oipi->lsa);
 
708
  XFREE (MTYPE_OPAQUE_INFO_PER_ID, oipi);
 
709
  return;
 
710
}
 
711
 
 
712
static struct opaque_info_per_id *
 
713
lookup_opaque_info_by_id (struct opaque_info_per_type *oipt,
 
714
                          struct ospf_lsa *lsa)
 
715
{
 
716
  listnode node;
 
717
  struct opaque_info_per_id   *oipi;
 
718
  u_int32_t key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
 
719
 
 
720
  for (node = listhead (oipt->id_list); node; nextnode (node))
 
721
    if ((oipi = getdata (node)) != NULL)
 
722
      if (oipi->opaque_id == key)
 
723
        return oipi;
 
724
 
 
725
  return NULL;
 
726
}
 
727
 
 
728
static struct opaque_info_per_id *
 
729
register_opaque_lsa (struct ospf_lsa *new)
 
730
{
 
731
  struct ospf_opaque_functab *functab;
 
732
  struct opaque_info_per_type *oipt;
 
733
  struct opaque_info_per_id *oipi = NULL;
 
734
 
 
735
  if ((functab = ospf_opaque_functab_lookup (new)) == NULL)
 
736
    goto out;
 
737
 
 
738
  if ((oipt = lookup_opaque_info_by_type (new)) == NULL
 
739
  &&  (oipt = register_opaque_info_per_type (functab, new)) == NULL)
 
740
    goto out;
 
741
 
 
742
  if ((oipi = register_opaque_info_per_id (oipt, new)) == NULL)
 
743
    goto out;
 
744
 
 
745
out:
 
746
  return oipi;
 
747
}
 
748
 
 
749
/*------------------------------------------------------------------------*
 
750
 * Followings 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
{
 
759
  struct ospf *ospf = (struct ospf *) vty->index;
 
760
 
 
761
  /* Turn on the "master switch" of opaque-lsa capability. */
 
762
  if (!CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
 
763
    {
 
764
      if (IS_DEBUG_OSPF_EVENT)
 
765
        zlog_info ("Opaque capability: OFF -> ON");
 
766
 
 
767
      SET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
 
768
      ospf_renegotiate_optional_capabilities (ospf);
 
769
    }
 
770
  return CMD_SUCCESS;
 
771
}
 
772
 
 
773
ALIAS (capability_opaque,
 
774
       ospf_opaque_capable_cmd,
 
775
       "ospf opaque-lsa",
 
776
       "OSPF specific commands\n"
 
777
       "Enable the Opaque-LSA capability (rfc2370)\n")
 
778
 
 
779
DEFUN (no_capability_opaque,
 
780
       no_capability_opaque_cmd,
 
781
       "no capability opaque",
 
782
       NO_STR
 
783
       "Enable specific OSPF feature\n"
 
784
       "Opaque LSA\n")
 
785
{
 
786
  struct ospf *ospf = (struct ospf *) vty->index;
 
787
 
 
788
  /* Turn off the "master switch" of opaque-lsa capability. */
 
789
  if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
 
790
    {
 
791
      if (IS_DEBUG_OSPF_EVENT)
 
792
        zlog_info ("Opaque capability: ON -> OFF");
 
793
 
 
794
      UNSET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
 
795
      ospf_renegotiate_optional_capabilities (ospf);
 
796
    }
 
797
  return CMD_SUCCESS;
 
798
}
 
799
 
 
800
ALIAS (no_capability_opaque,
 
801
       no_ospf_opaque_capable_cmd,
 
802
       "no ospf opaque-lsa",
 
803
       NO_STR
 
804
       "OSPF specific commands\n"
 
805
       "Disable the Opaque-LSA capability (rfc2370)\n")
 
806
 
 
807
static void
 
808
ospf_opaque_register_vty (void)
 
809
{
 
810
  install_element (OSPF_NODE, &capability_opaque_cmd);
 
811
  install_element (OSPF_NODE, &no_capability_opaque_cmd);
 
812
  install_element (OSPF_NODE, &ospf_opaque_capable_cmd);
 
813
  install_element (OSPF_NODE, &no_ospf_opaque_capable_cmd);
 
814
  return;
 
815
}
 
816
 
 
817
/*------------------------------------------------------------------------*
 
818
 * Followings are collection of user-registered function callers.
 
819
 *------------------------------------------------------------------------*/
 
820
 
 
821
static int
 
822
opaque_lsa_new_if_callback (list funclist, struct interface *ifp)
 
823
{
 
824
  listnode node;
 
825
  struct ospf_opaque_functab *functab;
 
826
  int rc = -1;
 
827
 
 
828
  for (node = listhead (funclist); node; nextnode (node))
 
829
    if ((functab = getdata (node)) != NULL)
 
830
      if (functab->new_if_hook != NULL)
 
831
        if ((* functab->new_if_hook)(ifp) != 0)
 
832
          goto out;
 
833
  rc = 0;
 
834
out:
 
835
  return rc;
 
836
}
 
837
 
 
838
static int
 
839
opaque_lsa_del_if_callback (list funclist, struct interface *ifp)
 
840
{
 
841
  listnode node;
 
842
  struct ospf_opaque_functab *functab;
 
843
  int rc = -1;
 
844
 
 
845
  for (node = listhead (funclist); node; nextnode (node))
 
846
    if ((functab = getdata (node)) != NULL)
 
847
      if (functab->del_if_hook != NULL)
 
848
        if ((* functab->del_if_hook)(ifp) != 0)
 
849
          goto out;
 
850
  rc = 0;
 
851
out:
 
852
  return rc;
 
853
}
 
854
 
 
855
static void
 
856
opaque_lsa_ism_change_callback (list funclist,
 
857
                                struct ospf_interface *oi, int old_status)
 
858
{
 
859
  listnode node;
 
860
  struct ospf_opaque_functab *functab;
 
861
 
 
862
  for (node = listhead (funclist); node; nextnode (node))
 
863
    if ((functab = getdata (node)) != NULL)
 
864
      if (functab->ism_change_hook != NULL)
 
865
        (* functab->ism_change_hook)(oi, old_status);
 
866
  return;
 
867
}
 
868
 
 
869
static void
 
870
opaque_lsa_nsm_change_callback (list funclist,
 
871
                                struct ospf_neighbor *nbr, int old_status)
 
872
{
 
873
  listnode node;
 
874
  struct ospf_opaque_functab *functab;
 
875
 
 
876
  for (node = listhead (funclist); node; nextnode (node))
 
877
    if ((functab = getdata (node)) != NULL)
 
878
      if (functab->nsm_change_hook != NULL)
 
879
        (* functab->nsm_change_hook)(nbr, old_status);
 
880
  return;
 
881
}
 
882
 
 
883
static void
 
884
opaque_lsa_config_write_router_callback (list funclist, struct vty *vty)
 
885
{
 
886
  listnode node;
 
887
  struct ospf_opaque_functab *functab;
 
888
 
 
889
  for (node = listhead (funclist); node; nextnode (node))
 
890
    if ((functab = getdata (node)) != NULL)
 
891
      if (functab->config_write_router != NULL)
 
892
        (* functab->config_write_router)(vty);
 
893
  return;
 
894
}
 
895
 
 
896
static void
 
897
opaque_lsa_config_write_if_callback (list funclist,
 
898
                                     struct vty *vty, struct interface *ifp)
 
899
{
 
900
  listnode node;
 
901
  struct ospf_opaque_functab *functab;
 
902
 
 
903
  for (node = listhead (funclist); node; nextnode (node))
 
904
    if ((functab = getdata (node)) != NULL)
 
905
      if (functab->config_write_if != NULL)
 
906
        (* functab->config_write_if)(vty, ifp);
 
907
  return;
 
908
}
 
909
 
 
910
static void
 
911
opaque_lsa_config_write_debug_callback (list funclist, struct vty *vty)
 
912
{
 
913
  listnode node;
 
914
  struct ospf_opaque_functab *functab;
 
915
 
 
916
  for (node = listhead (funclist); node; nextnode (node))
 
917
    if ((functab = getdata (node)) != NULL)
 
918
      if (functab->config_write_debug != NULL)
 
919
        (* functab->config_write_debug)(vty);
 
920
  return;
 
921
}
 
922
 
 
923
static int
 
924
opaque_lsa_originate_callback (list funclist, void *lsa_type_dependent)
 
925
{
 
926
  listnode node;
 
927
  struct ospf_opaque_functab *functab;
 
928
  int rc = -1;
 
929
 
 
930
  for (node = listhead (funclist); node; nextnode (node))
 
931
    if ((functab = getdata (node)) != NULL)
 
932
      if (functab->lsa_originator != NULL)
 
933
        if ((* functab->lsa_originator)(lsa_type_dependent) != 0)
 
934
           goto out;
 
935
  rc = 0;
 
936
out:
 
937
  return rc;
 
938
}
 
939
 
 
940
static int
 
941
new_lsa_callback (list funclist, struct ospf_lsa *lsa)
 
942
{
 
943
  listnode node;
 
944
  struct ospf_opaque_functab *functab;
 
945
  int rc = -1;
 
946
 
 
947
  /* This function handles ALL types of LSAs, not only opaque ones. */
 
948
  for (node = listhead (funclist); node; nextnode (node))
 
949
    if ((functab = getdata (node)) != NULL)
 
950
      if (functab->new_lsa_hook != NULL)
 
951
        if ((* functab->new_lsa_hook)(lsa) != 0)
 
952
          goto out;
 
953
  rc = 0;
 
954
out:
 
955
  return rc;
 
956
}
 
957
 
 
958
static int
 
959
del_lsa_callback (list funclist, struct ospf_lsa *lsa)
 
960
{
 
961
  listnode node;
 
962
  struct ospf_opaque_functab *functab;
 
963
  int rc = -1;
 
964
 
 
965
  /* This function handles ALL types of LSAs, not only opaque ones. */
 
966
  for (node = listhead (funclist); node; nextnode (node))
 
967
    if ((functab = getdata (node)) != NULL)
 
968
      if (functab->del_lsa_hook != NULL)
 
969
        if ((* functab->del_lsa_hook)(lsa) != 0)
 
970
          goto out;
 
971
  rc = 0;
 
972
out:
 
973
  return rc;
 
974
}
 
975
 
 
976
/*------------------------------------------------------------------------*
 
977
 * Followings are glue functions to call Opaque-LSA specific processing.
 
978
 *------------------------------------------------------------------------*/
 
979
 
 
980
int
 
981
ospf_opaque_new_if (struct interface *ifp)
 
982
{
 
983
  list funclist;
 
984
  int rc = -1;
 
985
 
 
986
  funclist = ospf_opaque_wildcard_funclist;
 
987
  if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
 
988
    goto out;
 
989
 
 
990
  funclist = ospf_opaque_type9_funclist;
 
991
  if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
 
992
    goto out;
 
993
 
 
994
  funclist = ospf_opaque_type10_funclist;
 
995
  if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
 
996
    goto out;
 
997
 
 
998
  funclist = ospf_opaque_type11_funclist;
 
999
  if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
 
1000
    goto out;
 
1001
 
 
1002
  rc = 0;
 
1003
out:
 
1004
  return rc;
 
1005
}
 
1006
 
 
1007
int
 
1008
ospf_opaque_del_if (struct interface *ifp)
 
1009
{
 
1010
  list funclist;
 
1011
  int rc = -1;
 
1012
 
 
1013
  funclist = ospf_opaque_wildcard_funclist;
 
1014
  if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
 
1015
    goto out;
 
1016
 
 
1017
  funclist = ospf_opaque_type9_funclist;
 
1018
  if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
 
1019
    goto out;
 
1020
 
 
1021
  funclist = ospf_opaque_type10_funclist;
 
1022
  if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
 
1023
    goto out;
 
1024
 
 
1025
  funclist = ospf_opaque_type11_funclist;
 
1026
  if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
 
1027
    goto out;
 
1028
 
 
1029
  rc = 0;
 
1030
out:
 
1031
  return rc;
 
1032
}
 
1033
 
 
1034
void
 
1035
ospf_opaque_ism_change (struct ospf_interface *oi, int old_status)
 
1036
{
 
1037
  list funclist;
 
1038
 
 
1039
  funclist = ospf_opaque_wildcard_funclist;
 
1040
  opaque_lsa_ism_change_callback (funclist, oi, old_status);
 
1041
 
 
1042
  funclist = ospf_opaque_type9_funclist;
 
1043
  opaque_lsa_ism_change_callback (funclist, oi, old_status);
 
1044
 
 
1045
  funclist = ospf_opaque_type10_funclist;
 
1046
  opaque_lsa_ism_change_callback (funclist, oi, old_status);
 
1047
 
 
1048
  funclist = ospf_opaque_type11_funclist;
 
1049
  opaque_lsa_ism_change_callback (funclist, oi, old_status);
 
1050
 
 
1051
  return;
 
1052
}
 
1053
 
 
1054
void
 
1055
ospf_opaque_nsm_change (struct ospf_neighbor *nbr, int old_state)
 
1056
{
 
1057
  struct ospf *top;
 
1058
  list funclist;
 
1059
 
 
1060
  if ((top = oi_to_top (nbr->oi)) == NULL)
 
1061
    goto out;
 
1062
 
 
1063
  if (old_state != NSM_Full && nbr->state == NSM_Full)
 
1064
    {
 
1065
      if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
 
1066
        {
 
1067
          if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
 
1068
            {
 
1069
              if (IS_DEBUG_OSPF_EVENT)
 
1070
                zlog_info ("Opaque-LSA: Now get operational!");
 
1071
 
 
1072
              SET_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT);
 
1073
            }
 
1074
 
 
1075
          ospf_opaque_lsa_originate_schedule (nbr->oi, NULL);
 
1076
        }
 
1077
    }
 
1078
  else
 
1079
  if (old_state == NSM_Full && nbr->state != NSM_Full)
 
1080
    {
 
1081
#ifdef NOTYET
 
1082
      /*
 
1083
       * If no more opaque-capable full-state neighbor remains in the
 
1084
       * flooding scope which corresponds to Opaque-LSA type, periodic
 
1085
       * LS flooding should be stopped.
 
1086
       */
 
1087
#endif /* NOTYET */
 
1088
      ;
 
1089
    }
 
1090
 
 
1091
  funclist = ospf_opaque_wildcard_funclist;
 
1092
  opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
 
1093
 
 
1094
  funclist = ospf_opaque_type9_funclist;
 
1095
  opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
 
1096
 
 
1097
  funclist = ospf_opaque_type10_funclist;
 
1098
  opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
 
1099
 
 
1100
  funclist = ospf_opaque_type11_funclist;
 
1101
  opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
 
1102
 
 
1103
out:
 
1104
  return;
 
1105
}
 
1106
 
 
1107
void
 
1108
ospf_opaque_config_write_router (struct vty *vty, struct ospf *ospf)
 
1109
{
 
1110
  list funclist;
 
1111
 
 
1112
  if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
 
1113
    vty_out (vty, " capability opaque%s", VTY_NEWLINE);
 
1114
 
 
1115
  funclist = ospf_opaque_wildcard_funclist;
 
1116
  opaque_lsa_config_write_router_callback (funclist, vty);
 
1117
 
 
1118
  funclist = ospf_opaque_type9_funclist;
 
1119
  opaque_lsa_config_write_router_callback (funclist, vty);
 
1120
 
 
1121
  funclist = ospf_opaque_type10_funclist;
 
1122
  opaque_lsa_config_write_router_callback (funclist, vty);
 
1123
 
 
1124
  funclist = ospf_opaque_type11_funclist;
 
1125
  opaque_lsa_config_write_router_callback (funclist, vty);
 
1126
 
 
1127
  return;
 
1128
}
 
1129
 
 
1130
void
 
1131
ospf_opaque_config_write_if (struct vty *vty, struct interface *ifp)
 
1132
{
 
1133
  list funclist;
 
1134
 
 
1135
  funclist = ospf_opaque_wildcard_funclist;
 
1136
  opaque_lsa_config_write_if_callback (funclist, vty, ifp);
 
1137
 
 
1138
  funclist = ospf_opaque_type9_funclist;
 
1139
  opaque_lsa_config_write_if_callback (funclist, vty, ifp);
 
1140
 
 
1141
  funclist = ospf_opaque_type10_funclist;
 
1142
  opaque_lsa_config_write_if_callback (funclist, vty, ifp);
 
1143
 
 
1144
  funclist = ospf_opaque_type11_funclist;
 
1145
  opaque_lsa_config_write_if_callback (funclist, vty, ifp);
 
1146
 
 
1147
  return;
 
1148
}
 
1149
 
 
1150
void
 
1151
ospf_opaque_config_write_debug (struct vty *vty)
 
1152
{
 
1153
  list funclist;
 
1154
 
 
1155
  funclist = ospf_opaque_wildcard_funclist;
 
1156
  opaque_lsa_config_write_debug_callback (funclist, vty);
 
1157
 
 
1158
  funclist = ospf_opaque_type9_funclist;
 
1159
  opaque_lsa_config_write_debug_callback (funclist, vty);
 
1160
 
 
1161
  funclist = ospf_opaque_type10_funclist;
 
1162
  opaque_lsa_config_write_debug_callback (funclist, vty);
 
1163
 
 
1164
  funclist = ospf_opaque_type11_funclist;
 
1165
  opaque_lsa_config_write_debug_callback (funclist, vty);
 
1166
 
 
1167
  return;
 
1168
}
 
1169
 
 
1170
void
 
1171
show_opaque_info_detail (struct vty *vty, struct ospf_lsa *lsa)
 
1172
{
 
1173
  struct lsa_header *lsah = (struct lsa_header *) lsa->data;
 
1174
  u_int32_t lsid = ntohl (lsah->id.s_addr);
 
1175
  u_char    opaque_type = GET_OPAQUE_TYPE (lsid);
 
1176
  u_int32_t opaque_id = GET_OPAQUE_ID (lsid);
 
1177
  struct ospf_opaque_functab *functab;
 
1178
 
 
1179
  /* Switch output functionality by vty address. */
 
1180
  if (vty != NULL)
 
1181
    {
 
1182
      vty_out (vty, "  Opaque-Type %u (%s)%s", opaque_type,
 
1183
               ospf_opaque_type_name (opaque_type), VTY_NEWLINE);
 
1184
      vty_out (vty, "  Opaque-ID   0x%x%s", opaque_id, VTY_NEWLINE);
 
1185
 
 
1186
      vty_out (vty, "  Opaque-Info: %u octets of data%s%s",
 
1187
               ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
 
1188
               VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)",
 
1189
               VTY_NEWLINE);
 
1190
    }
 
1191
  else
 
1192
    {
 
1193
      zlog_info ("    Opaque-Type %u (%s)", opaque_type,
 
1194
                 ospf_opaque_type_name (opaque_type));
 
1195
      zlog_info ("    Opaque-ID   0x%x", opaque_id);
 
1196
 
 
1197
      zlog_info ("    Opaque-Info: %u octets of data%s",
 
1198
               ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
 
1199
               VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)");
 
1200
    }
 
1201
 
 
1202
  /* Call individual output functions. */
 
1203
  if ((functab = ospf_opaque_functab_lookup (lsa)) != NULL)
 
1204
    if (functab->show_opaque_info != NULL)
 
1205
      (* functab->show_opaque_info)(vty, lsa);
 
1206
 
 
1207
  return;
 
1208
}
 
1209
 
 
1210
void
 
1211
ospf_opaque_lsa_dump (struct stream *s, u_int16_t length)
 
1212
{
 
1213
  struct ospf_lsa lsa;
 
1214
 
 
1215
  lsa.data = (struct lsa_header *) STREAM_PNT (s);
 
1216
  show_opaque_info_detail (NULL, &lsa);
 
1217
  return;
 
1218
}
 
1219
 
 
1220
static int
 
1221
ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa)
 
1222
{
 
1223
  list funclist;
 
1224
  int rc = -1;
 
1225
 
 
1226
  /*
 
1227
   * Some Opaque-LSA user may want to monitor every LSA installation
 
1228
   * into the LSDB, regardless with target LSA type.
 
1229
   */
 
1230
  funclist = ospf_opaque_wildcard_funclist;
 
1231
  if (new_lsa_callback (funclist, lsa) != 0)
 
1232
    goto out;
 
1233
 
 
1234
  funclist = ospf_opaque_type9_funclist;
 
1235
  if (new_lsa_callback (funclist, lsa) != 0)
 
1236
    goto out;
 
1237
 
 
1238
  funclist = ospf_opaque_type10_funclist;
 
1239
  if (new_lsa_callback (funclist, lsa) != 0)
 
1240
    goto out;
 
1241
 
 
1242
  funclist = ospf_opaque_type11_funclist;
 
1243
  if (new_lsa_callback (funclist, lsa) != 0)
 
1244
    goto out;
 
1245
 
 
1246
  rc = 0;
 
1247
out:
 
1248
  return rc;
 
1249
}
 
1250
 
 
1251
static int
 
1252
ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa)
 
1253
{
 
1254
  list funclist;
 
1255
  int rc = -1;
 
1256
 
 
1257
  /*
 
1258
   * Some Opaque-LSA user may want to monitor every LSA deletion
 
1259
   * from the LSDB, regardless with target LSA type.
 
1260
   */
 
1261
  funclist = ospf_opaque_wildcard_funclist;
 
1262
  if (del_lsa_callback (funclist, lsa) != 0)
 
1263
    goto out;
 
1264
 
 
1265
  funclist = ospf_opaque_type9_funclist;
 
1266
  if (del_lsa_callback (funclist, lsa) != 0)
 
1267
    goto out;
 
1268
 
 
1269
  funclist = ospf_opaque_type10_funclist;
 
1270
  if (del_lsa_callback (funclist, lsa) != 0)
 
1271
    goto out;
 
1272
 
 
1273
  funclist = ospf_opaque_type11_funclist;
 
1274
  if (del_lsa_callback (funclist, lsa) != 0)
 
1275
    goto out;
 
1276
 
 
1277
  rc = 0;
 
1278
out:
 
1279
  return rc;
 
1280
}
 
1281
 
 
1282
/*------------------------------------------------------------------------*
 
1283
 * Followings are Opaque-LSA origination/refresh management functions.
 
1284
 *------------------------------------------------------------------------*/
 
1285
 
 
1286
static int ospf_opaque_type9_lsa_originate (struct thread *t);
 
1287
static int ospf_opaque_type10_lsa_originate (struct thread *t);
 
1288
static int ospf_opaque_type11_lsa_originate (struct thread *t);
 
1289
static void ospf_opaque_lsa_reoriginate_resume (list listtop, void *arg);
 
1290
 
 
1291
void
 
1292
ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0)
 
1293
{
 
1294
  struct ospf *top;
 
1295
  struct ospf_area *area;
 
1296
  listnode node;
 
1297
  struct opaque_info_per_type *oipt;
 
1298
  int delay = 0;
 
1299
 
 
1300
  if ((top = oi_to_top (oi)) == NULL || (area = oi->area) == NULL)
 
1301
    {
 
1302
      zlog_warn ("ospf_opaque_lsa_originate_schedule: Invalid argument?");
 
1303
      goto out;
 
1304
    }
 
1305
 
 
1306
  /* It may not a right time to schedule origination now. */
 
1307
  if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
 
1308
    {
 
1309
      if (IS_DEBUG_OSPF_EVENT)
 
1310
        zlog_info ("ospf_opaque_lsa_originate_schedule: Not operational.");
 
1311
      goto out; /* This is not an error. */
 
1312
    }
 
1313
  if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
 
1314
    {
 
1315
      if (IS_DEBUG_OSPF_EVENT)
 
1316
        zlog_info ("ospf_opaque_lsa_originate_schedule: Under blockade.");
 
1317
      goto out; /* This is not an error, too. */
 
1318
    }
 
1319
 
 
1320
  if (delay0 != NULL)
 
1321
    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
  ospf_opaque_lsa_reoriginate_resume (  oi->opaque_lsa_self, (void *)   oi);
 
1328
  ospf_opaque_lsa_reoriginate_resume (area->opaque_lsa_self, (void *) area);
 
1329
  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
  if (! list_isempty (ospf_opaque_type9_funclist)
 
1335
  &&    list_isempty (oi->opaque_lsa_self)
 
1336
  &&    oi->t_opaque_lsa_self == NULL)
 
1337
    {
 
1338
      if (IS_DEBUG_OSPF_EVENT)
 
1339
        zlog_info ("Schedule Type-9 Opaque-LSA origination in %d sec later.", delay);
 
1340
      oi->t_opaque_lsa_self =
 
1341
        thread_add_timer (master, ospf_opaque_type9_lsa_originate, oi, delay);
 
1342
      delay += OSPF_MIN_LS_INTERVAL;
 
1343
    }
 
1344
 
 
1345
  if (! list_isempty (ospf_opaque_type10_funclist)
 
1346
  &&    list_isempty (area->opaque_lsa_self)
 
1347
  &&    area->t_opaque_lsa_self == NULL)
 
1348
    {
 
1349
      /*
 
1350
       * One AREA may contain multiple OIs, but above 2nd and 3rd
 
1351
       * conditions prevent from scheduling the originate function
 
1352
       * again and again.
 
1353
       */
 
1354
      if (IS_DEBUG_OSPF_EVENT)
 
1355
        zlog_info ("Schedule Type-10 Opaque-LSA origination in %d sec later.", delay);
 
1356
      area->t_opaque_lsa_self =
 
1357
        thread_add_timer (master, ospf_opaque_type10_lsa_originate,
 
1358
                          area, delay);
 
1359
      delay += OSPF_MIN_LS_INTERVAL;
 
1360
    }
 
1361
 
 
1362
  if (! list_isempty (ospf_opaque_type11_funclist)
 
1363
  &&    list_isempty (top->opaque_lsa_self)
 
1364
  &&    top->t_opaque_lsa_self == NULL)
 
1365
    {
 
1366
      /*
 
1367
       * One OSPF may contain multiple AREAs, but above 2nd and 3rd
 
1368
       * conditions prevent from scheduling the originate function
 
1369
       * again and again.
 
1370
       */
 
1371
      if (IS_DEBUG_OSPF_EVENT)
 
1372
        zlog_info ("Schedule Type-11 Opaque-LSA origination in %d sec later.", delay);
 
1373
      top->t_opaque_lsa_self =
 
1374
        thread_add_timer (master, ospf_opaque_type11_lsa_originate,
 
1375
                          top, delay);
 
1376
      delay += OSPF_MIN_LS_INTERVAL;
 
1377
    }
 
1378
 
 
1379
  /*
 
1380
   * Following section treats a special situation that this node's
 
1381
   * opaque capability has changed as "ON -> OFF -> ON".
 
1382
   */
 
1383
  if (! list_isempty (ospf_opaque_type9_funclist)
 
1384
  &&  ! list_isempty (oi->opaque_lsa_self))
 
1385
    {
 
1386
      for (node = listhead (oi->opaque_lsa_self); node; nextnode (node))
 
1387
        {
 
1388
          /* 
 
1389
           * removed the test for
 
1390
           *   (! list_isempty (oipt->id_list))   * Handler is already active. *
 
1391
           * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
 
1392
           * not being empty.
 
1393
           */
 
1394
          if ((oipt = getdata (node))  == NULL /* Something wrong? */
 
1395
          ||   oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
 
1396
          ||   oipt->status == PROC_SUSPEND)   /* Cannot originate now. */
 
1397
              continue;
 
1398
 
 
1399
          ospf_opaque_lsa_reoriginate_schedule ((void *) oi,
 
1400
            OSPF_OPAQUE_LINK_LSA, oipt->opaque_type);
 
1401
        }
 
1402
    }
 
1403
 
 
1404
  if (! list_isempty (ospf_opaque_type10_funclist)
 
1405
  &&  ! list_isempty (area->opaque_lsa_self))
 
1406
    {
 
1407
      for (node = listhead (area->opaque_lsa_self); node; nextnode (node))
 
1408
        {
 
1409
          /* 
 
1410
           * removed the test for
 
1411
           *   (! list_isempty (oipt->id_list))   * Handler is already active. *
 
1412
           * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
 
1413
           * not being empty.
 
1414
           */
 
1415
          if ((oipt = getdata (node))  == NULL /* Something wrong? */
 
1416
          ||   oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
 
1417
          ||   oipt->status == PROC_SUSPEND)   /* Cannot originate now. */
 
1418
            continue;
 
1419
 
 
1420
          ospf_opaque_lsa_reoriginate_schedule ((void *) area,
 
1421
            OSPF_OPAQUE_AREA_LSA, oipt->opaque_type);
 
1422
        }
 
1423
    }
 
1424
 
 
1425
  if (! list_isempty (ospf_opaque_type11_funclist)
 
1426
  &&  ! list_isempty (top->opaque_lsa_self))
 
1427
    {
 
1428
      for (node = listhead (top->opaque_lsa_self); node; nextnode (node))
 
1429
        {
 
1430
          /* 
 
1431
           * removed the test for
 
1432
           *   (! list_isempty (oipt->id_list))   * Handler is already active. *
 
1433
           * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
 
1434
           * not being empty.
 
1435
           */
 
1436
          if ((oipt = getdata (node))  == NULL /* Something wrong? */
 
1437
          ||   oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
 
1438
          ||   oipt->status == PROC_SUSPEND)   /* Cannot originate now. */
 
1439
            continue;
 
1440
 
 
1441
          ospf_opaque_lsa_reoriginate_schedule ((void *) top,
 
1442
            OSPF_OPAQUE_AS_LSA, oipt->opaque_type);
 
1443
        }
 
1444
    }
 
1445
 
 
1446
  if (delay0 != NULL)
 
1447
    *delay0 = delay;
 
1448
 
 
1449
out:
 
1450
  return;
 
1451
}
 
1452
 
 
1453
static int
 
1454
ospf_opaque_type9_lsa_originate (struct thread *t)
 
1455
{
 
1456
  struct ospf_interface *oi;
 
1457
  int rc;
 
1458
 
 
1459
  oi = THREAD_ARG (t);
 
1460
  oi->t_opaque_lsa_self = NULL;
 
1461
 
 
1462
  if (IS_DEBUG_OSPF_EVENT)
 
1463
    zlog_info ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
 
1464
                IF_NAME (oi));
 
1465
 
 
1466
  rc = opaque_lsa_originate_callback (ospf_opaque_type9_funclist, oi);
 
1467
 
 
1468
  return rc;
 
1469
}
 
1470
 
 
1471
static int
 
1472
ospf_opaque_type10_lsa_originate (struct thread *t)
 
1473
{
 
1474
  struct ospf_area *area;
 
1475
  int rc;
 
1476
 
 
1477
  area = THREAD_ARG (t);
 
1478
  area->t_opaque_lsa_self = NULL;
 
1479
 
 
1480
  if (IS_DEBUG_OSPF_EVENT)
 
1481
    zlog_info ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
 
1482
                inet_ntoa (area->area_id));
 
1483
 
 
1484
  rc = opaque_lsa_originate_callback (ospf_opaque_type10_funclist, area);
 
1485
 
 
1486
  return rc;
 
1487
}
 
1488
 
 
1489
static int
 
1490
ospf_opaque_type11_lsa_originate (struct thread *t)
 
1491
{
 
1492
  struct ospf *top;
 
1493
  int rc;
 
1494
 
 
1495
  top = THREAD_ARG (t);
 
1496
  top->t_opaque_lsa_self = NULL;
 
1497
 
 
1498
  if (IS_DEBUG_OSPF_EVENT)
 
1499
    zlog_info ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
 
1500
 
 
1501
  rc = opaque_lsa_originate_callback (ospf_opaque_type11_funclist, top);
 
1502
 
 
1503
  return rc;
 
1504
}
 
1505
 
 
1506
static void
 
1507
ospf_opaque_lsa_reoriginate_resume (list listtop, void *arg)
 
1508
{
 
1509
  listnode node;
 
1510
  struct opaque_info_per_type *oipt;
 
1511
  struct ospf_opaque_functab *functab;
 
1512
 
 
1513
  if (listtop == NULL)
 
1514
    goto out;
 
1515
 
 
1516
  /*
 
1517
   * Pickup oipt entries those which in SUSPEND status, and give
 
1518
   * them a chance to start re-origination now.
 
1519
   */
 
1520
  for (node = listhead (listtop); node; nextnode (node))
 
1521
    {
 
1522
      if ((oipt = getdata (node)) == NULL
 
1523
      ||   oipt->status != PROC_SUSPEND)
 
1524
          continue;
 
1525
 
 
1526
      oipt->status = PROC_NORMAL;
 
1527
 
 
1528
      if ((functab = oipt->functab) == NULL
 
1529
      ||   functab->lsa_originator  == NULL)
 
1530
        continue;
 
1531
 
 
1532
      if ((* functab->lsa_originator)(arg) != 0)
 
1533
        {
 
1534
          zlog_warn ("ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", oipt->opaque_type);
 
1535
          continue;
 
1536
        }
 
1537
    }
 
1538
 
 
1539
out:
 
1540
  return;
 
1541
}
 
1542
 
 
1543
struct ospf_lsa *
 
1544
ospf_opaque_lsa_install (struct ospf_lsa *lsa, int rt_recalc)
 
1545
{
 
1546
  struct ospf_lsa *new = NULL;
 
1547
  struct opaque_info_per_type *oipt;
 
1548
  struct opaque_info_per_id *oipi;
 
1549
  struct ospf *top;
 
1550
 
 
1551
  /* Don't take "rt_recalc" into consideration for now. *//* XXX */
 
1552
 
 
1553
  if (! IS_LSA_SELF (lsa))
 
1554
    {
 
1555
      new = lsa; /* Don't touch this LSA. */
 
1556
      goto out;
 
1557
    }
 
1558
 
 
1559
  if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
 
1560
    zlog_info ("Install Type-%u Opaque-LSA: [opaque-type=%u, opaque-id=%x]", lsa->data->type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)));
 
1561
 
 
1562
  /* Replace the existing lsa with the new one. */
 
1563
  if ((oipt = lookup_opaque_info_by_type (lsa)) != NULL
 
1564
  &&  (oipi = lookup_opaque_info_by_id (oipt, lsa)) != NULL)
 
1565
    {
 
1566
      ospf_lsa_unlock (oipi->lsa);
 
1567
      oipi->lsa = ospf_lsa_lock (lsa);
 
1568
    }
 
1569
  /* Register the new lsa entry and get its control info. */
 
1570
  else
 
1571
  if ((oipi = register_opaque_lsa (lsa)) == NULL)
 
1572
    {
 
1573
      zlog_warn ("ospf_opaque_lsa_install: register_opaque_lsa() ?");
 
1574
      goto out;
 
1575
    }
 
1576
 
 
1577
  /*
 
1578
   * Make use of a common mechanism (ospf_lsa_refresh_walker)
 
1579
   * for periodic refresh of self-originated Opaque-LSAs.
 
1580
   */
 
1581
  switch (lsa->data->type)
 
1582
    {
 
1583
    case OSPF_OPAQUE_LINK_LSA:
 
1584
      if ((top = oi_to_top (lsa->oi)) == NULL)
 
1585
        {
 
1586
          /* Above conditions must have passed. */
 
1587
          zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
 
1588
          goto out;
 
1589
        }
 
1590
      break;
 
1591
    case OSPF_OPAQUE_AREA_LSA:
 
1592
      if (lsa->area == NULL || (top = lsa->area->ospf) == NULL)
 
1593
        {
 
1594
          /* Above conditions must have passed. */
 
1595
          zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
 
1596
          goto out;
 
1597
        }
 
1598
      break;
 
1599
    case OSPF_OPAQUE_AS_LSA:
 
1600
      top = ospf_lookup ();
 
1601
      if (lsa->area != NULL && (top = lsa->area->ospf) == NULL)
 
1602
        {
 
1603
          /* Above conditions must have passed. */
 
1604
          zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
 
1605
          goto out;
 
1606
        }
 
1607
      break;
 
1608
    default:
 
1609
      zlog_warn ("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", lsa->data->type);
 
1610
      goto out;
 
1611
    }
 
1612
 
 
1613
  ospf_refresher_register_lsa (top, lsa);
 
1614
  new = lsa;
 
1615
 
 
1616
out:
 
1617
  return new;
 
1618
}
 
1619
 
 
1620
void
 
1621
ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
 
1622
{
 
1623
  struct ospf *ospf;
 
1624
  struct ospf_opaque_functab *functab;
 
1625
 
 
1626
  ospf = ospf_lookup ();
 
1627
 
 
1628
  if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL
 
1629
  ||   functab->lsa_refresher == NULL)
 
1630
    {
 
1631
      /*
 
1632
       * Though this LSA seems to have originated on this node, the
 
1633
       * handling module for this "lsa-type and opaque-type" was
 
1634
       * already deleted sometime ago.
 
1635
       * Anyway, this node still has a responsibility to flush this
 
1636
       * LSA from the routing domain.
 
1637
       */
 
1638
      if (IS_DEBUG_OSPF_EVENT)
 
1639
        zlog_info ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id));
 
1640
 
 
1641
      lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
 
1642
      ospf_lsa_maxage (ospf, lsa);
 
1643
    }
 
1644
  else
 
1645
    (* functab->lsa_refresher)(lsa);
 
1646
 
 
1647
  return;
 
1648
}
 
1649
 
 
1650
/*------------------------------------------------------------------------*
 
1651
 * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
 
1652
 * triggered by external interventions (vty session, signaling, etc).
 
1653
 *------------------------------------------------------------------------*/
 
1654
 
 
1655
#define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
 
1656
      if (!(T)) \
 
1657
        (T) = thread_add_timer (master, (F), (L), (V))
 
1658
 
 
1659
static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type);
 
1660
static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t);
 
1661
static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t);
 
1662
static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t);
 
1663
static int ospf_opaque_lsa_refresh_timer (struct thread *t);
 
1664
 
 
1665
void
 
1666
ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
 
1667
                                      u_char lsa_type, u_char opaque_type)
 
1668
{
 
1669
  struct ospf *top;
 
1670
  struct ospf_area dummy, *area = NULL;
 
1671
  struct ospf_interface *oi = NULL;
 
1672
 
 
1673
  struct ospf_lsa *lsa;
 
1674
  struct opaque_info_per_type *oipt;
 
1675
  int (* func)(struct thread *t) = NULL;
 
1676
  int delay;
 
1677
 
 
1678
  switch (lsa_type)
 
1679
    {
 
1680
    case OSPF_OPAQUE_LINK_LSA:
 
1681
      if ((oi = (struct ospf_interface *) lsa_type_dependent) == NULL)
 
1682
        {
 
1683
          zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Type-9 Opaque-LSA: Invalid parameter?");
 
1684
          goto out;
 
1685
        }
 
1686
      if ((top = oi_to_top (oi)) == NULL)
 
1687
        {
 
1688
          zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?", IF_NAME (oi));
 
1689
          goto out;
 
1690
        }
 
1691
      if (! list_isempty (ospf_opaque_type9_funclist)
 
1692
      &&    list_isempty (oi->opaque_lsa_self)
 
1693
      &&    oi->t_opaque_lsa_self != NULL)
 
1694
        {
 
1695
          zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u): Common origination for OI(%s) has already started", opaque_type, IF_NAME (oi));
 
1696
          goto out;
 
1697
        }
 
1698
      func = ospf_opaque_type9_lsa_reoriginate_timer;
 
1699
      break;
 
1700
    case OSPF_OPAQUE_AREA_LSA:
 
1701
      if ((area = (struct ospf_area *) lsa_type_dependent) == NULL)
 
1702
        {
 
1703
          zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Type-10 Opaque-LSA: Invalid parameter?");
 
1704
          goto out;
 
1705
        }
 
1706
      if ((top = area->ospf) == NULL)
 
1707
        {
 
1708
          zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: AREA(%s) -> TOP?", inet_ntoa (area->area_id));
 
1709
          goto out;
 
1710
        }
 
1711
      if (! list_isempty (ospf_opaque_type10_funclist)
 
1712
      &&    list_isempty (area->opaque_lsa_self)
 
1713
      &&    area->t_opaque_lsa_self != NULL)
 
1714
        {
 
1715
          zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u): Common origination for AREA(%s) has already started", opaque_type, inet_ntoa (area->area_id));
 
1716
          goto out;
 
1717
        }
 
1718
      func = ospf_opaque_type10_lsa_reoriginate_timer;
 
1719
      break;
 
1720
    case OSPF_OPAQUE_AS_LSA:
 
1721
      if ((top = (struct ospf *) lsa_type_dependent) == NULL)
 
1722
        {
 
1723
          zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Type-11 Opaque-LSA: Invalid parameter?");
 
1724
          goto out;
 
1725
        }
 
1726
      if (! list_isempty (ospf_opaque_type11_funclist)
 
1727
      &&    list_isempty (top->opaque_lsa_self)
 
1728
      &&    top->t_opaque_lsa_self != NULL)
 
1729
        {
 
1730
          zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u): Common origination has already started", 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:
 
1741
      zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Unexpected LSA-type(%u)", lsa_type);
 
1742
      goto out;
 
1743
    }
 
1744
 
 
1745
  /* It may not a right time to schedule reorigination now. */
 
1746
  if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
 
1747
    {
 
1748
      if (IS_DEBUG_OSPF_EVENT)
 
1749
        zlog_info ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
 
1750
      goto out; /* This is not an error. */
 
1751
    }
 
1752
  if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
 
1753
    {
 
1754
      if (IS_DEBUG_OSPF_EVENT)
 
1755
        zlog_info ("ospf_opaque_lsa_reoriginate_schedule: Under blockade.");
 
1756
      goto out; /* This is not an error, too. */
 
1757
    }
 
1758
 
 
1759
  /* Generate a dummy lsa to be passed for a lookup function. */
 
1760
  lsa = pseudo_lsa (oi, area, lsa_type, opaque_type);
 
1761
 
 
1762
  if ((oipt = lookup_opaque_info_by_type (lsa)) == NULL)
 
1763
    {
 
1764
      struct ospf_opaque_functab *functab;
 
1765
      if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL)
 
1766
        {
 
1767
          zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: No associated function?: lsa_type(%u), opaque_type(%u)", lsa_type, opaque_type);
 
1768
          goto out;
 
1769
        }
 
1770
      if ((oipt = register_opaque_info_per_type (functab, lsa)) == NULL)
 
1771
        {
 
1772
          zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Cannot get a control info?: lsa_type(%u), opaque_type(%u)", lsa_type, opaque_type);
 
1773
          goto out;
 
1774
        }
 
1775
    }
 
1776
 
 
1777
  if (oipt->t_opaque_lsa_self != NULL)
 
1778
    {
 
1779
      if (IS_DEBUG_OSPF_EVENT)
 
1780
        zlog_info ("Type-%u Opaque-LSA has already scheduled to RE-ORIGINATE: [opaque-type=%u]", lsa_type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
 
1781
      goto out;
 
1782
    }
 
1783
 
 
1784
  /*
 
1785
   * Different from initial origination time, in which various conditions
 
1786
   * (opaque capability, neighbor status etc) are assured by caller of
 
1787
   * the originating function "ospf_opaque_lsa_originate_schedule ()",
 
1788
   * it is highly possible that these conditions might not be satisfied
 
1789
   * at the time of re-origination function is to be called.
 
1790
   */
 
1791
  delay = OSPF_MIN_LS_INTERVAL; /* XXX */
 
1792
 
 
1793
  if (IS_DEBUG_OSPF_EVENT)
 
1794
    zlog_info ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d sec later: [opaque-type=%u]", lsa_type, delay, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
 
1795
 
 
1796
  OSPF_OPAQUE_TIMER_ON (oipt->t_opaque_lsa_self, func, oipt, delay);
 
1797
 
 
1798
out:
 
1799
  return;
 
1800
}
 
1801
 
 
1802
static struct ospf_lsa *
 
1803
pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area,
 
1804
            u_char lsa_type, u_char opaque_type)
 
1805
{
 
1806
  static struct ospf_lsa lsa = { 0 };
 
1807
  static struct lsa_header lsah = { 0 };
 
1808
  u_int32_t tmp;
 
1809
 
 
1810
  lsa.oi   = oi;
 
1811
  lsa.area = area;
 
1812
  lsa.data = &lsah;
 
1813
 
 
1814
  lsah.type = lsa_type;
 
1815
  tmp = SET_OPAQUE_LSID (opaque_type, 0); /* Opaque-ID is unused here. */
 
1816
  lsah.id.s_addr = htonl (tmp);
 
1817
 
 
1818
  return &lsa;
 
1819
}
 
1820
 
 
1821
static int
 
1822
ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t)
 
1823
{
 
1824
  struct opaque_info_per_type *oipt;
 
1825
  struct ospf_opaque_functab *functab;
 
1826
  struct ospf *top;
 
1827
  struct ospf_interface *oi;
 
1828
  int rc = -1;
 
1829
 
 
1830
  oipt = THREAD_ARG (t);
 
1831
  oipt->t_opaque_lsa_self = NULL;
 
1832
 
 
1833
  if ((functab = oipt->functab) == NULL
 
1834
  ||   functab->lsa_originator == NULL)
 
1835
    {
 
1836
      zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
 
1837
      goto out;
 
1838
    }
 
1839
 
 
1840
  oi = (struct ospf_interface *) oipt->owner;
 
1841
  if ((top = oi_to_top (oi)) == NULL)
 
1842
    {
 
1843
      zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
 
1844
      goto out;
 
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
    {
 
1851
      if (IS_DEBUG_OSPF_EVENT)
 
1852
        zlog_info ("Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
 
1853
    
 
1854
      oipt->status = PROC_SUSPEND;
 
1855
      rc = 0;
 
1856
      goto out;
 
1857
    }
 
1858
 
 
1859
  if (IS_DEBUG_OSPF_EVENT)
 
1860
    zlog_info ("Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)", oipt->opaque_type, IF_NAME (oi));
 
1861
 
 
1862
  rc = (* functab->lsa_originator)(oi);
 
1863
out:
 
1864
  return rc;
 
1865
}
 
1866
 
 
1867
static int
 
1868
ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t)
 
1869
{
 
1870
  struct opaque_info_per_type *oipt;
 
1871
  struct ospf_opaque_functab *functab;
 
1872
  listnode node;
 
1873
  struct ospf *top;
 
1874
  struct ospf_area *area;
 
1875
  struct ospf_interface *oi;
 
1876
  int n, rc = -1;
 
1877
 
 
1878
  oipt = THREAD_ARG (t);
 
1879
  oipt->t_opaque_lsa_self = NULL;
 
1880
 
 
1881
  if ((functab = oipt->functab) == NULL
 
1882
  ||   functab->lsa_originator == NULL)
 
1883
    {
 
1884
      zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
 
1885
      goto out;
 
1886
    }
 
1887
 
 
1888
  area = (struct ospf_area *) oipt->owner;
 
1889
  if (area == NULL || (top = area->ospf) == NULL)
 
1890
    {
 
1891
      zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
 
1892
      goto out;
 
1893
    }
 
1894
 
 
1895
  /* There must be at least one "opaque-capable, full-state" neighbor. */
 
1896
  n = 0;
 
1897
  for (node = listhead (area->oiflist); node; nextnode (node))
 
1898
    {
 
1899
      if ((oi = getdata (node)) == NULL)
 
1900
        continue;
 
1901
      if ((n = ospf_nbr_count_opaque_capable (oi)) > 0)
 
1902
        break;
 
1903
    }
 
1904
 
 
1905
  if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
 
1906
    {
 
1907
      if (IS_DEBUG_OSPF_EVENT)
 
1908
        zlog_info ("Suspend re-origination of Type-10 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
 
1909
 
 
1910
      oipt->status = PROC_SUSPEND;
 
1911
      rc = 0;
 
1912
      goto out;
 
1913
    }
 
1914
 
 
1915
  if (IS_DEBUG_OSPF_EVENT)
 
1916
    zlog_info ("Timer[Type10-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for Area %s", oipt->opaque_type, inet_ntoa (area->area_id));
 
1917
 
 
1918
  rc = (* functab->lsa_originator)(area);
 
1919
out:
 
1920
  return rc;
 
1921
}
 
1922
 
 
1923
static int
 
1924
ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t)
 
1925
{
 
1926
  struct opaque_info_per_type *oipt;
 
1927
  struct ospf_opaque_functab *functab;
 
1928
  struct ospf *top;
 
1929
  int rc = -1;
 
1930
 
 
1931
  oipt = THREAD_ARG (t);
 
1932
  oipt->t_opaque_lsa_self = NULL;
 
1933
 
 
1934
  if ((functab = oipt->functab) == NULL
 
1935
  ||   functab->lsa_originator == NULL)
 
1936
    {
 
1937
      zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: No associated function?");
 
1938
      goto out;
 
1939
    }
 
1940
 
 
1941
  if ((top = (struct ospf *) oipt->owner) == NULL)
 
1942
    {
 
1943
      zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
 
1944
      goto out;
 
1945
    }
 
1946
 
 
1947
  if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
 
1948
    {
 
1949
      if (IS_DEBUG_OSPF_EVENT)
 
1950
        zlog_info ("Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
 
1951
    
 
1952
      oipt->status = PROC_SUSPEND;
 
1953
      rc = 0;
 
1954
      goto out;
 
1955
    }
 
1956
 
 
1957
  if (IS_DEBUG_OSPF_EVENT)
 
1958
    zlog_info ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type);
 
1959
 
 
1960
  rc = (* functab->lsa_originator)(top);
 
1961
out:
 
1962
  return rc;
 
1963
}
 
1964
 
 
1965
extern int ospf_lsa_refresh_delay (struct ospf_lsa *); /* ospf_lsa.c */
 
1966
 
 
1967
void
 
1968
ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
 
1969
{
 
1970
  struct ospf *ospf = ospf;
 
1971
  struct opaque_info_per_type *oipt;
 
1972
  struct opaque_info_per_id *oipi;
 
1973
  struct ospf_lsa *lsa;
 
1974
  int delay;
 
1975
 
 
1976
  ospf = ospf_lookup ();
 
1977
 
 
1978
  if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
 
1979
  ||  (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
 
1980
    {
 
1981
      zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
 
1982
      goto out;
 
1983
    }
 
1984
 
 
1985
  /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
 
1986
  if ((lsa = oipi->lsa) == NULL)
 
1987
    {
 
1988
      zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
 
1989
      goto out;
 
1990
    }
 
1991
 
 
1992
  if (oipi->t_opaque_lsa_self != NULL)
 
1993
    {
 
1994
      if (IS_DEBUG_OSPF_EVENT)
 
1995
        zlog_info ("Type-%u Opaque-LSA has already scheduled to REFRESH: [opaque-type=%u, opaque-id=%x]", lsa->data->type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)));
 
1996
      goto out;
 
1997
    }
 
1998
 
 
1999
  /* Delete this lsa from neighbor retransmit-list. */
 
2000
  switch (lsa->data->type)
 
2001
    {
 
2002
    case OSPF_OPAQUE_LINK_LSA:
 
2003
    case OSPF_OPAQUE_AREA_LSA:
 
2004
      ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
 
2005
      break;
 
2006
    case OSPF_OPAQUE_AS_LSA:
 
2007
      ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
 
2008
      break;
 
2009
    default:
 
2010
      zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type);
 
2011
      goto out;
 
2012
    }
 
2013
 
 
2014
  delay = ospf_lsa_refresh_delay (lsa);
 
2015
 
 
2016
  if (IS_DEBUG_OSPF_EVENT)
 
2017
    zlog_info ("Schedule Type-%u Opaque-LSA to REFRESH in %d sec later: [opaque-type=%u, opaque-id=%x]", lsa->data->type, delay, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)));
 
2018
 
 
2019
  OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self,
 
2020
                        ospf_opaque_lsa_refresh_timer, oipi, delay);
 
2021
out:
 
2022
  return;
 
2023
}
 
2024
 
 
2025
static int
 
2026
ospf_opaque_lsa_refresh_timer (struct thread *t)
 
2027
{
 
2028
  struct opaque_info_per_id *oipi;
 
2029
  struct ospf_opaque_functab *functab;
 
2030
  struct ospf_lsa *lsa;
 
2031
 
 
2032
  if (IS_DEBUG_OSPF_EVENT)
 
2033
    zlog_info ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
 
2034
 
 
2035
  oipi = THREAD_ARG (t);
 
2036
  oipi->t_opaque_lsa_self = NULL;
 
2037
 
 
2038
  if ((lsa = oipi->lsa) != NULL)
 
2039
    if ((functab = oipi->opqctl_type->functab) != NULL)
 
2040
      if (functab->lsa_refresher != NULL)
 
2041
        (* functab->lsa_refresher)(lsa);
 
2042
 
 
2043
  return 0;
 
2044
}
 
2045
 
 
2046
void
 
2047
ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
 
2048
{
 
2049
  struct ospf *ospf = ospf;
 
2050
  struct opaque_info_per_type *oipt;
 
2051
  struct opaque_info_per_id *oipi;
 
2052
  struct ospf_lsa *lsa;
 
2053
 
 
2054
  ospf = ospf_lookup ();
 
2055
 
 
2056
  if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
 
2057
  ||  (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
 
2058
    {
 
2059
      zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
 
2060
      goto out;
 
2061
    }
 
2062
 
 
2063
  /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
 
2064
  if ((lsa = oipi->lsa) == NULL)
 
2065
    {
 
2066
      zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
 
2067
      goto out;
 
2068
    }
 
2069
 
 
2070
  /* Delete this lsa from neighbor retransmit-list. */
 
2071
  switch (lsa->data->type)
 
2072
    {
 
2073
    case OSPF_OPAQUE_LINK_LSA:
 
2074
    case OSPF_OPAQUE_AREA_LSA:
 
2075
      ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
 
2076
      break;
 
2077
    case OSPF_OPAQUE_AS_LSA:
 
2078
      ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
 
2079
      break;
 
2080
    default:
 
2081
      zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type);
 
2082
      goto out;
 
2083
    }
 
2084
 
 
2085
  /* Dequeue listnode entry from the list. */
 
2086
  listnode_delete (oipt->id_list, oipi);
 
2087
 
 
2088
  /* Avoid misjudgement in the next lookup. */
 
2089
  if (listcount (oipt->id_list) == 0)
 
2090
    oipt->id_list->head = oipt->id_list->tail = NULL;
 
2091
 
 
2092
  /* Disassociate internal control information with the given lsa. */
 
2093
  oipi->lsa = NULL;
 
2094
  free_opaque_info_per_id ((void *) oipi);
 
2095
 
 
2096
  /* Force given lsa's age to MaxAge. */
 
2097
  lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
 
2098
 
 
2099
  if (IS_DEBUG_OSPF_EVENT)
 
2100
    zlog_info ("Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]", lsa->data->type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)));
 
2101
 
 
2102
  /* This lsa will be flushed and removed eventually. */
 
2103
  ospf_lsa_maxage (ospf, lsa);
 
2104
 
 
2105
out:
 
2106
  return;
 
2107
}
 
2108
 
 
2109
/*------------------------------------------------------------------------*
 
2110
 * Followings are control functions to block origination after restart.
 
2111
 *------------------------------------------------------------------------*/
 
2112
 
 
2113
static void ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs, struct ospf_neighbor *inbr, struct ospf_lsa *lsa);
 
2114
static void ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi);
 
2115
static void ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area);
 
2116
static void ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top);
 
2117
static unsigned long ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type);
 
2118
 
 
2119
void
 
2120
ospf_opaque_adjust_lsreq (struct ospf_neighbor *nbr, list lsas)
 
2121
{
 
2122
  struct ospf *top;
 
2123
  struct ospf_area *area;
 
2124
  struct ospf_interface *oi;
 
2125
  listnode node1, node2;
 
2126
  struct ospf_lsa *lsa;
 
2127
 
 
2128
  if ((top = oi_to_top (nbr->oi)) == NULL)
 
2129
    goto out;
 
2130
 
 
2131
  /*
 
2132
   * If an instance of self-originated Opaque-LSA is found in the given
 
2133
   * LSA list, and it is not installed to LSDB yet, exclude it from the
 
2134
   * list "nbr->ls_req". In this way, it is assured that an LSReq message,
 
2135
   * which might be sent in the process of flooding, will not request for
 
2136
   * the LSA to be flushed immediately; otherwise, depending on timing,
 
2137
   * an LSUpd message will carry instances of target LSAs with MaxAge,
 
2138
   * while other LSUpd message might carry old LSA instances (non-MaxAge).
 
2139
   * Obviously, the latter would trigger miserable situations that repeat
 
2140
   * installation and removal of unwanted LSAs indefinitely.
 
2141
   */
 
2142
  for (node1 = listhead (lsas); node1; nextnode (node1))
 
2143
    {
 
2144
      if ((lsa = getdata (node1)) == NULL)
 
2145
        continue;
 
2146
 
 
2147
      /* Filter out unwanted LSAs. */
 
2148
      if (! IS_OPAQUE_LSA (lsa->data->type))
 
2149
        continue;
 
2150
      if (! IPV4_ADDR_SAME (&lsa->data->adv_router, &top->router_id))
 
2151
        continue;
 
2152
 
 
2153
      /*
 
2154
       * Don't touch an LSA which has MaxAge; two possible cases.
 
2155
       *
 
2156
       *   1) This LSA has originally flushed by myself (received LSUpd
 
2157
       *      message's router-id is equal to my router-id), and flooded
 
2158
       *      back by an opaque-capable router.
 
2159
       *
 
2160
       *   2) This LSA has expired in an opaque-capable router and thus
 
2161
       *      flushed by the router.
 
2162
       */
 
2163
      if (IS_LSA_MAXAGE (lsa))
 
2164
        continue;
 
2165
 
 
2166
      /* If the LSA has installed in the LSDB, nothing to do here. */
 
2167
      if (ospf_lsa_lookup_by_header (nbr->oi->area, lsa->data) != NULL)
 
2168
        continue;
 
2169
 
 
2170
      /* Ok, here we go. */
 
2171
      switch (lsa->data->type)
 
2172
        {
 
2173
        case OSPF_OPAQUE_LINK_LSA:
 
2174
          oi = nbr->oi;
 
2175
          ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
 
2176
          break;
 
2177
        case OSPF_OPAQUE_AREA_LSA:
 
2178
          area = nbr->oi->area;
 
2179
          for (node2 = listhead (area->oiflist); node2; nextnode (node2))
 
2180
            {
 
2181
              if ((oi = getdata (node2)) == NULL)
 
2182
                continue;
 
2183
              ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
 
2184
            }
 
2185
          break;
 
2186
        case OSPF_OPAQUE_AS_LSA:
 
2187
          for (node2 = listhead (top->oiflist); node2; nextnode (node2))
 
2188
            {
 
2189
              if ((oi = getdata (node2)) == NULL)
 
2190
                continue;
 
2191
              ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
 
2192
            }
 
2193
          break;
 
2194
        default:
 
2195
          break;
 
2196
        }
 
2197
    }
 
2198
 
 
2199
out:
 
2200
  return;
 
2201
}
 
2202
 
 
2203
static void
 
2204
ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs,
 
2205
                                    struct ospf_neighbor *inbr,
 
2206
                                    struct ospf_lsa *lsa)
 
2207
{
 
2208
  struct route_node *rn;
 
2209
  struct ospf_neighbor *onbr;
 
2210
  struct ospf_lsa *ls_req;
 
2211
 
 
2212
  for (rn = route_top (nbrs); rn; rn = route_next (rn))
 
2213
    {
 
2214
      if ((onbr = rn->info) == NULL)
 
2215
        continue;
 
2216
      if (onbr == inbr)
 
2217
        continue;
 
2218
      if ((ls_req = ospf_ls_request_lookup (onbr, lsa)) == NULL)
 
2219
        continue;
 
2220
 
 
2221
      if (IS_DEBUG_OSPF_EVENT)
 
2222
        zlog_info ("LSA[%s]: Exclude this entry from LSReq to send.", dump_lsa_key (lsa));
 
2223
 
 
2224
      ospf_ls_request_delete (onbr, ls_req);
 
2225
/*    ospf_check_nbr_loading (onbr);*//* XXX */
 
2226
    }
 
2227
 
 
2228
  return;
 
2229
}
 
2230
 
 
2231
void
 
2232
ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr, list lsas)
 
2233
{
 
2234
  struct ospf *top;
 
2235
  listnode node, next;
 
2236
  struct ospf_lsa *lsa;
 
2237
  u_char before;
 
2238
 
 
2239
  if ((top = oi_to_top (nbr->oi)) == NULL)
 
2240
    goto out;
 
2241
 
 
2242
  before = IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque);
 
2243
 
 
2244
  for (node = listhead (lsas); node; node = next)
 
2245
    {
 
2246
      next = node->next;
 
2247
 
 
2248
      if ((lsa = getdata (node)) == NULL)
 
2249
        continue;
 
2250
 
 
2251
      listnode_delete (lsas, lsa);
 
2252
 
 
2253
      /*
 
2254
       * Since these LSA entries are not yet installed into corresponding
 
2255
       * LSDB, just flush them without calling ospf_ls_maxage() afterward.
 
2256
       */
 
2257
      lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
 
2258
      switch (lsa->data->type)
 
2259
        {
 
2260
        case OSPF_OPAQUE_LINK_LSA:
 
2261
          SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
 
2262
          ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
 
2263
          break;
 
2264
        case OSPF_OPAQUE_AREA_LSA:
 
2265
          SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
 
2266
          ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
 
2267
          break;
 
2268
        case OSPF_OPAQUE_AS_LSA:
 
2269
          SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
 
2270
          ospf_flood_through_as (top, NULL/*inbr*/, lsa);
 
2271
          break;
 
2272
        default:
 
2273
          zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
 
2274
          goto out;
 
2275
        }
 
2276
 
 
2277
      ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */
 
2278
    }
 
2279
 
 
2280
  if (before == 0 && IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
 
2281
    {
 
2282
      if (IS_DEBUG_OSPF_EVENT)
 
2283
        zlog_info ("Block Opaque-LSA origination: OFF -> ON");
 
2284
    }
 
2285
 
 
2286
out:
 
2287
  return;
 
2288
}
 
2289
 
 
2290
void
 
2291
ospf_opaque_ls_ack_received (struct ospf_neighbor *nbr, list acks)
 
2292
{
 
2293
  struct ospf *top;
 
2294
  listnode node;
 
2295
  struct ospf_lsa *lsa;
 
2296
  char type9_lsa_rcv = 0, type10_lsa_rcv = 0, type11_lsa_rcv = 0;
 
2297
 
 
2298
  if ((top = oi_to_top (nbr->oi)) == NULL)
 
2299
    goto out;
 
2300
 
 
2301
  for (node = listhead (acks); node; nextnode (node))
 
2302
    {
 
2303
      if ((lsa = getdata (node)) == NULL)
 
2304
        continue;
 
2305
 
 
2306
      switch (lsa->data->type)
 
2307
        {
 
2308
        case OSPF_OPAQUE_LINK_LSA:
 
2309
          type9_lsa_rcv = 1;
 
2310
          /* Callback function... */
 
2311
          break;
 
2312
        case OSPF_OPAQUE_AREA_LSA:
 
2313
          type10_lsa_rcv = 1;
 
2314
          /* Callback function... */
 
2315
          break;
 
2316
        case OSPF_OPAQUE_AS_LSA:
 
2317
          type11_lsa_rcv = 1;
 
2318
          /* Callback function... */
 
2319
          break;
 
2320
        default:
 
2321
          zlog_warn ("ospf_opaque_ls_ack_received: Unexpected LSA-type(%u)", lsa->data->type);
 
2322
          goto out;
 
2323
        }
 
2324
    }
 
2325
 
 
2326
  if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
 
2327
    {
 
2328
      int delay;
 
2329
      struct ospf_interface *oi;
 
2330
 
 
2331
      if (type9_lsa_rcv
 
2332
      &&  CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT))
 
2333
        ospf_opaque_type9_lsa_rxmt_nbr_check (nbr->oi);
 
2334
 
 
2335
      if (type10_lsa_rcv
 
2336
      &&  CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT))
 
2337
        ospf_opaque_type10_lsa_rxmt_nbr_check (nbr->oi->area);
 
2338
 
 
2339
      if (type11_lsa_rcv
 
2340
      &&  CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT))
 
2341
        ospf_opaque_type11_lsa_rxmt_nbr_check (top);
 
2342
 
 
2343
      if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
 
2344
        goto out; /* Blocking still in progress. */
 
2345
 
 
2346
      if (IS_DEBUG_OSPF_EVENT)
 
2347
        zlog_info ("Block Opaque-LSA origination: ON -> OFF");
 
2348
 
 
2349
      if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
 
2350
        goto out; /* Opaque capability condition must have changed. */
 
2351
 
 
2352
      /* Ok, let's start origination of Opaque-LSAs. */
 
2353
      delay = OSPF_MIN_LS_INTERVAL;
 
2354
      for (node = listhead (top->oiflist); node; nextnode (node))
 
2355
        {
 
2356
          if ((oi = getdata (node)) == NULL)
 
2357
            continue;
 
2358
 
 
2359
          if (! ospf_if_is_enable (oi)
 
2360
          ||    ospf_nbr_count_opaque_capable (oi) == 0)
 
2361
            continue;
 
2362
 
 
2363
          ospf_opaque_lsa_originate_schedule (oi, &delay);
 
2364
        }
 
2365
    }
 
2366
 
 
2367
out:
 
2368
  return;
 
2369
}
 
2370
 
 
2371
static void
 
2372
ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi)
 
2373
{
 
2374
  unsigned long n;
 
2375
 
 
2376
  n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_LINK_LSA);
 
2377
  if (n == 0)
 
2378
    {
 
2379
      if (IS_DEBUG_OSPF_EVENT)
 
2380
        zlog_info ("Self-originated type-9 Opaque-LSAs: OI(%s): Flush completed", IF_NAME (oi));
 
2381
 
 
2382
      UNSET_FLAG (oi->area->ospf->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
 
2383
    }
 
2384
  return;
 
2385
}
 
2386
 
 
2387
static void
 
2388
ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area)
 
2389
{
 
2390
  listnode node;
 
2391
  struct ospf_interface *oi;
 
2392
  unsigned long n = 0;
 
2393
 
 
2394
  for (node = listhead (area->oiflist); node; nextnode (node))
 
2395
    {
 
2396
      if ((oi = getdata (node)) == NULL)
 
2397
        continue;
 
2398
 
 
2399
      if (area->area_id.s_addr != OSPF_AREA_BACKBONE
 
2400
      &&  oi->type == OSPF_IFTYPE_VIRTUALLINK) 
 
2401
        continue;
 
2402
 
 
2403
      n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AREA_LSA);
 
2404
      if (n > 0)
 
2405
        break;
 
2406
    }
 
2407
 
 
2408
  if (n == 0)
 
2409
    {
 
2410
      if (IS_DEBUG_OSPF_EVENT)
 
2411
        zlog_info ("Self-originated type-10 Opaque-LSAs: AREA(%s): Flush completed", inet_ntoa (area->area_id));
 
2412
 
 
2413
      UNSET_FLAG (area->ospf->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
 
2414
    }
 
2415
 
 
2416
  return;
 
2417
}
 
2418
 
 
2419
static void
 
2420
ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top)
 
2421
{
 
2422
  listnode node;
 
2423
  struct ospf_interface *oi;
 
2424
  unsigned long n = 0;
 
2425
 
 
2426
  for (node = listhead (top->oiflist); node; nextnode (node))
 
2427
    {
 
2428
      if ((oi = getdata (node)) == NULL)
 
2429
        continue;
 
2430
 
 
2431
      switch (oi->type)
 
2432
        {
 
2433
        case OSPF_IFTYPE_VIRTUALLINK:
 
2434
          continue;
 
2435
        default:
 
2436
          break;
 
2437
        }
 
2438
 
 
2439
      n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AS_LSA);
 
2440
      if (n > 0)
 
2441
        goto out;
 
2442
    }
 
2443
 
 
2444
  if (n == 0)
 
2445
    {
 
2446
      if (IS_DEBUG_OSPF_EVENT)
 
2447
        zlog_info ("Self-originated type-11 Opaque-LSAs: Flush completed");
 
2448
 
 
2449
      UNSET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
 
2450
    }
 
2451
 
 
2452
out:
 
2453
  return;
 
2454
}
 
2455
 
 
2456
static unsigned long
 
2457
ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type)
 
2458
{
 
2459
  struct route_node *rn;
 
2460
  struct ospf_neighbor *nbr;
 
2461
  struct ospf *top;
 
2462
  unsigned long n = 0;
 
2463
 
 
2464
  for (rn = route_top (nbrs); rn; rn = route_next (rn))
 
2465
    {
 
2466
      if ((nbr = rn->info) == NULL)
 
2467
        continue;
 
2468
      if ((top = oi_to_top (nbr->oi)) == NULL)
 
2469
        continue;
 
2470
      if (IPV4_ADDR_SAME (&nbr->router_id, &top->router_id))
 
2471
        continue;
 
2472
      n += ospf_ls_retransmit_count_self (nbr, lsa_type);
 
2473
    }
 
2474
 
 
2475
  return n;
 
2476
}
 
2477
 
 
2478
/*------------------------------------------------------------------------*
 
2479
 * Followings are util functions; probably be used by Opaque-LSAs only...
 
2480
 *------------------------------------------------------------------------*/
 
2481
 
 
2482
void
 
2483
htonf (float *src, float *dst)
 
2484
{
 
2485
  u_int32_t lu1, lu2;
 
2486
 
 
2487
  memcpy (&lu1, src, sizeof (u_int32_t));
 
2488
  lu2 = htonl (lu1);
 
2489
  memcpy (dst, &lu2, sizeof (u_int32_t));
 
2490
  return;
 
2491
}
 
2492
 
 
2493
void
 
2494
ntohf (float *src, float *dst)
 
2495
{
 
2496
  u_int32_t lu1, lu2;
 
2497
 
 
2498
  memcpy (&lu1, src, sizeof (u_int32_t));
 
2499
  lu2 = ntohl (lu1);
 
2500
  memcpy (dst, &lu2, sizeof (u_int32_t));
 
2501
  return;
 
2502
}
 
2503
 
 
2504
struct ospf *
 
2505
oi_to_top (struct ospf_interface *oi)
 
2506
{
 
2507
  struct ospf *top = NULL;
 
2508
  struct ospf_area *area;
 
2509
 
 
2510
  if (oi == NULL || (area = oi->area) == NULL || (top = area->ospf) == NULL)
 
2511
    zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");
 
2512
 
 
2513
  return top;
 
2514
}
 
2515
 
 
2516
#endif /* HAVE_OPAQUE_LSA */