Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / topology.c @ f623ab98

History | View | Annotate | Download (45.7 KB)

1 6ba36f06 Martin Mares
/*
2
 *        BIRD -- OSPF Topological Database
3
 *
4 98ac6176 Ondrej Filip
 *        (c) 1999       Martin Mares <mj@ucw.cz>
5
 *        (c) 1999--2004 Ondrej Filip <feela@network.cz>
6 6ba36f06 Martin Mares
 *
7
 *        Can be freely distributed and used under the terms of the GNU GPL.
8
 */
9
10
#include "nest/bird.h"
11 221135d6 Martin Mares
#include "lib/string.h"
12 6ba36f06 Martin Mares
13
#include "ospf.h"
14
15 8d56febe Ondrej Filip
#define HASH_DEF_ORDER 6
16 6ba36f06 Martin Mares
#define HASH_HI_MARK *4
17
#define HASH_HI_STEP 2
18
#define HASH_HI_MAX 16
19
#define HASH_LO_MARK /5
20
#define HASH_LO_STEP 2
21
#define HASH_LO_MIN 8
22
23 b49e6f5a Ondrej Zajicek
void originate_prefix_rt_lsa(struct ospf_area *oa);
24
void originate_prefix_net_lsa(struct ospf_iface *ifa);
25 061ab802 Ondrej Zajicek
void flush_prefix_net_lsa(struct ospf_iface *ifa);
26 b49e6f5a Ondrej Zajicek
27
#ifdef OSPFv2
28
#define ipa_to_rid(x) _I(x)
29
#else /* OSPFv3 */
30
#define ipa_to_rid(x) _I3(x)
31
#endif
32
33 d82fc18d Ondrej Zajicek
34 b49e6f5a Ondrej Zajicek
#ifdef OSPFv2
35 d82fc18d Ondrej Zajicek
static inline u32
36
fibnode_to_lsaid(struct proto_ospf *po, struct fib_node *fn)
37
{
38
  /* We have to map IP prefixes to u32 in such manner that resulting
39
     u32 interpreted as IP address is a member of given
40
     prefix. Therefore, /32 prefix have to be mapped on itself.
41
     All received prefixes have to be mapped on different u32s.
42

43
     We have an assumption that if there is nontrivial (non-/32)
44
     network prefix, then there is not /32 prefix for the first
45
     and the last IP address of the network (these are usually
46
     reserved, therefore it is not an important restriction).
47
     The network prefix is mapped to the first or the last
48
     IP address in the manner that disallow collisions - we
49
     use IP address that cannot be used by parent prefix.
50

51
     For example:
52
     192.168.0.0/24 maps to 192.168.0.255
53
     192.168.1.0/24 maps to 192.168.1.0
54
     because 192.168.0.0 and 192.168.1.255 might be used by
55
     192.168.0.0/23 .
56

57
     This is not compatible with older RFC 1583, so we have an option
58
     to the RFC 1583 compatible assignment (that always uses the first
59
     address) which disallows subnetting.
60

61
     Appendig E of RFC 2328 suggests different algorithm, that tries
62
     to maximize both compatibility and subnetting. But as it is not
63
     possible to have both reliably and the suggested algorithm was
64
     unnecessary complicated and it does crazy things like changing
65
     LSA ID for a network because different network appeared, we
66
     choose a different way. */
67
68
  u32 id = _I(fn->prefix);
69
70
  if ((po->rfc1583) || (fn->pxlen == 0) || (fn->pxlen == 32))
71
    return id;
72
73
  if (id & (1 << (32 - fn->pxlen)))
74
    return id;
75
  else
76
    return id | ~u32_mkmask(fn->pxlen);
77
}
78
79 b49e6f5a Ondrej Zajicek
#else /* OSPFv3 */
80 d82fc18d Ondrej Zajicek
81
static inline u32
82
fibnode_to_lsaid(struct proto_ospf *po, struct fib_node *fn)
83
{
84 6384c7d7 Ondrej Zajicek
  /*
85
   * In OSPFv3, it is simpler. There is not a requirement for
86
   * membership of the result in the input network, so we just use a
87
   * hash-based unique ID of a routing table entry for a route that
88
   * originated given LSA. For ext-LSA, it is an imported route in the
89
   * nest's routing table (p->table). For summary-LSA, it is a
90
   * 'source' route in the protocol internal routing table (po->rtf).
91
   */
92 d82fc18d Ondrej Zajicek
  return fn->uid;
93
}
94
95 b49e6f5a Ondrej Zajicek
#endif
96
97
98 9831e591 Martin Mares
static void *
99 3d15dcdb Ondrej Zajicek
lsab_alloc(struct proto_ospf *po, unsigned size)
100
{
101
  unsigned offset = po->lsab_used;
102
  po->lsab_used += size;
103
  if (po->lsab_used > po->lsab_size)
104
    {
105
      po->lsab_size = MAX(po->lsab_used, 2 * po->lsab_size);
106
      po->lsab = mb_realloc(po->proto.pool, po->lsab, po->lsab_size);
107
    }
108
  return ((byte *) po->lsab) + offset;
109
}
110
111
static inline void *
112
lsab_allocz(struct proto_ospf *po, unsigned size)
113
{
114
  void *r = lsab_alloc(po, size);
115
  bzero(r, size);
116
  return r;
117
}
118
119
static inline void *
120
lsab_flush(struct proto_ospf *po)
121
{
122 f0160f0e Ondrej Zajicek
  void *r = mb_alloc(po->proto.pool, po->lsab_used);
123 3d15dcdb Ondrej Zajicek
  memcpy(r, po->lsab, po->lsab_used);
124
  po->lsab_used = 0;
125
  return r;
126
}
127
128 c3226991 Ondrej Zajicek
static inline void *
129
lsab_offset(struct proto_ospf *po, unsigned offset)
130
{
131
  return ((byte *) po->lsab) + offset;
132
}
133
134
static inline void *
135
lsab_end(struct proto_ospf *po)
136
{
137
  return ((byte *) po->lsab) + po->lsab_used;
138
}
139
140 52572e94 Ondrej Zajicek
static s32
141
get_seqnum(struct top_hash_entry *en)
142
{
143
  if (!en)
144
    return LSA_INITSEQNO;
145
146
  if (en->lsa.sn == LSA_MAXSEQNO)
147
  {
148 d395fe48 Ondrej Zajicek
    log(L_WARN "OSPF: Premature origination of LSA (Type: %04x, Id: %R, Rt: %R)",
149 52572e94 Ondrej Zajicek
        en->lsa.type, en->lsa.id, en->lsa.rt);
150
    return LSA_INITSEQNO;
151
  }
152
153 74add5df Ondrej Zajicek
  return en->lsa.sn + 1;
154 52572e94 Ondrej Zajicek
}
155
156 c3226991 Ondrej Zajicek
157 38675202 Ondrej Zajicek
static int
158
configured_stubnet(struct ospf_area *oa, struct ifa *a)
159
{
160 5cdf264f Ondrej Zajicek
  if (!oa->ac)
161
    return 0;
162
163 52a43ae3 Ondrej Zajicek
  /* Does not work for IA_PEER addresses, but it is not called on these */
164 38675202 Ondrej Zajicek
  struct ospf_stubnet_config *sn;
165
  WALK_LIST(sn, oa->ac->stubnet_list)
166
    {
167
      if (sn->summary)
168
        {
169
          if (ipa_in_net(a->prefix, sn->px.addr, sn->px.len) && (a->pxlen >= sn->px.len))
170
            return 1;
171
        }
172
      else
173
        {
174
          if (ipa_equal(a->prefix, sn->px.addr) && (a->pxlen == sn->px.len))
175
            return 1;
176
        }
177
    }
178
  return 0;
179
}
180 3d15dcdb Ondrej Zajicek
181 c3226991 Ondrej Zajicek
int
182
bcast_net_active(struct ospf_iface *ifa)
183
{
184
  struct ospf_neighbor *neigh;
185
186
  if (ifa->state == OSPF_IS_WAITING)
187
    return 0;
188
189
  WALK_LIST(neigh, ifa->neigh_list)
190
    {
191
      if (neigh->state == NEIGHBOR_FULL)
192
        {
193
          if (neigh->rid == ifa->drid)
194
            return 1;
195
196
          if (ifa->state == OSPF_IS_DR)
197
            return 1;
198
        }
199
    }
200
201
  return 0;
202
}
203
204
205
#ifdef OSPFv2
206
207 3d15dcdb Ondrej Zajicek
static void *
208 c3226991 Ondrej Zajicek
originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
209 ce17d4c1 Ondrej Filip
{
210 b9ed99f7 Ondrej Filip
  struct proto_ospf *po = oa->po;
211 ce17d4c1 Ondrej Filip
  struct ospf_iface *ifa;
212 c3226991 Ondrej Zajicek
  int i = 0, bitv = 0;
213 ce17d4c1 Ondrej Filip
  struct ospf_lsa_rt *rt;
214 3d15dcdb Ondrej Zajicek
  struct ospf_lsa_rt_link *ln;
215 ce17d4c1 Ondrej Filip
  struct ospf_neighbor *neigh;
216
217 3d15dcdb Ondrej Zajicek
  ASSERT(po->lsab_used == 0);
218
  rt = lsab_allocz(po, sizeof(struct ospf_lsa_rt));
219 c3226991 Ondrej Zajicek
220 f9c799a0 Ondrej Zajicek
  rt->options = 0;
221 c3226991 Ondrej Zajicek
222 b9ed99f7 Ondrej Filip
  if (po->areano > 1)
223 c3226991 Ondrej Zajicek
    rt->options |= OPT_RT_B;
224
225 4160a9dd Ondrej Zajicek
  if ((po->areano > 1) && oa_is_nssa(oa) && oa->ac->translator)
226
    rt->options |= OPT_RT_NT;
227
228 41b612c3 Ondrej Zajicek
  if (po->ebit && !oa_is_stub(oa))
229 c3226991 Ondrej Zajicek
    rt->options |= OPT_RT_E;
230
231 3d15dcdb Ondrej Zajicek
  rt = NULL; /* buffer might be reallocated later */
232 b9ed99f7 Ondrej Filip
233
  WALK_LIST(ifa, po->iface_list)
234 ce17d4c1 Ondrej Filip
  {
235 353729f5 Ondrej Zajicek
    int net_lsa = 0;
236 f623ab98 Ondrej Zajicek
    u32 link_cost = po->stub_router ? 0xffff : ifa->cost;
237 3d15dcdb Ondrej Zajicek
238
    if ((ifa->type == OSPF_IT_VLINK) && (ifa->voa == oa) &&
239
        (!EMPTY_LIST(ifa->neigh_list)))
240 5d3f5552 Ondrej Filip
    {
241
      neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list);
242
      if ((neigh->state == NEIGHBOR_FULL) && (ifa->cost <= 0xffff))
243 3d15dcdb Ondrej Zajicek
        bitv = 1;
244 5d3f5552 Ondrej Filip
    }
245 3b16080c Ondrej Filip
246
    if ((ifa->oa != oa) || (ifa->state == OSPF_IS_DOWN))
247 b9ed99f7 Ondrej Filip
      continue;
248 3b580a23 Ondrej Filip
249 e7b4948c Ondrej Zajicek
    ifa->rt_pos_beg = i;
250
251 919f5411 Ondrej Zajicek
    /* RFC2328 - 12.4.1.1-4 */
252 3d15dcdb Ondrej Zajicek
    switch (ifa->type)
253 ce17d4c1 Ondrej Filip
      {
254 919f5411 Ondrej Zajicek
      case OSPF_IT_PTP:
255
      case OSPF_IT_PTMP:
256
        WALK_LIST(neigh, ifa->neigh_list)
257
          if (neigh->state == NEIGHBOR_FULL)
258
          {
259
            ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
260
            ln->type = LSART_PTP;
261
            ln->id = neigh->rid;
262 6cadbf32 Ondrej Zajicek
263
            /*
264
             * ln->data should be ifa->iface_id in case of no/ptp
265
             * address (ifa->addr->flags & IA_PEER) on PTP link (see
266
             * RFC 2328 12.4.1.1.), but the iface ID value has no use,
267
             * while using IP address even in this case is here for
268
             * compatibility with some broken implementations that use
269
             * this address as a next-hop.
270
             */
271
            ln->data = ipa_to_u32(ifa->addr->ip);
272 f623ab98 Ondrej Zajicek
            ln->metric = link_cost;
273 919f5411 Ondrej Zajicek
            ln->padding = 0;
274
            i++;
275
          }
276 b9ed99f7 Ondrej Filip
        break;
277 3d15dcdb Ondrej Zajicek
278 919f5411 Ondrej Zajicek
      case OSPF_IT_BCAST:
279 b9ed99f7 Ondrej Filip
      case OSPF_IT_NBMA:
280 c3226991 Ondrej Zajicek
        if (bcast_net_active(ifa))
281 b9ed99f7 Ondrej Filip
          {
282 3d15dcdb Ondrej Zajicek
            ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
283 b9ed99f7 Ondrej Filip
            ln->type = LSART_NET;
284
            ln->id = ipa_to_u32(ifa->drip);
285 353729f5 Ondrej Zajicek
            ln->data = ipa_to_u32(ifa->addr->ip);
286 f623ab98 Ondrej Zajicek
            ln->metric = link_cost;
287 c15e5690 Ondrej Zajicek
            ln->padding = 0;
288 3d15dcdb Ondrej Zajicek
            i++;
289 353729f5 Ondrej Zajicek
            net_lsa = 1;
290 b9ed99f7 Ondrej Filip
          }
291
        break;
292 3d15dcdb Ondrej Zajicek
293 919f5411 Ondrej Zajicek
      case OSPF_IT_VLINK:
294 98ac6176 Ondrej Filip
        neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list);
295
        if ((!EMPTY_LIST(ifa->neigh_list)) && (neigh->state == NEIGHBOR_FULL) && (ifa->cost <= 0xffff))
296
        {
297 3d15dcdb Ondrej Zajicek
          ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
298 98ac6176 Ondrej Filip
          ln->type = LSART_VLNK;
299
          ln->id = neigh->rid;
300 353729f5 Ondrej Zajicek
          ln->data = ipa_to_u32(ifa->addr->ip);
301 f623ab98 Ondrej Zajicek
          ln->metric = link_cost;
302 c15e5690 Ondrej Zajicek
          ln->padding = 0;
303 3d15dcdb Ondrej Zajicek
          i++;
304 12dd8dc8 Ondrej Filip
        }
305
        break;
306 3d15dcdb Ondrej Zajicek
307 12dd8dc8 Ondrej Filip
      default:
308 86c84d76 Ondrej Filip
        log("Unknown interface type %s", ifa->iface->name);
309 98ac6176 Ondrej Filip
        break;
310 ce17d4c1 Ondrej Filip
      }
311 3d15dcdb Ondrej Zajicek
312 e7b4948c Ondrej Zajicek
    ifa->rt_pos_end = i;
313
314 0aad2b92 Ondrej Zajicek
    /* Now we will originate stub area if there is no primary */
315
    if (net_lsa ||
316
        (ifa->type == OSPF_IT_VLINK) ||
317 a55a90fa Ondrej Zajicek
        ((ifa->addr->flags & IA_PEER) && ! ifa->cf->stub) ||
318 0aad2b92 Ondrej Zajicek
        configured_stubnet(oa, ifa->addr))
319
      continue;
320 3d15dcdb Ondrej Zajicek
321 0aad2b92 Ondrej Zajicek
    ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
322 52a43ae3 Ondrej Zajicek
    if ((ifa->addr->flags & IA_HOST) ||
323
        (ifa->state == OSPF_IS_LOOP) ||
324
        (ifa->type == OSPF_IT_PTMP))
325 d9e7e1b1 Ondrej Zajicek
    {
326
      /* Host stub entry */
327
      ln->type = LSART_STUB;
328
      ln->id = ipa_to_u32(ifa->addr->ip);
329
      ln->data = 0xffffffff;
330
      ln->metric = 0;
331
      ln->padding = 0;
332
    }
333
    else 
334
    {
335
      /* Network stub entry */
336
      ln->type = LSART_STUB;
337
      ln->id = ipa_to_u32(ifa->addr->prefix);
338
      ln->data = ipa_to_u32(ipa_mkmask(ifa->addr->pxlen));
339
      ln->metric = ifa->cost;
340
      ln->padding = 0;
341
    }
342 0aad2b92 Ondrej Zajicek
    i++;
343 e7b4948c Ondrej Zajicek
344
    ifa->rt_pos_end = i;
345 ce17d4c1 Ondrej Filip
  }
346 3d15dcdb Ondrej Zajicek
347 38675202 Ondrej Zajicek
  struct ospf_stubnet_config *sn;
348 5cdf264f Ondrej Zajicek
  if (oa->ac)
349
    WALK_LIST(sn, oa->ac->stubnet_list)
350
      if (!sn->hidden)
351 38675202 Ondrej Zajicek
      {
352
        ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
353
        ln->type = LSART_STUB;
354
        ln->id = ipa_to_u32(sn->px.addr);
355
        ln->data = ipa_to_u32(ipa_mkmask(sn->px.len));
356
        ln->metric = sn->cost;
357 c15e5690 Ondrej Zajicek
        ln->padding = 0;
358 38675202 Ondrej Zajicek
        i++;
359
      }
360
361 3d15dcdb Ondrej Zajicek
  rt = po->lsab;
362 b9ed99f7 Ondrej Filip
  rt->links = i;
363 c3226991 Ondrej Zajicek
364
  if (bitv) 
365
    rt->options |= OPT_RT_V;
366
367 3d15dcdb Ondrej Zajicek
  *length = po->lsab_used + sizeof(struct ospf_lsa_header);
368
  return lsab_flush(po);
369 ce17d4c1 Ondrej Filip
}
370 c45f48fb Ondrej Filip
371 c3226991 Ondrej Zajicek
#else /* OSPFv3 */
372
373
static void
374
add_lsa_rt_link(struct proto_ospf *po, struct ospf_iface *ifa, u8 type, u32 nif, u32 id)
375
{
376
  struct ospf_lsa_rt_link *ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
377
  ln->type = type;
378
  ln->padding = 0;
379
  ln->metric = ifa->cost;
380 dd4da6f6 Ondrej Zajicek
  ln->lif = ifa->iface_id;
381 c3226991 Ondrej Zajicek
  ln->nif = nif;
382
  ln->id = id;
383
}
384
385
static void *
386
originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
387
{
388
  struct proto_ospf *po = oa->po;
389
  struct ospf_iface *ifa;
390 b49e6f5a Ondrej Zajicek
  int bitv = 0;
391 e7b4948c Ondrej Zajicek
  int i = 0;
392 c3226991 Ondrej Zajicek
  struct ospf_lsa_rt *rt;
393
  struct ospf_neighbor *neigh;
394
395
  ASSERT(po->lsab_used == 0);
396
  rt = lsab_allocz(po, sizeof(struct ospf_lsa_rt));
397
398
  rt->options = oa->options & OPTIONS_MASK;
399
400
  if (po->areano > 1)
401
    rt->options |= OPT_RT_B;
402
403 4160a9dd Ondrej Zajicek
  if ((po->areano > 1) && oa_is_nssa(oa) && oa->ac->translator)
404
    rt->options |= OPT_RT_NT;
405
406 41b612c3 Ondrej Zajicek
  if (po->ebit && !oa_is_stub(oa))
407 c3226991 Ondrej Zajicek
    rt->options |= OPT_RT_E;
408
409
  rt = NULL; /* buffer might be reallocated later */
410
411
  WALK_LIST(ifa, po->iface_list)
412
  {
413
    if ((ifa->type == OSPF_IT_VLINK) && (ifa->voa == oa) &&
414
        (!EMPTY_LIST(ifa->neigh_list)))
415
    {
416
      neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list);
417
      if ((neigh->state == NEIGHBOR_FULL) && (ifa->cost <= 0xffff))
418
        bitv = 1;
419
    }
420
421
    if ((ifa->oa != oa) || (ifa->state == OSPF_IS_DOWN))
422
      continue;
423
424 e7b4948c Ondrej Zajicek
    ifa->rt_pos_beg = i;
425
426 c3226991 Ondrej Zajicek
    /* RFC5340 - 4.4.3.2 */
427
    switch (ifa->type)
428
      {
429
      case OSPF_IT_PTP:
430 919f5411 Ondrej Zajicek
      case OSPF_IT_PTMP:
431
        WALK_LIST(neigh, ifa->neigh_list)
432
          if (neigh->state == NEIGHBOR_FULL)
433 e7b4948c Ondrej Zajicek
            add_lsa_rt_link(po, ifa, LSART_PTP, neigh->iface_id, neigh->rid), i++;
434 c3226991 Ondrej Zajicek
        break;
435
436
      case OSPF_IT_BCAST:
437
      case OSPF_IT_NBMA:
438
        if (bcast_net_active(ifa))
439 e7b4948c Ondrej Zajicek
          add_lsa_rt_link(po, ifa, LSART_NET, ifa->dr_iface_id, ifa->drid), i++;
440 c3226991 Ondrej Zajicek
        break;
441
442
      case OSPF_IT_VLINK:
443
        neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list);
444
        if ((!EMPTY_LIST(ifa->neigh_list)) && (neigh->state == NEIGHBOR_FULL) && (ifa->cost <= 0xffff))
445 e7b4948c Ondrej Zajicek
          add_lsa_rt_link(po, ifa, LSART_VLNK, neigh->iface_id, neigh->rid), i++;
446 c3226991 Ondrej Zajicek
        break;
447
448
      default:
449
        log("Unknown interface type %s", ifa->iface->name);
450
        break;
451
      }
452 e7b4948c Ondrej Zajicek
453
    ifa->rt_pos_end = i;
454 c3226991 Ondrej Zajicek
  }
455
456
  if (bitv)
457
    {
458
      rt = po->lsab;
459
      rt->options |= OPT_RT_V;
460
    }
461
462
  *length = po->lsab_used + sizeof(struct ospf_lsa_header);
463
  return lsab_flush(po);
464
}
465
466
#endif
467
468 7ab3ff6a Ondrej Filip
/**
469
 * originate_rt_lsa - build new instance of router LSA
470
 * @oa: ospf_area which is LSA built to
471
 *
472
 * It builds router LSA walking through all OSPF interfaces in
473
 * specified OSPF area. This function is mostly called from
474
 * area_disp(). Builds new LSA, increases sequence number (if old
475
 * instance exists) and sets age of LSA to zero.
476
 */
477 9bc1808a Ondrej Filip
void
478 70a38319 Ondrej Filip
originate_rt_lsa(struct ospf_area *oa)
479 d8852b36 Ondrej Filip
{
480
  struct ospf_lsa_header lsa;
481 b9ed99f7 Ondrej Filip
  struct proto_ospf *po = oa->po;
482
  struct proto *p = &po->proto;
483 d8852b36 Ondrej Filip
  void *body;
484
485 be862406 Ondrej Zajicek
  OSPF_TRACE(D_EVENTS, "Originating router-LSA for area %R", oa->areaid);
486 b9ed99f7 Ondrej Filip
487
  lsa.age = 0;
488
  lsa.type = LSA_T_RT;
489 c3226991 Ondrej Zajicek
  
490
#ifdef OSPFv2
491
  lsa.options = oa->options;
492 8a70a13e Ondrej Zajicek
  lsa.id = po->router_id;
493 cf31112f Ondrej Zajicek
#else /* OSPFv3 */
494
  lsa.id = 0;
495
#endif
496
497 8a70a13e Ondrej Zajicek
  lsa.rt = po->router_id;
498 52572e94 Ondrej Zajicek
  lsa.sn = get_seqnum(oa->rt);
499 c3226991 Ondrej Zajicek
  u32 dom = oa->areaid;
500
501 b9ed99f7 Ondrej Filip
  body = originate_rt_lsa_body(oa, &lsa.length);
502 d5d9693c Ondrej Filip
  lsasum_calculate(&lsa, body);
503 b49e6f5a Ondrej Zajicek
  oa->rt = lsa_install_new(po, &lsa, dom, body);
504
  ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
505
}
506
507
void
508
update_rt_lsa(struct ospf_area *oa)
509
{
510
  struct proto_ospf *po = oa->po;
511
512
  if ((oa->rt) && ((oa->rt->inst_t + MINLSINTERVAL)) > now)
513
    return;
514
  /*
515
   * Tick is probably set to very low value. We cannot
516
   * originate new LSA before MINLSINTERVAL. We will
517
   * try to do it next tick.
518
   */
519
520
  originate_rt_lsa(oa);
521 f9c799a0 Ondrej Zajicek
#ifdef OSPFv3
522 b49e6f5a Ondrej Zajicek
  originate_prefix_rt_lsa(oa);
523 f9c799a0 Ondrej Zajicek
#endif
524 b49e6f5a Ondrej Zajicek
525 b8f17cf1 Ondrej Filip
  schedule_rtcalc(po);
526 b9ed99f7 Ondrej Filip
  oa->origrt = 0;
527 ab56f6b1 Ondrej Filip
}
528
529 9831e591 Martin Mares
static void *
530 c3226991 Ondrej Zajicek
originate_net_lsa_body(struct ospf_iface *ifa, u16 *length,
531 b9ed99f7 Ondrej Filip
                       struct proto_ospf *po)
532 0bf2f203 Ondrej Filip
{
533 b9ed99f7 Ondrej Filip
  u16 i = 1;
534 0bf2f203 Ondrej Filip
  struct ospf_neighbor *n;
535 d345cda5 Ondrej Filip
  struct ospf_lsa_net *net;
536 c3226991 Ondrej Zajicek
  int nodes = ifa->fadj + 1;
537
538
  net = mb_alloc(po->proto.pool, sizeof(struct ospf_lsa_net)
539
                 + nodes * sizeof(u32));
540 0bf2f203 Ondrej Filip
541 c3226991 Ondrej Zajicek
#ifdef OSPFv2
542 353729f5 Ondrej Zajicek
  net->netmask = ipa_mkmask(ifa->addr->pxlen);
543 c3226991 Ondrej Zajicek
#endif
544
545
#ifdef OSPFv3
546
  /* In OSPFv3, we would like to merge options from Link LSAs of added neighbors */
547
  struct top_hash_entry *en;
548
  u32 options = 0;
549
#endif
550
551 8a70a13e Ondrej Zajicek
  net->routers[0] = po->router_id;
552 d345cda5 Ondrej Filip
553 b9ed99f7 Ondrej Filip
  WALK_LIST(n, ifa->neigh_list)
554 0bf2f203 Ondrej Filip
  {
555 b9ed99f7 Ondrej Filip
    if (n->state == NEIGHBOR_FULL)
556 0bf2f203 Ondrej Filip
    {
557 c3226991 Ondrej Zajicek
#ifdef OSPFv3
558 dd4da6f6 Ondrej Zajicek
      en = ospf_hash_find(po->gr, ifa->iface_id, n->iface_id, n->rid, LSA_T_LINK);
559 c3226991 Ondrej Zajicek
      if (en)
560
        options |= ((struct ospf_lsa_link *) en->lsa_body)->options;
561
#endif
562
563
      net->routers[i] = n->rid;
564 0bf2f203 Ondrej Filip
      i++;
565
    }
566
  }
567 c3226991 Ondrej Zajicek
  ASSERT(i == nodes);
568
569
#ifdef OSPFv3
570
  net->options = options & OPTIONS_MASK;
571
#endif
572
  
573
  *length = sizeof(struct ospf_lsa_header) + sizeof(struct ospf_lsa_net)
574
    + nodes * sizeof(u32);
575 d345cda5 Ondrej Filip
  return net;
576 0bf2f203 Ondrej Filip
}
577
578 b49e6f5a Ondrej Zajicek
579 7ab3ff6a Ondrej Filip
/**
580
 * originate_net_lsa - originates of deletes network LSA
581
 * @ifa: interface which is LSA originated for
582
 *
583 baa5dd6c Ondrej Filip
 * Interface counts number of adjacent neighbors. If this number is
584
 * lower than one or interface is not in state %OSPF_IS_DR it deletes
585 7ab3ff6a Ondrej Filip
 * and premature ages instance of network LSA for specified interface.
586
 * In other case, new instance of network LSA is originated.
587
 */
588 9bc1808a Ondrej Filip
void
589 7ab3ff6a Ondrej Filip
originate_net_lsa(struct ospf_iface *ifa)
590 0bf2f203 Ondrej Filip
{
591 86c84d76 Ondrej Filip
  struct proto_ospf *po = ifa->oa->po;
592 8a70a13e Ondrej Zajicek
  struct proto *p = &po->proto;
593 0bf2f203 Ondrej Filip
  struct ospf_lsa_header lsa;
594 c3226991 Ondrej Zajicek
  u32 dom = ifa->oa->areaid;
595 8a70a13e Ondrej Zajicek
  
596 0bf2f203 Ondrej Filip
  void *body;
597
598 be862406 Ondrej Zajicek
  OSPF_TRACE(D_EVENTS, "Originating network-LSA for iface %s",
599 b9ed99f7 Ondrej Filip
             ifa->iface->name);
600
601
  lsa.age = 0;
602
  lsa.type = LSA_T_NET;
603 c3226991 Ondrej Zajicek
604
#ifdef OSPFv2
605
  lsa.options = ifa->oa->options;
606 353729f5 Ondrej Zajicek
  lsa.id = ipa_to_u32(ifa->addr->ip);
607 c3226991 Ondrej Zajicek
#else /* OSPFv3 */
608 dd4da6f6 Ondrej Zajicek
  lsa.id = ifa->iface_id;
609 c3226991 Ondrej Zajicek
#endif
610
611 8a70a13e Ondrej Zajicek
  lsa.rt = po->router_id;
612 52572e94 Ondrej Zajicek
  lsa.sn = get_seqnum(ifa->net_lsa);
613 3dd8f983 Ondrej Filip
614 b9ed99f7 Ondrej Filip
  body = originate_net_lsa_body(ifa, &lsa.length, po);
615 d5d9693c Ondrej Filip
  lsasum_calculate(&lsa, body);
616 c3226991 Ondrej Zajicek
  ifa->net_lsa = lsa_install_new(po, &lsa, dom, body);
617
  ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
618 0bf2f203 Ondrej Filip
}
619
620 b49e6f5a Ondrej Zajicek
void
621
flush_net_lsa(struct ospf_iface *ifa)
622
{
623
  struct proto_ospf *po = ifa->oa->po;
624
  struct proto *p = &po->proto;
625
  u32 dom = ifa->oa->areaid;
626
627
  if (ifa->net_lsa == NULL)
628
    return;
629
630 be862406 Ondrej Zajicek
  OSPF_TRACE(D_EVENTS, "Flushing network-LSA for iface %s",
631 b49e6f5a Ondrej Zajicek
             ifa->iface->name);
632
  ifa->net_lsa->lsa.sn += 1;
633
  ifa->net_lsa->lsa.age = LSA_MAXAGE;
634
  lsasum_calculate(&ifa->net_lsa->lsa, ifa->net_lsa->lsa_body);
635
  ospf_lsupd_flood(po, NULL, NULL, &ifa->net_lsa->lsa, dom, 0);
636
  flush_lsa(ifa->net_lsa, po);
637
  ifa->net_lsa = NULL;
638
}
639
640
void
641
update_net_lsa(struct ospf_iface *ifa)
642
{
643
  struct proto_ospf *po = ifa->oa->po;
644
 
645
  if (ifa->net_lsa && ((ifa->net_lsa->inst_t + MINLSINTERVAL) > now))
646
    return;
647
  /*
648
   * It's too early to originate new network LSA. We will
649
   * try to do it next tick
650
   */
651
652
  if ((ifa->state != OSPF_IS_DR) || (ifa->fadj == 0))
653
    {
654
      flush_net_lsa(ifa);
655 f9c799a0 Ondrej Zajicek
#ifdef OSPFv3
656 b49e6f5a Ondrej Zajicek
      flush_prefix_net_lsa(ifa);
657 f9c799a0 Ondrej Zajicek
#endif
658 b49e6f5a Ondrej Zajicek
    }
659
  else
660
    {
661
      originate_net_lsa(ifa);
662 f9c799a0 Ondrej Zajicek
#ifdef OSPFv3
663 b49e6f5a Ondrej Zajicek
      originate_prefix_net_lsa(ifa);
664 f9c799a0 Ondrej Zajicek
#endif
665 b49e6f5a Ondrej Zajicek
    }
666
667
  schedule_rtcalc(po);
668
  ifa->orignet = 0;
669
}
670 98ac6176 Ondrej Filip
671 c3226991 Ondrej Zajicek
#ifdef OSPFv2
672
673 9727681a Ondrej Zajicek
static inline void *
674 c3226991 Ondrej Zajicek
originate_sum_lsa_body(struct proto_ospf *po, u16 *length, u32 mlen, u32 metric)
675 e8085aba Ondrej Filip
{
676 c3226991 Ondrej Zajicek
  struct ospf_lsa_sum *sum = mb_alloc(po->proto.pool, sizeof(struct ospf_lsa_sum));
677
  *length = sizeof(struct ospf_lsa_header) + sizeof(struct ospf_lsa_sum);
678 e8085aba Ondrej Filip
679 c3226991 Ondrej Zajicek
  sum->netmask = ipa_mkmask(mlen);
680
  sum->metric = metric;
681 e8085aba Ondrej Filip
682 c3226991 Ondrej Zajicek
  return sum;
683
}
684 5919c66e Martin Mares
685 c3226991 Ondrej Zajicek
#define originate_sum_net_lsa_body(po,length,fn,metric) \
686
  originate_sum_lsa_body(po, length, (fn)->pxlen, metric)
687 b9ed99f7 Ondrej Filip
688 c3226991 Ondrej Zajicek
#define originate_sum_rt_lsa_body(po,length,drid,metric,options) \
689
  originate_sum_lsa_body(po, length, 0, metric)
690 e8085aba Ondrej Filip
691 9727681a Ondrej Zajicek
static inline int
692
check_sum_net_lsaid_collision(struct fib_node *fn, struct top_hash_entry *en)
693
{
694
  struct ospf_lsa_sum *sum = en->lsa_body;
695 98955023 Ondrej Zajicek
  return fn->pxlen != ipa_mklen(sum->netmask);
696 9727681a Ondrej Zajicek
}
697
698
static inline int
699 7ff5803b Ondrej Zajicek
check_sum_lsa_same(struct top_hash_entry *en, u32 metric)
700 9727681a Ondrej Zajicek
{
701 7ff5803b Ondrej Zajicek
  /* Netmask already checked in check_sum_net_lsaid_collision() */
702
  struct ospf_lsa_sum *sum = en->lsa_body;
703 d395fe48 Ondrej Zajicek
  return (en->lsa.sn != LSA_MAXSEQNO) && (sum->metric == metric);
704 9727681a Ondrej Zajicek
}
705
706 7ff5803b Ondrej Zajicek
#define check_sum_net_lsa_same(en,metric) \
707
  check_sum_lsa_same(en, metric)
708
709
#define check_sum_rt_lsa_same(en,drid,metric,options) \
710
  check_sum_lsa_same(en, metric)
711
712
713 c3226991 Ondrej Zajicek
#else /* OSPFv3 */
714 0077aab4 Martin Mares
715 9727681a Ondrej Zajicek
static inline void *
716 c3226991 Ondrej Zajicek
originate_sum_net_lsa_body(struct proto_ospf *po, u16 *length, struct fib_node *fn, u32 metric)
717 0077aab4 Martin Mares
{
718 c3226991 Ondrej Zajicek
  int size = sizeof(struct ospf_lsa_sum_net) + IPV6_PREFIX_SPACE(fn->pxlen);
719
  struct ospf_lsa_sum_net *sum = mb_alloc(po->proto.pool, size);
720
  *length = sizeof(struct ospf_lsa_header) + size;
721
722
  sum->metric = metric;
723
  put_ipv6_prefix(sum->prefix, fn->prefix, fn->pxlen, 0, 0);
724
725
  return sum;
726
}
727
728 9727681a Ondrej Zajicek
static inline int
729
check_sum_net_lsaid_collision(struct fib_node *fn, struct top_hash_entry *en)
730
{
731
  struct ospf_lsa_sum_net *sum = en->lsa_body;
732
  ip_addr prefix;
733
  int pxlen;
734
  u8 pxopts;
735
  u16 rest;
736
737
  lsa_get_ipv6_prefix(sum->prefix, &prefix, &pxlen, &pxopts, &rest);
738
  return (fn->pxlen != pxlen) || !ipa_equal(fn->prefix, prefix);
739
}
740
741
static inline int
742 7ff5803b Ondrej Zajicek
check_sum_net_lsa_same(struct top_hash_entry *en, u32 metric)
743 9727681a Ondrej Zajicek
{
744 7ff5803b Ondrej Zajicek
  /* Prefix already checked in check_sum_net_lsaid_collision() */
745
  struct ospf_lsa_sum_net *sum = en->lsa_body;
746 d395fe48 Ondrej Zajicek
  return (en->lsa.sn != LSA_MAXSEQNO) && (sum->metric == metric);
747 9727681a Ondrej Zajicek
}
748
749
static inline void *
750 c3226991 Ondrej Zajicek
originate_sum_rt_lsa_body(struct proto_ospf *po, u16 *length, u32 drid, u32 metric, u32 options)
751
{
752
  struct ospf_lsa_sum_rt *sum = mb_alloc(po->proto.pool, sizeof(struct ospf_lsa_sum_rt));
753
  *length = sizeof(struct ospf_lsa_header) + sizeof(struct ospf_lsa_sum_rt);
754
755 7ff5803b Ondrej Zajicek
  sum->options = options;
756 c3226991 Ondrej Zajicek
  sum->metric = metric;
757
  sum->drid = drid;
758
759
  return sum;
760 0077aab4 Martin Mares
}
761
762 7ff5803b Ondrej Zajicek
static inline int
763
check_sum_rt_lsa_same(struct top_hash_entry *en, u32 drid, u32 metric, u32 options)
764
{
765
  struct ospf_lsa_sum_rt *sum = en->lsa_body;
766 d395fe48 Ondrej Zajicek
  return (en->lsa.sn != LSA_MAXSEQNO) && (sum->options == options) &&
767
    (sum->metric == metric) && (sum->drid == drid);
768 7ff5803b Ondrej Zajicek
}
769
770 c3226991 Ondrej Zajicek
#endif
771
772 98ac6176 Ondrej Filip
void
773 9727681a Ondrej Zajicek
originate_sum_net_lsa(struct ospf_area *oa, struct fib_node *fn, int metric)
774 98ac6176 Ondrej Filip
{
775
  struct proto_ospf *po = oa->po;
776
  struct proto *p = &po->proto;
777
  struct top_hash_entry *en;
778 9727681a Ondrej Zajicek
  u32 dom = oa->areaid;
779 98ac6176 Ondrej Filip
  struct ospf_lsa_header lsa;
780 c3226991 Ondrej Zajicek
  void *body;
781 98ac6176 Ondrej Filip
782 9727681a Ondrej Zajicek
  OSPF_TRACE(D_EVENTS, "Originating net-summary-LSA for %I/%d (metric %d)",
783
             fn->prefix, fn->pxlen, metric);
784 c3226991 Ondrej Zajicek
785 9727681a Ondrej Zajicek
  /* options argument is used in ORT_NET and OSPFv3 only */
786 c3226991 Ondrej Zajicek
  lsa.age = 0;
787
#ifdef OSPFv2
788
  lsa.options = oa->options;
789
#endif
790 9727681a Ondrej Zajicek
  lsa.type = LSA_T_SUM_NET;
791
  lsa.id = fibnode_to_lsaid(po, fn);
792 8a70a13e Ondrej Zajicek
  lsa.rt = po->router_id;
793 98ac6176 Ondrej Filip
794 9727681a Ondrej Zajicek
  if ((en = ospf_hash_find_header(po->gr, dom, &lsa)) != NULL)
795
  {
796
    if (check_sum_net_lsaid_collision(fn, en))
797 7ff5803b Ondrej Zajicek
    {
798 35c875f0 Ondrej Zajicek
      log(L_ERR "%s: LSAID collision for %I/%d",
799 7ff5803b Ondrej Zajicek
          p->name, fn->prefix, fn->pxlen);
800
      return;
801
    }
802
803
    if (check_sum_net_lsa_same(en, metric))
804
      return;
805 9727681a Ondrej Zajicek
  }
806 52572e94 Ondrej Zajicek
  lsa.sn = get_seqnum(en);
807 c3226991 Ondrej Zajicek
808 9727681a Ondrej Zajicek
  body = originate_sum_net_lsa_body(po, &lsa.length, fn, metric);
809
  lsasum_calculate(&lsa, body);
810 d494df63 Ondrej Zajicek
  lsa_install_new(po, &lsa, dom, body);
811 9727681a Ondrej Zajicek
  ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
812
}
813 c3226991 Ondrej Zajicek
814 9727681a Ondrej Zajicek
void
815 e81b440f Ondrej Zajicek
originate_sum_rt_lsa(struct ospf_area *oa, struct fib_node *fn, int metric, u32 options UNUSED)
816 9727681a Ondrej Zajicek
{
817
  struct proto_ospf *po = oa->po;
818
  struct proto *p = &po->proto;
819
  struct top_hash_entry *en;
820 353729f5 Ondrej Zajicek
  u32 dom = oa->areaid;
821
  u32 rid = ipa_to_rid(fn->prefix);
822 9727681a Ondrej Zajicek
  struct ospf_lsa_header lsa;
823
  void *body;
824 c3226991 Ondrej Zajicek
825 9727681a Ondrej Zajicek
  OSPF_TRACE(D_EVENTS, "Originating rt-summary-LSA for %R (metric %d)",
826 353729f5 Ondrej Zajicek
             rid, metric);
827 9727681a Ondrej Zajicek
828
  lsa.age = 0;
829
#ifdef OSPFv2
830
  lsa.options = oa->options;
831
#endif
832
  lsa.type = LSA_T_SUM_RT;
833
  /* In OSPFv3, LSA ID is meaningless, but we still use Router ID of ASBR */
834 353729f5 Ondrej Zajicek
  lsa.id = rid;
835 8a70a13e Ondrej Zajicek
  lsa.rt = po->router_id;
836 9727681a Ondrej Zajicek
837 7ff5803b Ondrej Zajicek
  options &= OPTIONS_MASK;
838 9727681a Ondrej Zajicek
  if ((en = ospf_hash_find_header(po->gr, dom, &lsa)) != NULL)
839 7ff5803b Ondrej Zajicek
  {
840
    if (check_sum_rt_lsa_same(en, lsa.id, metric, options))
841
      return;
842
  }
843 52572e94 Ondrej Zajicek
  lsa.sn = get_seqnum(en);
844 c3226991 Ondrej Zajicek
845 9727681a Ondrej Zajicek
  body = originate_sum_rt_lsa_body(po, &lsa.length, lsa.id, metric, options);
846 c3226991 Ondrej Zajicek
  lsasum_calculate(&lsa, body);
847 d494df63 Ondrej Zajicek
  lsa_install_new(po, &lsa, dom, body);
848 c3226991 Ondrej Zajicek
  ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
849 98ac6176 Ondrej Filip
}
850
851 9727681a Ondrej Zajicek
void
852 c3226991 Ondrej Zajicek
flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
853 98ac6176 Ondrej Filip
{
854
  struct proto_ospf *po = oa->po;
855
  struct proto *p = &po->proto;
856
  struct top_hash_entry *en;
857
  struct ospf_lsa_header lsa;
858
859 8a70a13e Ondrej Zajicek
  lsa.rt = po->router_id;
860 c3226991 Ondrej Zajicek
  if (type == ORT_NET)
861 98ac6176 Ondrej Filip
    {
862 d82fc18d Ondrej Zajicek
      lsa.id = fibnode_to_lsaid(po, fn);
863 c3226991 Ondrej Zajicek
      lsa.type = LSA_T_SUM_NET;
864 98ac6176 Ondrej Filip
    }
865 c3226991 Ondrej Zajicek
  else
866 98ac6176 Ondrej Filip
    {
867 9727681a Ondrej Zajicek
      /* In OSPFv3, LSA ID is meaningless, but we still use Router ID of ASBR */
868 c3226991 Ondrej Zajicek
      lsa.id = ipa_to_rid(fn->prefix);
869
      lsa.type = LSA_T_SUM_RT;
870 98ac6176 Ondrej Filip
    }
871
872 b49e6f5a Ondrej Zajicek
  if ((en = ospf_hash_find_header(po->gr, oa->areaid, &lsa)) != NULL)
873 c3226991 Ondrej Zajicek
    {
874 bbcfd5a0 Ondrej Zajicek
      OSPF_TRACE(D_EVENTS, "Flushing summary-LSA (id=%R, type=%d)",
875
                 en->lsa.id, en->lsa.type);
876
877 9727681a Ondrej Zajicek
      if ((type == ORT_NET) && check_sum_net_lsaid_collision(fn, en))
878
        {
879 35c875f0 Ondrej Zajicek
          log(L_ERR "%s: LSAID collision for %I/%d",
880 9727681a Ondrej Zajicek
              p->name, fn->prefix, fn->pxlen);
881
          return;
882
        }
883
884 c3226991 Ondrej Zajicek
      struct ospf_lsa_sum *sum = en->lsa_body;
885
      en->lsa.age = LSA_MAXAGE;
886
      en->lsa.sn = LSA_MAXSEQNO;
887
      lsasum_calculate(&en->lsa, sum);
888
      ospf_lsupd_flood(po, NULL, NULL, &en->lsa, oa->areaid, 1);
889
      if (can_flush_lsa(po)) flush_lsa(en, po);
890
    }
891 98ac6176 Ondrej Filip
}
892
893 7ff5803b Ondrej Zajicek
#ifdef OSPFv2
894 c3226991 Ondrej Zajicek
895 7ff5803b Ondrej Zajicek
static inline void *
896 ed317862 Ondrej Zajicek
originate_ext_lsa_body(struct proto_ospf *po, u16 *length, struct fib_node *fn,
897 2918e610 Ondrej Zajicek
                       u32 metric, ip_addr fwaddr, u32 tag, int pbit UNUSED)
898 c3226991 Ondrej Zajicek
{
899 7ff5803b Ondrej Zajicek
  struct ospf_lsa_ext *ext = mb_alloc(po->proto.pool, sizeof(struct ospf_lsa_ext));
900
  *length = sizeof(struct ospf_lsa_header) + sizeof(struct ospf_lsa_ext);
901 c3226991 Ondrej Zajicek
902 7ff5803b Ondrej Zajicek
  ext->metric = metric; 
903 ed317862 Ondrej Zajicek
  ext->netmask = ipa_mkmask(fn->pxlen);
904 7ff5803b Ondrej Zajicek
  ext->fwaddr = fwaddr;
905
  ext->tag = tag;
906 c3226991 Ondrej Zajicek
907 7ff5803b Ondrej Zajicek
  return ext;
908
}
909 c3226991 Ondrej Zajicek
910 7ff5803b Ondrej Zajicek
/*
911
 * check_ext_lsa() combines functions of check_*_lsaid_collision() and
912
 * check_*_lsa_same(). 'en' is existing ext LSA, and rest parameters
913
 * are parameters of new ext route.  Function returns -1 if there is
914
 * LSAID collision, returns 1 if the existing LSA is the same and
915
 * returns 0 otherwise (in that case, we need to originate a new LSA).
916
 *
917
 * Really, checking for the same parameters is not as important as in
918
 * summary LSA origination, because in most cases the duplicate
919
 * external route propagation would be stopped by the nest. But there
920
 * are still some cases (route reload, the same route propagated through
921
 * different protocol) so it is also done here.
922
 */
923 c3226991 Ondrej Zajicek
924 7ff5803b Ondrej Zajicek
static inline int
925
check_ext_lsa(struct top_hash_entry *en, struct fib_node *fn, u32 metric, ip_addr fwaddr, u32 tag)
926
{
927
  struct ospf_lsa_ext *ext = en->lsa_body;
928
929
  /* LSAID collision */
930
  if  (fn->pxlen != ipa_mklen(ext->netmask))
931
    return -1;
932
933 d395fe48 Ondrej Zajicek
  return (en->lsa.sn != LSA_MAXSEQNO) && (ext->metric == metric) &&
934
    (ext->tag == tag) && ipa_equal(ext->fwaddr,fwaddr);
935 7ff5803b Ondrej Zajicek
}
936 c3226991 Ondrej Zajicek
937
#else /* OSPFv3 */
938 7ff5803b Ondrej Zajicek
939
static inline void *
940 ed317862 Ondrej Zajicek
originate_ext_lsa_body(struct proto_ospf *po, u16 *length, struct fib_node *fn,
941 2918e610 Ondrej Zajicek
                       u32 metric, ip_addr fwaddr, u32 tag, int pbit)
942 7ff5803b Ondrej Zajicek
{
943
  int size = sizeof(struct ospf_lsa_ext)
944 2918e610 Ondrej Zajicek
    + IPV6_PREFIX_SPACE(fn->pxlen)
945 7ff5803b Ondrej Zajicek
    + (ipa_nonzero(fwaddr) ? 16 : 0)
946
    + (tag ? 4 : 0);
947
948
  struct ospf_lsa_ext *ext = mb_alloc(po->proto.pool, size);
949
  *length = sizeof(struct ospf_lsa_header) + size;
950
951
  ext->metric = metric;
952
953 e81b440f Ondrej Zajicek
  u32 *buf = ext->rest;
954 2918e610 Ondrej Zajicek
  buf = put_ipv6_prefix(buf, fn->prefix, fn->pxlen, pbit ? OPT_PX_P : 0, 0);
955 c3226991 Ondrej Zajicek
956 7ff5803b Ondrej Zajicek
  if (ipa_nonzero(fwaddr))
957
  {
958
    ext->metric |= LSA_EXT_FBIT;
959
    buf = put_ipv6_addr(buf, fwaddr);
960
  }
961 c3226991 Ondrej Zajicek
962
  if (tag)
963 7ff5803b Ondrej Zajicek
  {
964
    ext->metric |= LSA_EXT_TBIT;
965
    *buf++ = tag;
966
  }
967 c3226991 Ondrej Zajicek
968
  return ext;
969
}
970
971 7ff5803b Ondrej Zajicek
static inline int
972
check_ext_lsa(struct top_hash_entry *en, struct fib_node *fn, u32 metric, ip_addr fwaddr, u32 tag)
973
{
974
  struct ospf_lsa_ext *ext = en->lsa_body;
975
  ip_addr prefix;
976
  int pxlen;
977
  u8 pxopts;
978
  u16 rest;
979
980
  u32 *buf = lsa_get_ipv6_prefix(ext->rest, &prefix, &pxlen, &pxopts, &rest);
981
982
  /* LSAID collision */
983
  if ((fn->pxlen != pxlen) || !ipa_equal(fn->prefix, prefix))
984
    return -1;
985
986 d395fe48 Ondrej Zajicek
  if (en->lsa.sn == LSA_MAXSEQNO)
987
    return 0;
988
989 7ff5803b Ondrej Zajicek
  u32 rt_metric = ext->metric & METRIC_MASK;
990
  ip_addr rt_fwaddr = IPA_NONE;
991
  u32 rt_tag = 0;
992
993
  if (ext->metric & LSA_EXT_FBIT)
994
    buf = lsa_get_ipv6_addr(buf, &rt_fwaddr);
995
996
  if (ext->metric & LSA_EXT_TBIT)
997
    rt_tag = *buf++;
998
999
  return (rt_metric == metric) && ipa_equal(rt_fwaddr, fwaddr) && (rt_tag == tag);
1000
}
1001
1002
1003
#endif
1004
1005 2918e610 Ondrej Zajicek
static inline ip_addr
1006
find_surrogate_fwaddr(struct ospf_area *oa)
1007
{
1008
  struct proto_ospf *po = oa->po;
1009
  struct ospf_iface *ifa;
1010
  struct ifa *a, *cur_addr = NULL;
1011
  int np, cur_np = 0;
1012
1013
  WALK_LIST(ifa, po->iface_list)
1014
  {
1015
    if ((ifa->oa != oa) ||
1016
        (ifa->type == OSPF_IT_VLINK))
1017
      continue;
1018
1019
#ifdef OSPFv2
1020
    a = ifa->addr;
1021
    if (a->flags & IA_PEER)
1022
      continue;
1023
1024
    np = ((a->flags & IA_HOST) || ifa->stub) ? 2 : 1;
1025
    if (np > cur_np)
1026
    {
1027
      cur_addr = a;
1028
      cur_np = np;
1029
    }
1030
1031
#else /* OSPFv3 */
1032
    WALK_LIST(a, ifa->iface->addrs)
1033
    {
1034
      if ((a->flags & IA_SECONDARY) ||
1035
          (a->flags & IA_PEER) ||
1036
          (a->scope <= SCOPE_LINK))
1037
        continue;
1038
1039
      np = ((a->flags & IA_HOST) || ifa->stub) ? 2 : 1;
1040
      if (np > cur_np)
1041
      {
1042
        cur_addr = a;
1043
        cur_np = np;
1044
      }
1045
    }
1046
#endif
1047
  }
1048
1049
  return cur_addr ? cur_addr->ip : IPA_NONE;
1050
}
1051
1052
1053 0077aab4 Martin Mares
/**
1054 baa5dd6c Ondrej Filip
 * originate_ext_lsa - new route received from nest and filters
1055 41b612c3 Ondrej Zajicek
 * @oa: ospf_area for which LSA is originated
1056 ed317862 Ondrej Zajicek
 * @fn: network prefix and mask
1057 2918e610 Ondrej Zajicek
 * @src: the source of origination of the LSA (EXT_EXPORT/EXT_NSSA)
1058 ed317862 Ondrej Zajicek
 * @metric: the metric of a route
1059
 * @fwaddr: the forwarding address
1060
 * @tag: the route tag
1061 2918e610 Ondrej Zajicek
 * @pbit: P-bit for NSSA LSAs, ignored for external LSAs
1062 7ab3ff6a Ondrej Filip
 *
1063 baa5dd6c Ondrej Filip
 * If I receive a message that new route is installed, I try to originate an
1064 41b612c3 Ondrej Zajicek
 * external LSA. If @oa is an NSSA area, NSSA-LSA is originated instead.
1065 2918e610 Ondrej Zajicek
 * @oa should not be a stub area. @src does not specify whether the LSA
1066
 * is external or NSSA, but it specifies the source of origination - 
1067
 * the export from ospf_rt_notify(), or the NSSA-EXT translation.
1068 fdb19982 Ondrej Filip
 *
1069 baa5dd6c Ondrej Filip
 * The function also sets flag ebit. If it's the first time, the new router lsa
1070 fdb19982 Ondrej Filip
 * origination is necessary.
1071 7ab3ff6a Ondrej Filip
 */
1072 e8085aba Ondrej Filip
void
1073 2918e610 Ondrej Zajicek
originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src,
1074
                  u32 metric, ip_addr fwaddr, u32 tag, int pbit)
1075 e8085aba Ondrej Filip
{
1076 41b612c3 Ondrej Zajicek
  struct proto_ospf *po = oa->po;
1077 be862406 Ondrej Zajicek
  struct proto *p = &po->proto;
1078 e8085aba Ondrej Filip
  struct ospf_lsa_header lsa;
1079 b9ed99f7 Ondrej Filip
  struct top_hash_entry *en = NULL;
1080 c3226991 Ondrej Zajicek
  void *body;
1081 41b612c3 Ondrej Zajicek
  int nssa = oa_is_nssa(oa);
1082
  u32 dom = nssa ? oa->areaid : 0;
1083
1084
  OSPF_TRACE(D_EVENTS, "Originating %s-LSA for %I/%d",
1085
             nssa ? "NSSA" : "AS-external", fn->prefix, fn->pxlen);
1086 b9ed99f7 Ondrej Filip
1087
  lsa.age = 0;
1088 c3226991 Ondrej Zajicek
#ifdef OSPFv2
1089 2918e610 Ondrej Zajicek
  lsa.options = nssa ? (pbit ? OPT_P : 0) : OPT_E;
1090 c3226991 Ondrej Zajicek
#endif
1091 41b612c3 Ondrej Zajicek
  lsa.type = nssa ? LSA_T_NSSA : LSA_T_EXT;
1092 9727681a Ondrej Zajicek
  lsa.id = fibnode_to_lsaid(po, fn);
1093 8a70a13e Ondrej Zajicek
  lsa.rt = po->router_id;
1094 273fd2c1 Ondrej Filip
1095 2918e610 Ondrej Zajicek
  if (nssa && pbit && ipa_zero(fwaddr))
1096 41b612c3 Ondrej Zajicek
  {
1097 2918e610 Ondrej Zajicek
    /* NSSA-LSA with P-bit set must have non-zero forwarding address */
1098
1099
    fwaddr = find_surrogate_fwaddr(oa);
1100
    if (ipa_zero(fwaddr))
1101
    {
1102 35c875f0 Ondrej Zajicek
      log(L_ERR "%s: Cannot find forwarding address for NSSA-LSA %I/%d",
1103 2918e610 Ondrej Zajicek
          p->name, fn->prefix, fn->pxlen);
1104
      return;
1105
    }
1106 41b612c3 Ondrej Zajicek
  }
1107
1108
  if ((en = ospf_hash_find_header(po->gr, dom, &lsa)) != NULL)
1109 7ff5803b Ondrej Zajicek
  {
1110 ed317862 Ondrej Zajicek
    int rv = check_ext_lsa(en, fn, metric, fwaddr, tag);
1111 7ff5803b Ondrej Zajicek
    if (rv < 0)
1112 273fd2c1 Ondrej Filip
    {
1113 35c875f0 Ondrej Zajicek
      log(L_ERR "%s: LSAID collision for %I/%d",
1114 7ff5803b Ondrej Zajicek
          p->name, fn->prefix, fn->pxlen);
1115
      return;
1116 273fd2c1 Ondrej Filip
    }
1117
1118 7ff5803b Ondrej Zajicek
    if (rv > 0)
1119
      return;
1120
  }
1121 52572e94 Ondrej Zajicek
  lsa.sn = get_seqnum(en);
1122 7ff5803b Ondrej Zajicek
1123 2918e610 Ondrej Zajicek
  body = originate_ext_lsa_body(po, &lsa.length, fn, metric, fwaddr, tag, pbit);
1124 d5d9693c Ondrej Filip
  lsasum_calculate(&lsa, body);
1125 c3226991 Ondrej Zajicek
1126 2918e610 Ondrej Zajicek
  if (src) 
1127
    fn->x1 = src;
1128
1129 d494df63 Ondrej Zajicek
  lsa_install_new(po, &lsa, dom, body);
1130 41b612c3 Ondrej Zajicek
  ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
1131 fdb19982 Ondrej Filip
1132 b9ed99f7 Ondrej Filip
  if (po->ebit == 0)
1133 fdb19982 Ondrej Filip
  {
1134 b9ed99f7 Ondrej Filip
    po->ebit = 1;
1135 fdb19982 Ondrej Filip
    WALK_LIST(oa, po->area_list)
1136
    {
1137
      schedule_rt_lsa(oa);
1138
    }
1139
  }
1140 e8085aba Ondrej Filip
}
1141
1142 c3226991 Ondrej Zajicek
void
1143 bbcfd5a0 Ondrej Zajicek
flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int nssa)
1144 c3226991 Ondrej Zajicek
{
1145 41b612c3 Ondrej Zajicek
  struct proto_ospf *po = oa->po;
1146 be862406 Ondrej Zajicek
  struct proto *p = &po->proto;
1147 c3226991 Ondrej Zajicek
  struct top_hash_entry *en;
1148 be862406 Ondrej Zajicek
1149 41b612c3 Ondrej Zajicek
  u32 dom = nssa ? oa->areaid : 0;
1150
  u32 type = nssa ? LSA_T_NSSA : LSA_T_EXT;
1151 9727681a Ondrej Zajicek
  u32 lsaid = fibnode_to_lsaid(po, fn);
1152 c3226991 Ondrej Zajicek
1153 41b612c3 Ondrej Zajicek
  if (en = ospf_hash_find(po->gr, dom, lsaid, po->router_id, type))
1154 c3226991 Ondrej Zajicek
    {
1155 bbcfd5a0 Ondrej Zajicek
      OSPF_TRACE(D_EVENTS, "Flushing %s-LSA for %I/%d",
1156
                 nssa ? "NSSA" : "AS-external", fn->prefix, fn->pxlen);
1157
1158 7ff5803b Ondrej Zajicek
      if (check_ext_lsa(en, fn, 0, IPA_NONE, 0) < 0)
1159 c3226991 Ondrej Zajicek
        {
1160 35c875f0 Ondrej Zajicek
          log(L_ERR "%s: LSAID collision for %I/%d",
1161 9727681a Ondrej Zajicek
              p->name, fn->prefix, fn->pxlen);
1162
          return;
1163 c3226991 Ondrej Zajicek
        }
1164 9727681a Ondrej Zajicek
1165 ed317862 Ondrej Zajicek
      fn->x1 = 0;
1166 9727681a Ondrej Zajicek
      ospf_lsupd_flush_nlsa(po, en);
1167 c3226991 Ondrej Zajicek
    }
1168
}
1169
1170
1171
#ifdef OSPFv3
1172
1173
static void *
1174
originate_link_lsa_body(struct ospf_iface *ifa, u16 *length)
1175
{
1176
  struct proto_ospf *po = ifa->oa->po;
1177
  struct ospf_lsa_link *ll;
1178
  int i = 0;
1179
  u8 flags;
1180
1181
  ASSERT(po->lsab_used == 0);
1182
  ll = lsab_allocz(po, sizeof(struct ospf_lsa_link));
1183
  ll->options = ifa->oa->options | (ifa->priority << 24);
1184 353729f5 Ondrej Zajicek
  ll->lladdr = ifa->addr->ip;
1185 c3226991 Ondrej Zajicek
  ll = NULL; /* buffer might be reallocated later */
1186
1187
  struct ifa *a;
1188
  WALK_LIST(a, ifa->iface->addrs)
1189
    {
1190
      if ((a->flags & IA_SECONDARY) ||
1191
          (a->scope < SCOPE_SITE))
1192
        continue;
1193
1194
      flags = (a->pxlen < MAX_PREFIX_LENGTH) ? 0 : OPT_PX_LA;
1195
      put_ipv6_prefix(lsab_alloc(po, IPV6_PREFIX_SPACE(a->pxlen)),
1196
                      a->ip, a->pxlen, flags, 0);
1197
      i++;
1198
    }
1199
1200
  ll = po->lsab;
1201
  ll->pxcount = i;
1202
  *length = po->lsab_used + sizeof(struct ospf_lsa_header);
1203
  return lsab_flush(po);
1204
}
1205
1206
void
1207
originate_link_lsa(struct ospf_iface *ifa)
1208
{
1209
  struct ospf_lsa_header lsa;
1210
  struct proto_ospf *po = ifa->oa->po;
1211
  struct proto *p = &po->proto;
1212
  void *body;
1213
1214
  /* FIXME check for vlink and skip that? */
1215 be862406 Ondrej Zajicek
  OSPF_TRACE(D_EVENTS, "Originating link-LSA for iface %s", ifa->iface->name);
1216 c3226991 Ondrej Zajicek
1217
  lsa.age = 0;
1218
  lsa.type = LSA_T_LINK;
1219 dd4da6f6 Ondrej Zajicek
  lsa.id = ifa->iface_id;
1220 8a70a13e Ondrej Zajicek
  lsa.rt = po->router_id;
1221 52572e94 Ondrej Zajicek
  lsa.sn = get_seqnum(ifa->link_lsa);
1222 dd4da6f6 Ondrej Zajicek
  u32 dom = ifa->iface_id;
1223 c3226991 Ondrej Zajicek
1224
  body = originate_link_lsa_body(ifa, &lsa.length);
1225
  lsasum_calculate(&lsa, body);
1226
  ifa->link_lsa = lsa_install_new(po, &lsa, dom, body);
1227
  ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
1228 be862406 Ondrej Zajicek
1229
  /* Just to be sure to not forget on our link LSA */
1230
  if (ifa->state == OSPF_IS_DR)
1231
    schedule_net_lsa(ifa);
1232 c3226991 Ondrej Zajicek
}
1233
1234 b49e6f5a Ondrej Zajicek
void
1235
update_link_lsa(struct ospf_iface *ifa)
1236
{
1237
  if (ifa->link_lsa && ((ifa->link_lsa->inst_t + MINLSINTERVAL) > now))
1238
    return;
1239
  /*
1240
   * It's too early to originate new link LSA. We will
1241
   * try to do it next tick
1242
   */
1243
  originate_link_lsa(ifa);
1244
  ifa->origlink = 0;
1245
}
1246 c3226991 Ondrej Zajicek
1247 d9e7e1b1 Ondrej Zajicek
static inline void
1248
lsa_put_prefix(struct proto_ospf *po, ip_addr prefix, u32 pxlen, u32 cost)
1249
{
1250
  put_ipv6_prefix(lsab_alloc(po, IPV6_PREFIX_SPACE(pxlen)), prefix, pxlen,
1251
                  (pxlen < MAX_PREFIX_LENGTH) ? 0 : OPT_PX_LA, cost);
1252
}
1253
1254 c3226991 Ondrej Zajicek
static void *
1255
originate_prefix_rt_lsa_body(struct ospf_area *oa, u16 *length)
1256
{
1257
  struct proto_ospf *po = oa->po;
1258 8e48831a Ondrej Zajicek
  struct ospf_config *cf = (struct ospf_config *) (po->proto.cf);
1259 c3226991 Ondrej Zajicek
  struct ospf_iface *ifa;
1260
  struct ospf_lsa_prefix *lp;
1261 3b89a232 Ondrej Zajicek
  int host_addr = 0;
1262 c3226991 Ondrej Zajicek
  int net_lsa;
1263
  int i = 0;
1264
1265
  ASSERT(po->lsab_used == 0);
1266
  lp = lsab_allocz(po, sizeof(struct ospf_lsa_prefix));
1267
  lp->ref_type = LSA_T_RT;
1268
  lp->ref_id = 0;
1269 8a70a13e Ondrej Zajicek
  lp->ref_rt = po->router_id;
1270 c3226991 Ondrej Zajicek
  lp = NULL; /* buffer might be reallocated later */
1271
1272
  WALK_LIST(ifa, po->iface_list)
1273
  {
1274 e4404cef Ondrej Zajicek
    if ((ifa->oa != oa) || (ifa->type == OSPF_IT_VLINK) || (ifa->state == OSPF_IS_DOWN))
1275 c3226991 Ondrej Zajicek
      continue;
1276
1277 e7b4948c Ondrej Zajicek
    ifa->px_pos_beg = i;
1278
1279 c3226991 Ondrej Zajicek
    if ((ifa->type == OSPF_IT_BCAST) ||
1280
        (ifa->type == OSPF_IT_NBMA))
1281
      net_lsa = bcast_net_active(ifa);
1282
    else
1283
      net_lsa = 0;
1284
1285
    struct ifa *a;
1286
    WALK_LIST(a, ifa->iface->addrs)
1287
      {
1288 3b89a232 Ondrej Zajicek
        if ((a->flags & IA_SECONDARY) ||
1289 52a43ae3 Ondrej Zajicek
            (a->flags & IA_PEER) ||
1290 3b89a232 Ondrej Zajicek
            (a->scope <= SCOPE_LINK))
1291
          continue;
1292
1293
        if (((a->pxlen < MAX_PREFIX_LENGTH) && net_lsa) ||
1294 c3226991 Ondrej Zajicek
            configured_stubnet(oa, a))
1295
          continue;
1296
1297 52a43ae3 Ondrej Zajicek
        if ((a->flags & IA_HOST) ||
1298
            (ifa->state == OSPF_IS_LOOP) ||
1299
            (ifa->type == OSPF_IT_PTMP))
1300
        {
1301 d9e7e1b1 Ondrej Zajicek
          lsa_put_prefix(po, a->ip, MAX_PREFIX_LENGTH, 0);
1302 52a43ae3 Ondrej Zajicek
          host_addr = 1;
1303
        }
1304 d9e7e1b1 Ondrej Zajicek
        else
1305
          lsa_put_prefix(po, a->prefix, a->pxlen, ifa->cost);
1306 c3226991 Ondrej Zajicek
        i++;
1307
      }
1308 e7b4948c Ondrej Zajicek
1309
    ifa->px_pos_end = i;
1310 c3226991 Ondrej Zajicek
  }
1311
1312
  struct ospf_stubnet_config *sn;
1313 5cdf264f Ondrej Zajicek
  if (oa->ac)
1314
    WALK_LIST(sn, oa->ac->stubnet_list)
1315
      if (!sn->hidden)
1316 c3226991 Ondrej Zajicek
      {
1317 d9e7e1b1 Ondrej Zajicek
        lsa_put_prefix(po, sn->px.addr, sn->px.len, sn->cost);
1318 e4404cef Ondrej Zajicek
        if (sn->px.len == MAX_PREFIX_LENGTH)
1319
          host_addr = 1;
1320
        i++;
1321
      }
1322
1323
  /* If there are some configured vlinks, find some global address
1324
     (even from another area), which will be used as a vlink endpoint. */
1325
  if (!EMPTY_LIST(cf->vlink_list) && !host_addr)
1326
  {
1327
    WALK_LIST(ifa, po->iface_list)
1328
    {
1329
      if ((ifa->type == OSPF_IT_VLINK) || (ifa->state == OSPF_IS_DOWN))
1330
        continue;
1331
1332
      struct ifa *a;
1333
      WALK_LIST(a, ifa->iface->addrs)
1334
      {
1335
        if ((a->flags & IA_SECONDARY) || (a->scope <= SCOPE_LINK))
1336
          continue;
1337
1338
        /* Found some IP */
1339
        lsa_put_prefix(po, a->ip, MAX_PREFIX_LENGTH, 0);
1340 c3226991 Ondrej Zajicek
        i++;
1341 e4404cef Ondrej Zajicek
        goto done;
1342 c3226991 Ondrej Zajicek
      }
1343 e4404cef Ondrej Zajicek
    }
1344
  }
1345 c3226991 Ondrej Zajicek
1346 e4404cef Ondrej Zajicek
 done:
1347 c3226991 Ondrej Zajicek
  lp = po->lsab;
1348
  lp->pxcount = i;
1349
  *length = po->lsab_used + sizeof(struct ospf_lsa_header);
1350
  return lsab_flush(po);
1351
}
1352
1353
void
1354
originate_prefix_rt_lsa(struct ospf_area *oa)
1355
{
1356
  struct proto_ospf *po = oa->po;
1357 be862406 Ondrej Zajicek
  struct proto *p = &po->proto;  
1358
  struct ospf_lsa_header lsa;
1359 c3226991 Ondrej Zajicek
  void *body;
1360
1361 be862406 Ondrej Zajicek
  OSPF_TRACE(D_EVENTS, "Originating router prefix-LSA for area %R", oa->areaid);
1362
1363 c3226991 Ondrej Zajicek
  lsa.age = 0;
1364
  lsa.type = LSA_T_PREFIX;
1365 be862406 Ondrej Zajicek
  lsa.id = 0;
1366 8a70a13e Ondrej Zajicek
  lsa.rt = po->router_id;
1367 52572e94 Ondrej Zajicek
  lsa.sn = get_seqnum(oa->pxr_lsa);
1368 c3226991 Ondrej Zajicek
  u32 dom = oa->areaid;
1369
1370
  body = originate_prefix_rt_lsa_body(oa, &lsa.length);
1371
  lsasum_calculate(&lsa, body);
1372
  oa->pxr_lsa = lsa_install_new(po, &lsa, dom, body);
1373
  ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
1374
}
1375
1376
1377
static inline int
1378
prefix_space(u32 *buf)
1379
{
1380
  int pxl = *buf >> 24;
1381
  return IPV6_PREFIX_SPACE(pxl);
1382
}
1383
1384
static inline int
1385
prefix_same(u32 *b1, u32 *b2)
1386
{
1387
  int pxl1 = *b1 >> 24;
1388
  int pxl2 = *b2 >> 24;
1389
  int pxs, i;
1390
  
1391
  if (pxl1 != pxl2)
1392
    return 0;
1393
1394
  pxs = IPV6_PREFIX_WORDS(pxl1);
1395
  for (i = 1; i < pxs; i++)
1396
    if (b1[i] != b2[i])
1397
      return 0;
1398
1399
  return 1;
1400
}
1401
1402
static inline u32 *
1403
prefix_advance(u32 *buf)
1404
{
1405 be862406 Ondrej Zajicek
  int pxl = *buf >> 24;
1406
  return buf + IPV6_PREFIX_WORDS(pxl);
1407 c3226991 Ondrej Zajicek
}
1408
1409 2918e610 Ondrej Zajicek
/* FIXME eliminate items with LA bit set? see 4.4.3.9 */
1410 c3226991 Ondrej Zajicek
static void
1411 be862406 Ondrej Zajicek
add_prefix(struct proto_ospf *po, u32 *px, int offset, int *pxc)
1412 c3226991 Ondrej Zajicek
{
1413 be862406 Ondrej Zajicek
  u32 *pxl = lsab_offset(po, offset);
1414 c3226991 Ondrej Zajicek
  int i;
1415 e4404cef Ondrej Zajicek
  for (i = 0; i < *pxc; pxl = prefix_advance(pxl), i++)
1416
    if (prefix_same(px, pxl))
1417 c3226991 Ondrej Zajicek
    {
1418 e4404cef Ondrej Zajicek
      /* Options should be logically OR'ed together */
1419
      *pxl |= (*px & 0x00FF0000);
1420
      return;
1421 c3226991 Ondrej Zajicek
    }
1422
1423
  ASSERT(pxl == lsab_end(po));
1424
1425
  int pxspace = prefix_space(px);
1426
  pxl = lsab_alloc(po, pxspace);
1427
  memcpy(pxl, px, pxspace);
1428 e4404cef Ondrej Zajicek
  *pxl &= 0xFFFF0000;        /* Set metric to zero */
1429 c3226991 Ondrej Zajicek
  (*pxc)++;
1430
}
1431
1432 be862406 Ondrej Zajicek
static void
1433
add_link_lsa(struct proto_ospf *po, struct top_hash_entry *en, int offset, int *pxc)
1434
{
1435
  struct ospf_lsa_link *ll = en->lsa_body;
1436
  u32 *pxb = ll->rest;
1437
  int j;
1438
1439 e4404cef Ondrej Zajicek
  for (j = 0; j < ll->pxcount; pxb = prefix_advance(pxb), j++)
1440
  {
1441
    u8 pxlen = (pxb[0] >> 24);
1442
    u8 pxopts = (pxb[0] >> 16);
1443
1444
    /* Skip NU or LA prefixes */
1445
    if (pxopts & (OPT_PX_NU | OPT_PX_LA))
1446
      continue;
1447
1448
    /* Skip link-local prefixes */
1449
    if ((pxlen >= 10) && ((pxb[1] & 0xffc00000) == 0xfe800000))
1450
      continue;
1451
1452
    add_prefix(po, pxb, offset, pxc);
1453
  }
1454 be862406 Ondrej Zajicek
}
1455
1456
1457 c3226991 Ondrej Zajicek
1458
static void *
1459
originate_prefix_net_lsa_body(struct ospf_iface *ifa, u16 *length)
1460
{
1461
  struct proto_ospf *po = ifa->oa->po;
1462
  struct ospf_lsa_prefix *lp;
1463
  struct ospf_neighbor *n;
1464
  struct top_hash_entry *en;
1465 be862406 Ondrej Zajicek
  int pxc, offset;
1466 c3226991 Ondrej Zajicek
1467
  ASSERT(po->lsab_used == 0);
1468
  lp = lsab_allocz(po, sizeof(struct ospf_lsa_prefix));
1469
  lp->ref_type = LSA_T_NET;
1470
  lp->ref_id = ifa->net_lsa->lsa.id;
1471 8a70a13e Ondrej Zajicek
  lp->ref_rt = po->router_id;
1472 c3226991 Ondrej Zajicek
  lp = NULL; /* buffer might be reallocated later */
1473
1474 be862406 Ondrej Zajicek
  pxc = 0;
1475 c3226991 Ondrej Zajicek
  offset = po->lsab_used;
1476
1477 be862406 Ondrej Zajicek
  /* Find all Link LSAs associated with the link and merge their prefixes */
1478
  if (ifa->link_lsa)
1479
    add_link_lsa(po, ifa->link_lsa, offset, &pxc);
1480
1481 c3226991 Ondrej Zajicek
  WALK_LIST(n, ifa->neigh_list)
1482
    if ((n->state == NEIGHBOR_FULL) &&
1483 dd4da6f6 Ondrej Zajicek
              (en = ospf_hash_find(po->gr, ifa->iface_id, n->iface_id, n->rid, LSA_T_LINK)))
1484 be862406 Ondrej Zajicek
      add_link_lsa(po, en, offset, &pxc);
1485 c3226991 Ondrej Zajicek
1486
  lp = po->lsab;
1487 be862406 Ondrej Zajicek
  lp->pxcount = pxc;
1488 c3226991 Ondrej Zajicek
  *length = po->lsab_used + sizeof(struct ospf_lsa_header);
1489
  return lsab_flush(po);
1490
}
1491
1492
void
1493
originate_prefix_net_lsa(struct ospf_iface *ifa)
1494
{
1495
  struct proto_ospf *po = ifa->oa->po;
1496 be862406 Ondrej Zajicek
  struct proto *p = &po->proto;
1497
  struct ospf_lsa_header lsa;
1498 c3226991 Ondrej Zajicek
  void *body;
1499
1500 be862406 Ondrej Zajicek
  OSPF_TRACE(D_EVENTS, "Originating network prefix-LSA for iface %s",
1501
             ifa->iface->name);
1502
1503 c3226991 Ondrej Zajicek
  lsa.age = 0;
1504
  lsa.type = LSA_T_PREFIX;
1505 dd4da6f6 Ondrej Zajicek
  lsa.id = ifa->iface_id;
1506 8a70a13e Ondrej Zajicek
  lsa.rt = po->router_id;
1507 52572e94 Ondrej Zajicek
  lsa.sn = get_seqnum(ifa->pxn_lsa);
1508 c3226991 Ondrej Zajicek
  u32 dom = ifa->oa->areaid;
1509
1510
  body = originate_prefix_net_lsa_body(ifa, &lsa.length);
1511
  lsasum_calculate(&lsa, body);
1512
  ifa->pxn_lsa = lsa_install_new(po, &lsa, dom, body);
1513
  ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
1514
}
1515
1516 061ab802 Ondrej Zajicek
void
1517
flush_prefix_net_lsa(struct ospf_iface *ifa)
1518
{
1519
  struct proto_ospf *po = ifa->oa->po;
1520
  struct proto *p = &po->proto;
1521
  struct top_hash_entry *en = ifa->pxn_lsa;
1522
  u32 dom = ifa->oa->areaid;
1523
1524
  if (en == NULL)
1525
    return;
1526
1527 be862406 Ondrej Zajicek
  OSPF_TRACE(D_EVENTS, "Flushing network prefix-LSA for iface %s",
1528 061ab802 Ondrej Zajicek
             ifa->iface->name);
1529 be862406 Ondrej Zajicek
1530 061ab802 Ondrej Zajicek
  en->lsa.sn += 1;
1531
  en->lsa.age = LSA_MAXAGE;
1532
  lsasum_calculate(&en->lsa, en->lsa_body);
1533
  ospf_lsupd_flood(po, NULL, NULL, &en->lsa, dom, 0);
1534
  flush_lsa(en, po);
1535
  ifa->pxn_lsa = NULL;
1536
}
1537
1538
1539 c3226991 Ondrej Zajicek
#endif
1540 e8085aba Ondrej Filip
1541 b49e6f5a Ondrej Zajicek
1542 6ba36f06 Martin Mares
static void
1543
ospf_top_ht_alloc(struct top_graph *f)
1544
{
1545
  f->hash_size = 1 << f->hash_order;
1546
  f->hash_mask = f->hash_size - 1;
1547
  if (f->hash_order > HASH_HI_MAX - HASH_HI_STEP)
1548
    f->hash_entries_max = ~0;
1549
  else
1550
    f->hash_entries_max = f->hash_size HASH_HI_MARK;
1551
  if (f->hash_order < HASH_LO_MIN + HASH_LO_STEP)
1552
    f->hash_entries_min = 0;
1553
  else
1554
    f->hash_entries_min = f->hash_size HASH_LO_MARK;
1555
  DBG("Allocating OSPF hash of order %d: %d hash_entries, %d low, %d high\n",
1556
      f->hash_order, f->hash_size, f->hash_entries_min, f->hash_entries_max);
1557 b9ed99f7 Ondrej Filip
  f->hash_table =
1558
    mb_alloc(f->pool, f->hash_size * sizeof(struct top_hash_entry *));
1559 6ba36f06 Martin Mares
  bzero(f->hash_table, f->hash_size * sizeof(struct top_hash_entry *));
1560
}
1561
1562
static inline void
1563
ospf_top_ht_free(struct top_hash_entry **h)
1564
{
1565
  mb_free(h);
1566
}
1567
1568
static inline u32
1569
ospf_top_hash_u32(u32 a)
1570
{
1571
  /* Shamelessly stolen from IP address hashing in ipv4.h */
1572
  a ^= a >> 16;
1573
  a ^= a << 10;
1574
  return a;
1575
}
1576
1577
static inline unsigned
1578 c3226991 Ondrej Zajicek
ospf_top_hash(struct top_graph *f, u32 domain, u32 lsaid, u32 rtrid, u32 type)
1579
{
1580 be862406 Ondrej Zajicek
  /* In OSPFv2, we don't know Router ID when looking for network LSAs.
1581 9f0ba7b1 Ondrej Zajicek
     In OSPFv3, we don't know LSA ID when looking for router LSAs.
1582
     In both cases, there is (usually) just one (or small number)
1583
     appropriate LSA, so we just clear unknown part of key. */
1584 c3226991 Ondrej Zajicek
1585 9f0ba7b1 Ondrej Zajicek
  return (
1586 c3226991 Ondrej Zajicek
#ifdef OSPFv2
1587
          ((type == LSA_T_NET) ? 0 : ospf_top_hash_u32(rtrid)) +
1588 9f0ba7b1 Ondrej Zajicek
          ospf_top_hash_u32(lsaid) + 
1589 c3226991 Ondrej Zajicek
#else /* OSPFv3 */
1590
          ospf_top_hash_u32(rtrid) +
1591 9f0ba7b1 Ondrej Zajicek
          ((type == LSA_T_RT) ? 0 : ospf_top_hash_u32(lsaid)) +
1592 c3226991 Ondrej Zajicek
#endif
1593 9f0ba7b1 Ondrej Zajicek
          type + domain) & f->hash_mask;
1594 c3226991 Ondrej Zajicek
1595
  /*
1596 b9ed99f7 Ondrej Filip
  return (ospf_top_hash_u32(lsaid) + ospf_top_hash_u32(rtrid) +
1597 86c84d76 Ondrej Filip
          type + areaid) & f->hash_mask;
1598 c3226991 Ondrej Zajicek
  */
1599 6ba36f06 Martin Mares
}
1600
1601 7ab3ff6a Ondrej Filip
/**
1602
 * ospf_top_new - allocated new topology database
1603 c3226991 Ondrej Zajicek
 * @p: current instance of ospf
1604 7ab3ff6a Ondrej Filip
 *
1605 c3226991 Ondrej Zajicek
 * this dynamically hashed structure is often used for keeping lsas. mainly
1606 baa5dd6c Ondrej Filip
 * its used in @ospf_area structure.
1607 7ab3ff6a Ondrej Filip
 */
1608 6ba36f06 Martin Mares
struct top_graph *
1609 d5d9693c Ondrej Filip
ospf_top_new(pool *pool)
1610 6ba36f06 Martin Mares
{
1611
  struct top_graph *f;
1612
1613 035f6acb Ondrej Filip
  f = mb_allocz(pool, sizeof(struct top_graph));
1614
  f->pool = pool;
1615 6ba36f06 Martin Mares
  f->hash_slab = sl_new(f->pool, sizeof(struct top_hash_entry));
1616
  f->hash_order = HASH_DEF_ORDER;
1617
  ospf_top_ht_alloc(f);
1618
  f->hash_entries = 0;
1619
  f->hash_entries_min = 0;
1620
  return f;
1621
}
1622
1623
void
1624
ospf_top_free(struct top_graph *f)
1625
{
1626
  rfree(f->hash_slab);
1627
  ospf_top_ht_free(f->hash_table);
1628
  mb_free(f);
1629
}
1630
1631
static void
1632
ospf_top_rehash(struct top_graph *f, int step)
1633
{
1634
  unsigned int oldn, oldh;
1635
  struct top_hash_entry **n, **oldt, **newt, *e, *x;
1636
1637
  oldn = f->hash_size;
1638
  oldt = f->hash_table;
1639 b49e6f5a Ondrej Zajicek
  DBG("re-hashing topology hash from order %d to %d\n", f->hash_order,
1640 b9ed99f7 Ondrej Filip
      f->hash_order + step);
1641 6ba36f06 Martin Mares
  f->hash_order += step;
1642
  ospf_top_ht_alloc(f);
1643
  newt = f->hash_table;
1644
1645 b9ed99f7 Ondrej Filip
  for (oldh = 0; oldh < oldn; oldh++)
1646
  {
1647
    e = oldt[oldh];
1648
    while (e)
1649 6ba36f06 Martin Mares
    {
1650 b9ed99f7 Ondrej Filip
      x = e->next;
1651 c3226991 Ondrej Zajicek
      n = newt + ospf_top_hash(f, e->domain, e->lsa.id, e->lsa.rt, e->lsa.type);
1652 b9ed99f7 Ondrej Filip
      e->next = *n;
1653
      *n = e;
1654
      e = x;
1655 6ba36f06 Martin Mares
    }
1656 b9ed99f7 Ondrej Filip
  }
1657 6ba36f06 Martin Mares
  ospf_top_ht_free(oldt);
1658
}
1659
1660 f9c799a0 Ondrej Zajicek
#ifdef OSPFv2
1661
1662
u32
1663
ospf_lsa_domain(u32 type, struct ospf_iface *ifa)
1664
{
1665
  return (type == LSA_T_EXT) ? 0 : ifa->oa->areaid;
1666
}
1667
1668
#else /* OSPFv3 */
1669
1670 b49e6f5a Ondrej Zajicek
u32
1671
ospf_lsa_domain(u32 type, struct ospf_iface *ifa)
1672
{
1673
  switch (type & LSA_SCOPE_MASK)
1674
    {
1675
    case LSA_SCOPE_LINK:
1676 dd4da6f6 Ondrej Zajicek
      return ifa->iface_id;
1677 b49e6f5a Ondrej Zajicek
1678
    case LSA_SCOPE_AREA:
1679
      return ifa->oa->areaid;
1680
1681
    case LSA_SCOPE_AS:
1682
    default:
1683
      return 0;
1684
    }
1685
}
1686
1687 f9c799a0 Ondrej Zajicek
#endif
1688
1689 6ba36f06 Martin Mares
struct top_hash_entry *
1690 b49e6f5a Ondrej Zajicek
ospf_hash_find_header(struct top_graph *f, u32 domain, struct ospf_lsa_header *h)
1691 921a93f2 Ondrej Filip
{
1692 b49e6f5a Ondrej Zajicek
  return ospf_hash_find(f, domain, h->id, h->rt, h->type);
1693 921a93f2 Ondrej Filip
}
1694 d8852b36 Ondrej Filip
1695
struct top_hash_entry *
1696 b49e6f5a Ondrej Zajicek
ospf_hash_get_header(struct top_graph *f, u32 domain, struct ospf_lsa_header *h)
1697 d8852b36 Ondrej Filip
{
1698 b49e6f5a Ondrej Zajicek
  return ospf_hash_get(f, domain, h->id, h->rt, h->type);
1699 d8852b36 Ondrej Filip
}
1700
1701 921a93f2 Ondrej Filip
struct top_hash_entry *
1702 b49e6f5a Ondrej Zajicek
ospf_hash_find(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
1703 6ba36f06 Martin Mares
{
1704 86c84d76 Ondrej Filip
  struct top_hash_entry *e;
1705 c3226991 Ondrej Zajicek
  e = f->hash_table[ospf_top_hash(f, domain, lsa, rtr, type)];
1706 86c84d76 Ondrej Filip
1707 9f0ba7b1 Ondrej Zajicek
  while (e && (e->lsa.id != lsa || e->lsa.type != type || e->lsa.rt != rtr || e->domain != domain))
1708
    e = e->next;
1709
1710
  return e;
1711
}
1712
1713
1714 c3226991 Ondrej Zajicek
#ifdef OSPFv2
1715
1716 9f0ba7b1 Ondrej Zajicek
/* In OSPFv2, sometimes we don't know Router ID when looking for network LSAs.
1717
   There should be just one, so we find any match. */
1718
struct top_hash_entry *
1719
ospf_hash_find_net(struct top_graph *f, u32 domain, u32 lsa)
1720
{
1721
  struct top_hash_entry *e;
1722
  e = f->hash_table[ospf_top_hash(f, domain, lsa, 0, LSA_T_NET)];
1723
1724
  while (e && (e->lsa.id != lsa || e->lsa.type != LSA_T_NET || e->domain != domain))
1725
    e = e->next;
1726
1727
  return e;
1728
}
1729 86c84d76 Ondrej Filip
1730 c3226991 Ondrej Zajicek
#endif
1731
1732
1733 9f0ba7b1 Ondrej Zajicek
#ifdef OSPFv3
1734
1735
/* In OSPFv3, usually we don't know LSA ID when looking for router
1736
   LSAs. We return matching LSA with smallest LSA ID. */
1737
struct top_hash_entry *
1738
ospf_hash_find_rt(struct top_graph *f, u32 domain, u32 rtr)
1739
{
1740
  struct top_hash_entry *rv = NULL;
1741
  struct top_hash_entry *e;
1742
  e = f->hash_table[ospf_top_hash(f, domain, 0, rtr, LSA_T_RT)];
1743
  
1744
  while (e)
1745
    {
1746
      if (e->lsa.rt == rtr && e->lsa.type == LSA_T_RT && e->domain == domain)
1747
        if (!rv || e->lsa.id < rv->lsa.id)
1748
          rv = e;
1749
      e = e->next;
1750
    }
1751
1752
  return rv;
1753
}
1754
1755
static inline struct top_hash_entry *
1756
find_matching_rt(struct top_hash_entry *e, u32 domain, u32 rtr)
1757
{
1758
  while (e && (e->lsa.rt != rtr || e->lsa.type != LSA_T_RT || e->domain != domain))
1759
    e = e->next;
1760 6ba36f06 Martin Mares
  return e;
1761
}
1762
1763
struct top_hash_entry *
1764 9f0ba7b1 Ondrej Zajicek
ospf_hash_find_rt_first(struct top_graph *f, u32 domain, u32 rtr)
1765
{
1766
  struct top_hash_entry *e;
1767
  e = f->hash_table[ospf_top_hash(f, domain, 0, rtr, LSA_T_RT)];
1768
  return find_matching_rt(e, domain, rtr);
1769
}
1770
1771
struct top_hash_entry *
1772
ospf_hash_find_rt_next(struct top_hash_entry *e)
1773
{
1774
  return find_matching_rt(e->next, e->domain, e->lsa.rt);
1775
}
1776
1777
#endif
1778
1779
1780
struct top_hash_entry *
1781 b49e6f5a Ondrej Zajicek
ospf_hash_get(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
1782 6ba36f06 Martin Mares
{
1783 86c84d76 Ondrej Filip
  struct top_hash_entry **ee;
1784
  struct top_hash_entry *e;
1785
1786 c3226991 Ondrej Zajicek
  ee = f->hash_table + ospf_top_hash(f, domain, lsa, rtr, type);
1787 86c84d76 Ondrej Filip
  e = *ee;
1788
1789 c3226991 Ondrej Zajicek
  while (e && (e->lsa.id != lsa || e->lsa.rt != rtr || e->lsa.type != type || e->domain != domain))
1790
    e = e->next;
1791 6ba36f06 Martin Mares
1792
  if (e)
1793
    return e;
1794 933bfdde Ondrej Filip
1795 6ba36f06 Martin Mares
  e = sl_alloc(f->hash_slab);
1796 933bfdde Ondrej Filip
  e->color = OUTSPF;
1797
  e->dist = LSINFINITY;
1798 57c574d8 Ondrej Zajicek
  e->nhs = NULL;
1799 3b16080c Ondrej Filip
  e->lb = IPA_NONE;
1800 ce17d4c1 Ondrej Filip
  e->lsa.id = lsa;
1801
  e->lsa.rt = rtr;
1802
  e->lsa.type = type;
1803
  e->lsa_body = NULL;
1804 c3226991 Ondrej Zajicek
  e->domain = domain;
1805 933bfdde Ondrej Filip
  e->next = *ee;
1806 b9ed99f7 Ondrej Filip
  *ee = e;
1807 6ba36f06 Martin Mares
  if (f->hash_entries++ > f->hash_entries_max)
1808
    ospf_top_rehash(f, HASH_HI_STEP);
1809
  return e;
1810
}
1811
1812
void
1813
ospf_hash_delete(struct top_graph *f, struct top_hash_entry *e)
1814
{
1815 86c84d76 Ondrej Filip
  struct top_hash_entry **ee = f->hash_table + 
1816 c3226991 Ondrej Zajicek
    ospf_top_hash(f, e->domain, e->lsa.id, e->lsa.rt, e->lsa.type);
1817 6ba36f06 Martin Mares
1818
  while (*ee)
1819 b9ed99f7 Ondrej Filip
  {
1820
    if (*ee == e)
1821 6ba36f06 Martin Mares
    {
1822 b9ed99f7 Ondrej Filip
      *ee = e->next;
1823
      sl_free(f->hash_slab, e);
1824
      if (f->hash_entries-- < f->hash_entries_min)
1825
        ospf_top_rehash(f, -HASH_LO_STEP);
1826
      return;
1827 6ba36f06 Martin Mares
    }
1828 b9ed99f7 Ondrej Filip
    ee = &((*ee)->next);
1829
  }
1830 6ba36f06 Martin Mares
  bug("ospf_hash_delete() called for invalid node");
1831
}
1832
1833 e81b440f Ondrej Zajicek
/*
1834 226cb2bc Ondrej Filip
static void
1835
ospf_dump_lsa(struct top_hash_entry *he, struct proto *p)
1836
{
1837 e81b440f Ondrej Zajicek

1838 226cb2bc Ondrej Filip
  struct ospf_lsa_rt *rt = NULL;
1839
  struct ospf_lsa_rt_link *rr = NULL;
1840
  struct ospf_lsa_net *ln = NULL;
1841
  u32 *rts = NULL;
1842
  u32 i, max;
1843

1844 3aab39f5 Ondrej Zajicek
  OSPF_TRACE(D_EVENTS, "- %1x %-1R %-1R %4u 0x%08x 0x%04x %-1R",
1845
             he->lsa.type, he->lsa.id, he->lsa.rt, he->lsa.age, he->lsa.sn,
1846 c3226991 Ondrej Zajicek
             he->lsa.checksum, he->domain);
1847 226cb2bc Ondrej Filip

1848 b49e6f5a Ondrej Zajicek

1849 226cb2bc Ondrej Filip
  switch (he->lsa.type)
1850
    {
1851
    case LSA_T_RT:
1852
      rt = he->lsa_body;
1853
      rr = (struct ospf_lsa_rt_link *) (rt + 1);
1854

1855 c3226991 Ondrej Zajicek
      for (i = 0; i < lsa_rt_items(&he->lsa); i++)
1856 3aab39f5 Ondrej Zajicek
        OSPF_TRACE(D_EVENTS, "  - %1x %-1R %-1R %5u",
1857
                   rr[i].type, rr[i].id, rr[i].data, rr[i].metric);
1858 226cb2bc Ondrej Filip
      break;
1859

1860
    case LSA_T_NET:
1861
      ln = he->lsa_body;
1862
      rts = (u32 *) (ln + 1);
1863

1864 c3226991 Ondrej Zajicek
      for (i = 0; i < lsa_net_items(&he->lsa); i++)
1865 3aab39f5 Ondrej Zajicek
        OSPF_TRACE(D_EVENTS, "  - %-1R", rts[i]);
1866 226cb2bc Ondrej Filip
      break;
1867

1868
    default:
1869
      break;
1870
    }
1871
}
1872

1873 6ba36f06 Martin Mares
void
1874 992705f6 Ondrej Filip
ospf_top_dump(struct top_graph *f, struct proto *p)
1875 6ba36f06 Martin Mares
{
1876 89ba9a18 Ondrej Filip
  unsigned int i;
1877 992705f6 Ondrej Filip
  OSPF_TRACE(D_EVENTS, "Hash entries: %d", f->hash_entries);
1878 6ba36f06 Martin Mares

1879 b9ed99f7 Ondrej Filip
  for (i = 0; i < f->hash_size; i++)
1880
  {
1881 226cb2bc Ondrej Filip
    struct top_hash_entry *e;
1882
    for (e = f->hash_table[i]; e != NULL; e = e->next)
1883
      ospf_dump_lsa(e, p);
1884 b9ed99f7 Ondrej Filip
  }
1885 6ba36f06 Martin Mares
}
1886 e81b440f Ondrej Zajicek
*/
1887 de30342f Ondrej Filip
1888 baa5dd6c Ondrej Filip
/* This is very inefficient, please don't call it often */
1889 ad5453b5 Ondrej Filip
1890
/* I should also test for every LSA if it's in some link state
1891 baa5dd6c Ondrej Filip
 * retransmission list for every neighbor. I will not test it.
1892
 * It could happen that I'll receive some strange ls ack's.
1893 ad5453b5 Ondrej Filip
 */
1894
1895
int
1896 86c84d76 Ondrej Filip
can_flush_lsa(struct proto_ospf *po)
1897 ad5453b5 Ondrej Filip
{
1898
  struct ospf_iface *ifa;
1899
  struct ospf_neighbor *n;
1900
1901 86c84d76 Ondrej Filip
  WALK_LIST(ifa, po->iface_list)
1902 ad5453b5 Ondrej Filip
  {
1903 86c84d76 Ondrej Filip
    WALK_LIST(n, ifa->neigh_list)
1904 ad5453b5 Ondrej Filip
    {
1905 86c84d76 Ondrej Filip
      if ((n->state == NEIGHBOR_EXCHANGE) || (n->state == NEIGHBOR_LOADING))
1906
        return 0;
1907
1908 b9ed99f7 Ondrej Filip
      break;
1909 ad5453b5 Ondrej Filip
    }
1910
  }
1911
1912 9e48d717 Ondrej Filip
  return 1;
1913 ad5453b5 Ondrej Filip
}