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