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

« back to all changes in this revision

Viewing changes to ospf6d/ospf6_dbex.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
 * Copyright (C) 1999 Yasuhiro Ohara
 
3
 *
 
4
 * This file is part of GNU Zebra.
 
5
 *
 
6
 * GNU Zebra is free software; you can redistribute it and/or modify it
 
7
 * under the terms of the GNU General Public License as published by the
 
8
 * Free Software Foundation; either version 2, or (at your option) any
 
9
 * later version.
 
10
 *
 
11
 * GNU Zebra is distributed in the hope that it will be useful, but
 
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
 * General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with GNU Zebra; see the file COPYING.  If not, write to the 
 
18
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
 
19
 * Boston, MA 02111-1307, USA.  
 
20
 */
 
21
 
 
22
#include "ospf6d.h"
 
23
 
 
24
/* check validity and put lsa in reqestlist if needed. */
 
25
/* returns -1 if SeqNumMismatch required. */
 
26
int
 
27
ospf6_dbex_check_dbdesc_lsa_header (struct ospf6_lsa_header *lsa_header,
 
28
                                    struct ospf6_neighbor *from)
 
29
{
 
30
  struct ospf6_lsa *received = NULL;
 
31
  struct ospf6_lsa *have = NULL;
 
32
 
 
33
  received = ospf6_lsa_summary_create
 
34
    ((struct ospf6_lsa_header__ *) lsa_header);
 
35
 
 
36
  /* case when received is AS-External though neighbor belongs stub area */
 
37
  if (lsa_header->type == htons (OSPF6_LSA_TYPE_AS_EXTERNAL) &&
 
38
      ospf6_area_is_stub (from->ospf6_interface->area))
 
39
    {
 
40
      zlog_err ("DbDesc %s receive from %s", from->str, received->str);
 
41
      zlog_err ("    E-bit mismatch: %s", received->str);
 
42
      ospf6_lsa_delete (received);
 
43
      return -1;
 
44
    }
 
45
 
 
46
  /* if already have newer database copy, check next LSA */
 
47
  have = ospf6_lsdb_lookup (lsa_header->type, lsa_header->ls_id,
 
48
                            lsa_header->advrtr,
 
49
                            ospf6_lsa_get_scope (lsa_header->type,
 
50
                                                 from->ospf6_interface));
 
51
  if (! have)
 
52
    {
 
53
      /* if we don't have database copy, add request */
 
54
      if (IS_OSPF6_DUMP_DBEX)
 
55
        zlog_info ("Have no database copy, Request");
 
56
      ospf6_neighbor_request_add (received, from);
 
57
    }
 
58
  else if (have)
 
59
    {
 
60
      /* if database copy is less recent, add request */
 
61
      if (ospf6_lsa_check_recent (received, have) < 0)
 
62
        {
 
63
          if (IS_OSPF6_DUMP_DBEX)
 
64
            zlog_info ("Database copy less recent, Request");
 
65
          ospf6_neighbor_request_add (received, from);
 
66
        }
 
67
    }
 
68
 
 
69
  return 0;
 
70
}
 
71
 
 
72
/* Direct acknowledgement */
 
73
static void
 
74
ospf6_dbex_acknowledge_direct (struct ospf6_lsa *lsa,
 
75
                               struct ospf6_neighbor *o6n)
 
76
{
 
77
  struct iovec directack[MAXIOVLIST];
 
78
  assert (lsa);
 
79
 
 
80
  if (IS_OSPF6_DUMP_DBEX)
 
81
    zlog_info ("DBEX: [%s:%s] direct ack %s ",
 
82
               o6n->str, o6n->ospf6_interface->interface->name,
 
83
               lsa->str);
 
84
 
 
85
  /* clear pointers to fragments of packet for direct acknowledgement */
 
86
  iov_clear (directack, MAXIOVLIST);
 
87
 
 
88
  /* set pointer of LSA to send */
 
89
  OSPF6_MESSAGE_ATTACH (directack, lsa->header,
 
90
                        sizeof (struct ospf6_lsa_header));
 
91
 
 
92
  /* age update and add InfTransDelay */
 
93
  ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay);
 
94
 
 
95
  /* send unicast packet to neighbor's ipaddress */
 
96
  ospf6_message_send (OSPF6_MESSAGE_TYPE_LSACK, directack, &o6n->hisaddr,
 
97
                      o6n->ospf6_interface->if_id);
 
98
}
 
99
 
 
100
/* Delayed  acknowledgement */
 
101
void
 
102
ospf6_dbex_acknowledge_delayed (struct ospf6_lsa *lsa,
 
103
                                struct ospf6_interface *o6i)
 
104
{
 
105
  assert (o6i);
 
106
 
 
107
  if (IS_OSPF6_DUMP_DBEX)
 
108
    zlog_info ("DBEX: [%s] delayed ack %s", o6i->interface->name, lsa->str);
 
109
 
 
110
  /* attach delayed acknowledge list */
 
111
  ospf6_lsa_age_current (lsa);
 
112
  ospf6_interface_delayed_ack_add (lsa, o6i);
 
113
 
 
114
  /* if not yet, schedule delayed acknowledge RxmtInterval later.
 
115
     timers should be *less than* RxmtInterval
 
116
     or needless retrans will ensue */
 
117
  if (o6i->thread_send_lsack_delayed == NULL)
 
118
    o6i->thread_send_lsack_delayed
 
119
      = thread_add_timer (master, ospf6_send_lsack_delayed,
 
120
                          o6i, o6i->rxmt_interval - 1);
 
121
 
 
122
  return;
 
123
}
 
124
 
 
125
/* RFC2328 section 13 (4):
 
126
   if MaxAge LSA and if we have no instance, and no neighbor
 
127
   is in states Exchange or Loading */
 
128
/* returns 1 if match this case, else returns 0 */
 
129
static int
 
130
ospf6_dbex_is_maxage_to_be_dropped (struct ospf6_lsa *received,
 
131
                                    struct ospf6_neighbor *from)
 
132
{
 
133
  int count;
 
134
 
 
135
  if (! IS_LSA_MAXAGE (received))
 
136
    return 0;
 
137
 
 
138
  if (ospf6_lsdb_lookup (received->header->type, received->header->id,
 
139
                         received->header->adv_router,
 
140
                         ospf6_lsa_get_scope (received->header->type,
 
141
                                              from->ospf6_interface)))
 
142
    return 0;
 
143
 
 
144
  if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (ntohs (received->header->type)))
 
145
    {
 
146
      count = 0;
 
147
      (*from->ospf6_interface->foreach_nei)
 
148
        (from->ospf6_interface, &count, NBS_EXCHANGE, ospf6_count_state);
 
149
      (*from->ospf6_interface->foreach_nei)
 
150
        (from->ospf6_interface, &count, NBS_LOADING, ospf6_count_state);
 
151
      if (count)
 
152
        return 0;
 
153
    }
 
154
  else if (OSPF6_LSA_IS_SCOPE_AREA (ntohs (received->header->type)))
 
155
    {
 
156
      count = 0;
 
157
      (*from->ospf6_interface->area->foreach_nei)
 
158
         (from->ospf6_interface->area, &count, NBS_EXCHANGE, ospf6_count_state);
 
159
      (*from->ospf6_interface->area->foreach_nei)
 
160
         (from->ospf6_interface->area, &count, NBS_LOADING, ospf6_count_state);
 
161
      if (count)
 
162
        return 0;
 
163
    }
 
164
  else if (OSPF6_LSA_IS_SCOPE_AS (ntohs (received->header->type)))
 
165
    {
 
166
      count = 0;
 
167
      (*from->ospf6_interface->area->ospf6->foreach_nei)
 
168
         (from->ospf6_interface->area->ospf6, &count, NBS_EXCHANGE,
 
169
          ospf6_count_state);
 
170
      (*from->ospf6_interface->area->ospf6->foreach_nei)
 
171
         (from->ospf6_interface->area->ospf6, &count, NBS_LOADING,
 
172
          ospf6_count_state);
 
173
      if (count)
 
174
        return 0;
 
175
    }
 
176
 
 
177
  return 1;
 
178
}
 
179
 
 
180
static void
 
181
ospf6_dbex_remove_retrans (void *arg, int val, void *obj)
 
182
{
 
183
  struct ospf6_lsa *rem;
 
184
  struct ospf6_neighbor *nei = (struct ospf6_neighbor *) obj;
 
185
  struct ospf6_lsa *lsa = (struct ospf6_lsa *) arg;
 
186
 
 
187
  rem = ospf6_lsdb_lookup_lsdb (lsa->header->type, lsa->header->id,
 
188
                                lsa->header->adv_router, nei->retrans_list);
 
189
  if (rem)
 
190
    {
 
191
      ospf6_neighbor_retrans_remove (rem, nei);
 
192
      ospf6_maxage_remover ();
 
193
    }
 
194
}
 
195
 
 
196
void
 
197
ospf6_dbex_remove_from_all_retrans_list (struct ospf6_lsa *lsa)
 
198
{
 
199
  struct ospf6_interface *o6i;
 
200
  struct ospf6_area *o6a;
 
201
 
 
202
  if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (htons (lsa->header->type)))
 
203
    {
 
204
      o6i = lsa->scope;
 
205
      (*o6i->foreach_nei) (o6i, lsa, 0, ospf6_dbex_remove_retrans);
 
206
    }
 
207
  else if (OSPF6_LSA_IS_SCOPE_AREA (htons (lsa->header->type)))
 
208
    {
 
209
      o6a = lsa->scope;
 
210
      (*o6a->foreach_nei) (o6a, lsa, 0, ospf6_dbex_remove_retrans);
 
211
    }
 
212
  else if (OSPF6_LSA_IS_SCOPE_AS (htons (lsa->header->type)))
 
213
    {
 
214
      (*ospf6->foreach_nei) (ospf6, lsa, 0, ospf6_dbex_remove_retrans);
 
215
    }
 
216
}
 
217
 
 
218
/* RFC2328 section 13 */
 
219
void
 
220
ospf6_dbex_receive_lsa (struct ospf6_lsa_header *lsa_header,
 
221
                        struct ospf6_neighbor *from)
 
222
{
 
223
  struct ospf6_lsa *received, *have, *rem;
 
224
  struct timeval now;
 
225
  int ismore_recent, acktype;
 
226
  unsigned short cksum;
 
227
  struct ospf6_lsa_slot *slot;
 
228
 
 
229
  received = have = (struct ospf6_lsa *)NULL;
 
230
  ismore_recent = -1;
 
231
  recent_reason = "no instance";
 
232
 
 
233
  zlog_info ("Receive LSA (header -> %p)", lsa_header);
 
234
 
 
235
  /* make lsa structure for received lsa */
 
236
  received = ospf6_lsa_create (lsa_header);
 
237
 
 
238
  /* set LSA scope */
 
239
  if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (htons (lsa_header->type)))
 
240
    received->scope = from->ospf6_interface;
 
241
  else if (OSPF6_LSA_IS_SCOPE_AREA (htons (lsa_header->type)))
 
242
    received->scope = from->ospf6_interface->area;
 
243
  else if (OSPF6_LSA_IS_SCOPE_AS (htons (lsa_header->type)))
 
244
    received->scope = from->ospf6_interface->area->ospf6;
 
245
 
 
246
  /* (1) LSA Checksum */
 
247
  cksum = ntohs (lsa_header->checksum);
 
248
  if (ntohs (ospf6_lsa_checksum (lsa_header)) != cksum)
 
249
    {
 
250
      if (IS_OSPF6_DUMP_DBEX)
 
251
        zlog_info ("DBEX: received %s from %s%%%s"
 
252
                   ": wrong checksum, drop",
 
253
                   received->str, from->str,
 
254
                   from->ospf6_interface->interface->name);
 
255
      ospf6_lsa_delete (received);
 
256
      return;
 
257
    }
 
258
 
 
259
  /* (3) Ebit Missmatch: AS-External-LSA */
 
260
  if (lsa_header->type == htons (OSPF6_LSA_TYPE_AS_EXTERNAL) &&
 
261
      ospf6_area_is_stub (from->ospf6_interface->area))
 
262
    {
 
263
      if (IS_OSPF6_DUMP_DBEX)
 
264
        zlog_info ("DBEX: received %s from %s%%%s"
 
265
                   ": E-bit mismatch, drop",
 
266
                   received->str, from->str,
 
267
                   from->ospf6_interface->interface->name);
 
268
      ospf6_lsa_delete (received);
 
269
      return;
 
270
    }
 
271
 
 
272
  /* (4) if MaxAge LSA and if we have no instance, and no neighbor
 
273
         is in states Exchange or Loading */
 
274
  if (ospf6_dbex_is_maxage_to_be_dropped (received, from))
 
275
    {
 
276
      /* log */
 
277
      if (IS_OSPF6_DUMP_DBEX)
 
278
        zlog_info ("DBEX: received %s from %s%%%s"
 
279
                   ": MaxAge, no instance, no neighbor exchange, drop",
 
280
                   received->str, from->str,
 
281
                   from->ospf6_interface->interface->name);
 
282
 
 
283
      /* a) Acknowledge back to neighbor (13.5) */
 
284
        /* Direct Acknowledgement */
 
285
      ospf6_dbex_acknowledge_direct (received, from);
 
286
 
 
287
      /* b) Discard */
 
288
      ospf6_lsa_delete (received);
 
289
      return;
 
290
    }
 
291
 
 
292
  /* (5) */
 
293
  /* lookup the same database copy in lsdb */
 
294
  have = ospf6_lsdb_lookup (lsa_header->type, lsa_header->ls_id,
 
295
                            lsa_header->advrtr,
 
296
                            ospf6_lsa_get_scope (lsa_header->type,
 
297
                                                 from->ospf6_interface));
 
298
  if (have)
 
299
    {
 
300
      ismore_recent = ospf6_lsa_check_recent (received, have);
 
301
      if (ntohl (received->header->seqnum) == ntohl (have->header->seqnum))
 
302
        SET_FLAG (received->flag, OSPF6_LSA_FLAG_DUPLICATE);
 
303
    }
 
304
 
 
305
  /* if no database copy or received is more recent */
 
306
  if (!have || ismore_recent < 0)
 
307
    {
 
308
      /* in case we have no database copy */
 
309
      ismore_recent = -1;
 
310
 
 
311
      /* (a) MinLSArrival check */
 
312
      gettimeofday (&now, (struct timezone *)NULL);
 
313
      if (have && SEC_TVDIFF (&now, &have->installed) < OSPF6_MIN_LS_ARRIVAL)
 
314
        {
 
315
          //if (IS_OSPF6_DUMP_DBEX)
 
316
            zlog_info ("DBEX: Receive new LSA from %s: %s seq: %#x age: %d "
 
317
                       "within MinLSArrival, drop: %ld.%06ld",
 
318
                       from->str, received->str,
 
319
                       ntohl (received->header->seqnum),
 
320
                       ntohs (received->header->age),
 
321
                       now.tv_sec, now.tv_usec);
 
322
 
 
323
          /* this will do free this lsa */
 
324
          ospf6_lsa_delete (received);
 
325
          return;   /* examin next lsa */
 
326
        }
 
327
 
 
328
      //if (IS_OSPF6_DUMP_DBEX)
 
329
        zlog_info ("DBEX: Receive new LSA from %s: %s seq: %#x age: %d: "
 
330
                   "%ld.%06ld",
 
331
                   from->str, received->str,
 
332
                   ntohl (received->header->seqnum),
 
333
                   ntohs (received->header->age),
 
334
                   now.tv_sec, now.tv_usec);
 
335
 
 
336
      /* (b) immediately flood */
 
337
      ospf6_dbex_flood (received, from);
 
338
 
 
339
#if 0
 
340
      /* Because New LSDB do not permit two LSA having the same identifier
 
341
         exist in a LSDB list, above ospf6_dbex_flood() will remove
 
342
         the old instance automatically. thus bellow is not needed. */
 
343
      /* (c) remove database copy from all neighbor's retranslist */
 
344
      if (have)
 
345
        ospf6_dbex_remove_from_all_retrans_list (have);
 
346
#endif
 
347
 
 
348
      /* (d), installing lsdb, which may cause routing
 
349
              table calculation (replacing database copy) */
 
350
      ospf6_lsdb_install (received);
 
351
 
 
352
      /* (e) possibly acknowledge */
 
353
      acktype = ack_type (received, ismore_recent, from);
 
354
      if (acktype == DIRECT_ACK)
 
355
        {
 
356
          if (IS_OSPF6_DUMP_DBEX)
 
357
            zlog_info ("DBEX: Direct Ack to %s", from->str);
 
358
          ospf6_dbex_acknowledge_direct (received, from);
 
359
        }
 
360
      else if (acktype == DELAYED_ACK)
 
361
        {
 
362
          if (IS_OSPF6_DUMP_DBEX)
 
363
            zlog_info ("DBEX: Delayed Ack to %s", from->str);
 
364
          ospf6_dbex_acknowledge_delayed (received, from->ospf6_interface);
 
365
        }
 
366
      else
 
367
        {
 
368
          if (IS_OSPF6_DUMP_DBEX)
 
369
            zlog_info ("DBEX: No Ack to %s", from->str);
 
370
        }
 
371
 
 
372
      /* (f) */
 
373
      /* Self Originated LSA, section 13.4 */
 
374
      if (received->lsa_hdr->lsh_advrtr == ospf6->router_id
 
375
          && (! have || ismore_recent < 0))
 
376
        {
 
377
          /* we're going to make new lsa or to flush this LSA. */
 
378
          if (IS_OSPF6_DUMP_DBEX)
 
379
            zlog_info ("DBEX: Self-originated LSA %s from %s:%s",
 
380
                       received->str, from->str,
 
381
                       from->ospf6_interface->interface->name);
 
382
          if (IS_OSPF6_DUMP_DBEX)
 
383
            zlog_info ("DBEX: %s: Make new one/Flush", received->str);
 
384
 
 
385
          SET_FLAG (received->flag, OSPF6_LSA_FLAG_REFRESH);
 
386
          slot = ospf6_lsa_slot_get (received->header->type);
 
387
          if (slot && slot->func_refresh)
 
388
            {
 
389
              (*slot->func_refresh) (received);
 
390
              return;
 
391
            }
 
392
 
 
393
          zlog_warn ("Can't Refresh LSA: Unknown type: %#x, Flush",
 
394
                     ntohs (received->header->type));
 
395
          ospf6_lsa_premature_aging (received);
 
396
          return;
 
397
        }
 
398
    }
 
399
  else if (ospf6_lsdb_lookup_lsdb (received->header->type,
 
400
                                   received->header->id,
 
401
                                   received->header->adv_router,
 
402
                                   from->request_list))
 
403
    /* (6) if there is instance on sending neighbor's request list */
 
404
    {
 
405
      /* if no database copy, should go above state (5) */
 
406
      assert (have);
 
407
 
 
408
      zlog_warn ("DBEX: [%s:%s] received LSA %s is not newer,"
 
409
                 " and is on his requestlist: Generate BadLSReq",
 
410
                 from->str, from->ospf6_interface->interface->name,
 
411
                 received->str);
 
412
 
 
413
      /* BadLSReq */
 
414
      thread_add_event (master, bad_lsreq, from, 0);
 
415
 
 
416
      ospf6_lsa_delete (received);
 
417
    }
 
418
  else if (ismore_recent == 0) /* (7) if neither is more recent */
 
419
    {
 
420
      /* (a) if on retranslist, Treat this LSA as an Ack: Implied Ack */
 
421
      rem = ospf6_lsdb_lookup_lsdb (received->header->type,
 
422
                                    received->header->id,
 
423
                                    received->header->adv_router,
 
424
                                    from->retrans_list);
 
425
      if (rem)
 
426
        {
 
427
          if (IS_OSPF6_DUMP_DBEX)
 
428
            zlog_info ("DBEX: Implied Ack from %s, (remove retrans)",
 
429
                       from->str);
 
430
          SET_FLAG (received->flag, OSPF6_LSA_FLAG_IMPLIEDACK);
 
431
          ospf6_neighbor_retrans_remove (rem, from);
 
432
        }
 
433
 
 
434
      /* (b) possibly acknowledge */
 
435
      acktype = ack_type (received, ismore_recent, from);
 
436
      if (acktype == DIRECT_ACK)
 
437
        {
 
438
          if (IS_OSPF6_DUMP_DBEX)
 
439
            zlog_info ("DBEX: Direct Ack to %s", from->str);
 
440
          ospf6_dbex_acknowledge_direct (received, from);
 
441
        }
 
442
      else if (acktype == DELAYED_ACK)
 
443
        {
 
444
          if (IS_OSPF6_DUMP_DBEX)
 
445
            zlog_info ("DBEX: Delayed Ack to %s", from->str);
 
446
          ospf6_dbex_acknowledge_delayed (received, from->ospf6_interface);
 
447
        }
 
448
      else
 
449
        {
 
450
          if (IS_OSPF6_DUMP_DBEX)
 
451
            zlog_info ("DBEX: No Ack to %s", from->str);
 
452
        }
 
453
      ospf6_lsa_delete (received);
 
454
    }
 
455
  else /* (8) previous database copy is more recent */
 
456
    {
 
457
      /* If Seqnumber Wrapping, simply discard
 
458
         Otherwise, Send database copy of this LSA to this neighbor */
 
459
      if (! IS_LSA_MAXAGE (received) ||
 
460
          received->lsa_hdr->lsh_seqnum != MAX_SEQUENCE_NUMBER)
 
461
        {
 
462
          if (IS_OSPF6_DUMP_DBEX)
 
463
            zlog_info ("DBEX: database is more recent: send back to %s",
 
464
                       from->str);
 
465
          ospf6_send_lsupdate_direct (have, from);
 
466
        }
 
467
      ospf6_lsa_delete (received);
 
468
    }
 
469
}
 
470
 
 
471
/* RFC2328: Table 19: Sending link state acknowledgements. */
 
472
int 
 
473
ack_type (struct ospf6_lsa *newp, int ismore_recent,
 
474
          struct ospf6_neighbor *from)
 
475
{
 
476
  struct ospf6_interface *ospf6_interface;
 
477
  struct ospf6_lsa *have;
 
478
  int count;
 
479
 
 
480
  assert (from && from->ospf6_interface);
 
481
  ospf6_interface = from->ospf6_interface;
 
482
 
 
483
  if (CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_FLOODBACK))
 
484
    return NO_ACK;
 
485
 
 
486
  if (ismore_recent < 0)
 
487
    {
 
488
      if (ospf6_interface->state != IFS_BDR)
 
489
        return DELAYED_ACK;
 
490
 
 
491
      if (ospf6_interface->dr == from->router_id)
 
492
        return DELAYED_ACK;
 
493
      return NO_ACK;
 
494
    }
 
495
 
 
496
  if (CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_DUPLICATE) &&
 
497
      CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_IMPLIEDACK))
 
498
    {
 
499
      if (ospf6_interface->state != IFS_BDR)
 
500
        return NO_ACK;
 
501
 
 
502
      if (ospf6_interface->dr == from->router_id)
 
503
        return DELAYED_ACK;
 
504
 
 
505
      return NO_ACK;
 
506
    }
 
507
 
 
508
  if (CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_DUPLICATE) &&
 
509
      ! CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_IMPLIEDACK))
 
510
    return DIRECT_ACK;
 
511
 
 
512
  have = ospf6_lsdb_lookup (newp->header->type, newp->header->id,
 
513
                            newp->header->adv_router,
 
514
                            ospf6_lsa_get_scope (newp->header->type,
 
515
                                                 from->ospf6_interface));
 
516
 
 
517
  count = 0;
 
518
  ospf6->foreach_nei (ospf6, &count, NBS_EXCHANGE, ospf6_count_state);
 
519
  ospf6->foreach_nei (ospf6, &count, NBS_LOADING, ospf6_count_state);
 
520
 
 
521
  if (IS_LSA_MAXAGE (newp) && have == NULL && count == 0)
 
522
    return DIRECT_ACK;
 
523
 
 
524
  return NO_ACK;
 
525
}
 
526
 
 
527
static void
 
528
ospf6_dbex_flood_linklocal (struct ospf6_lsa *lsa, struct ospf6_interface *o6i,
 
529
                            struct ospf6_neighbor *from)
 
530
{
 
531
  struct ospf6_neighbor *o6n = (struct ospf6_neighbor *) NULL;
 
532
  int ismore_recent, addretrans = 0;
 
533
  listnode n;
 
534
  struct ospf6_lsa *req;
 
535
 
 
536
  /* (1) for each neighbor */
 
537
  for (n = listhead (o6i->neighbor_list); n; nextnode (n))
 
538
    {
 
539
      o6n = (struct ospf6_neighbor *) getdata (n);
 
540
 
 
541
      /* (a) */
 
542
      if (o6n->state < NBS_EXCHANGE)
 
543
        continue;  /* examin next neighbor */
 
544
 
 
545
      /* (b) */
 
546
      if (o6n->state == NBS_EXCHANGE
 
547
          || o6n->state == NBS_LOADING)
 
548
        {
 
549
          req = ospf6_lsdb_lookup_lsdb (lsa->header->type,
 
550
                                        lsa->header->id,
 
551
                                        lsa->header->adv_router,
 
552
                                        o6n->request_list);
 
553
          if (req)
 
554
            {
 
555
              ismore_recent = ospf6_lsa_check_recent (lsa, req);
 
556
              if (ismore_recent > 0)
 
557
                {
 
558
                  continue; /* examin next neighbor */
 
559
                }
 
560
              else if (ismore_recent == 0)
 
561
                {
 
562
                  ospf6_neighbor_request_remove (req, o6n);
 
563
                  continue; /* examin next neighbor */
 
564
                }
 
565
              else /* ismore_recent < 0 (the new LSA is more recent) */
 
566
                {
 
567
                  ospf6_neighbor_request_remove (req, o6n);
 
568
                }
 
569
            }
 
570
        }
 
571
 
 
572
      /* (c) */
 
573
      if (from && from->router_id == o6n->router_id)
 
574
        continue; /* examin next neighbor */
 
575
 
 
576
      /* (d) add retranslist */
 
577
      if (IS_OSPF6_DUMP_DBEX)
 
578
        zlog_info ("DBEX: schedule flooding [%s:%s]: %s",
 
579
                   o6n->str, o6n->ospf6_interface->interface->name,
 
580
                   lsa->str);
 
581
      ospf6_neighbor_retrans_add (lsa, o6n);
 
582
      addretrans++;
 
583
      if (o6n->send_update == (struct thread *) NULL)
 
584
        o6n->send_update =
 
585
          thread_add_timer (master, ospf6_send_lsupdate_rxmt, o6n,
 
586
                            o6n->ospf6_interface->rxmt_interval);
 
587
    }
 
588
 
 
589
  /* (2) */
 
590
  if (addretrans == 0)
 
591
    return; /* examin next interface */
 
592
 
 
593
  if (from && from->ospf6_interface == o6i)
 
594
    {
 
595
      if (IS_OSPF6_DUMP_DBEX)
 
596
        zlog_info ("DBEX: flood back %s to %s",
 
597
                   lsa->str, o6i->interface->name);
 
598
      /* note occurence of floodback */
 
599
      SET_FLAG (lsa->flag, OSPF6_LSA_FLAG_FLOODBACK);
 
600
    }
 
601
 
 
602
  /* (3) */
 
603
  if (from && from->ospf6_interface == o6i)
 
604
    {
 
605
      /* if from DR or BDR, don't need to flood this interface */
 
606
      if (from->router_id == from->ospf6_interface->dr ||
 
607
          from->router_id == from->ospf6_interface->bdr)
 
608
        return; /* examin next interface */
 
609
    }
 
610
 
 
611
  /* (4) if I'm BDR, DR will flood this interface */
 
612
  if (from && from->ospf6_interface == o6i
 
613
      && o6i->state == IFS_BDR)
 
614
    return; /* examin next interface */
 
615
 
 
616
  if (IS_OSPF6_DUMP_DBEX)
 
617
    zlog_info ("Flood to interface %s", o6i->interface->name);
 
618
 
 
619
  /* (5) send LinkState Update */
 
620
  ospf6_send_lsupdate_flood (lsa, o6i);
 
621
 
 
622
  return;
 
623
}
 
624
 
 
625
/* RFC2328 section 13.3 */
 
626
static void
 
627
ospf6_dbex_flood_area (struct ospf6_lsa *lsa, struct ospf6_area *area,
 
628
                       struct ospf6_neighbor *from)
 
629
{
 
630
  listnode n;
 
631
  struct ospf6_interface *ospf6_interface;
 
632
 
 
633
  assert (lsa && lsa->lsa_hdr && area);
 
634
 
 
635
  /* for each eligible ospf_ifs */
 
636
  for (n = listhead (area->if_list); n; nextnode (n))
 
637
    {
 
638
      ospf6_interface = (struct ospf6_interface *) getdata (n);
 
639
      ospf6_dbex_flood_linklocal (lsa, ospf6_interface, from);
 
640
    }
 
641
}
 
642
 
 
643
static void
 
644
ospf6_dbex_flood_as (struct ospf6_lsa *lsa, struct ospf6 *ospf6,
 
645
                     struct ospf6_neighbor *from)
 
646
{
 
647
  listnode n;
 
648
  struct ospf6_area *o6a;
 
649
 
 
650
  assert (lsa && lsa->lsa_hdr && ospf6);
 
651
 
 
652
  /* for each attached area */
 
653
  for (n = listhead (ospf6->area_list); n; nextnode (n))
 
654
    {
 
655
      o6a = (struct ospf6_area *) getdata (n);
 
656
      ospf6_dbex_flood_area (lsa, o6a, from);
 
657
    }
 
658
}
 
659
 
 
660
/* flood ospf6_lsa within appropriate scope */
 
661
void
 
662
ospf6_dbex_flood (struct ospf6_lsa *lsa, struct ospf6_neighbor *from)
 
663
{
 
664
  struct ospf6_area *o6a;
 
665
  struct ospf6_interface *o6i;
 
666
  struct ospf6 *o6;
 
667
  struct ospf6_lsa_header *lsa_header;
 
668
 
 
669
  lsa_header = (struct ospf6_lsa_header *) lsa->lsa_hdr;
 
670
 
 
671
  if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (ntohs (lsa_header->type)))
 
672
    {
 
673
      o6i = (struct ospf6_interface *) lsa->scope;
 
674
      assert (o6i);
 
675
 
 
676
      if (IS_OSPF6_DUMP_DBEX)
 
677
        zlog_info ("Flood Linklocal: %s", o6i->interface->name);
 
678
      ospf6_dbex_flood_linklocal (lsa, o6i, from);
 
679
    }
 
680
  else if (OSPF6_LSA_IS_SCOPE_AREA (ntohs (lsa_header->type)))
 
681
    {
 
682
      o6a = (struct ospf6_area *) lsa->scope;
 
683
      assert (o6a);
 
684
 
 
685
      if (IS_OSPF6_DUMP_DBEX)
 
686
        zlog_info ("Flood Area: %s", o6a->str);
 
687
      ospf6_dbex_flood_area (lsa, o6a, from);
 
688
    }
 
689
  else if (OSPF6_LSA_IS_SCOPE_AS (ntohs (lsa_header->type)))
 
690
    {
 
691
      o6 = (struct ospf6 *) lsa->scope;
 
692
      assert (o6);
 
693
 
 
694
      if (IS_OSPF6_DUMP_DBEX)
 
695
        zlog_info ("Flood AS");
 
696
      ospf6_dbex_flood_as (lsa, o6, from);
 
697
    }
 
698
  else
 
699
    {
 
700
      zlog_warn ("Can't Flood %s: scope unknown", lsa->str);
 
701
    }
 
702
}
 
703
 
 
704