]> git.ipfire.org Git - thirdparty/bird.git/blame - proto/ospf/topology.c
OSPF: Minor fix in graceful restart
[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>
70945cb6
OZ
6 * (c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org>
7 * (c) 2009--2014 CZ.NIC z.s.p.o.
6ba36f06
MM
8 *
9 * Can be freely distributed and used under the terms of the GNU GPL.
10 */
11
6ba36f06 12#include "nest/bird.h"
221135d6 13#include "lib/string.h"
6ba36f06
MM
14
15#include "ospf.h"
16
70945cb6 17
8d56febe 18#define HASH_DEF_ORDER 6
6ba36f06
MM
19#define HASH_HI_MARK *4
20#define HASH_HI_STEP 2
21#define HASH_HI_MAX 16
22#define HASH_LO_MARK /5
23#define HASH_LO_STEP 2
24#define HASH_LO_MIN 8
25
70945cb6
OZ
26static inline void * lsab_flush(struct ospf_proto *p);
27static inline void lsab_reset(struct ospf_proto *p);
b49e6f5a 28
b49e6f5a 29
70945cb6
OZ
30/**
31 * ospf_install_lsa - install new LSA into database
32 * @p: OSPF protocol instance
33 * @lsa: LSA header
742029eb 34 * @type: type of LSA
70945cb6
OZ
35 * @domain: domain of LSA
36 * @body: pointer to LSA body
37 *
38 * This function ensures installing new LSA received in LS update into LSA
39 * database. Old instance is replaced. Several actions are taken to detect if
40 * new routing table calculation is necessary. This is described in 13.2 of RFC
41 * 2328. This function is for received LSA only, locally originated LSAs are
42 * installed by ospf_originate_lsa().
a7a7372a
OZ
43 *
44 * The LSA body in @body is expected to be mb_allocated by the caller and its
45 * ownership is transferred to the LSA entry structure.
70945cb6
OZ
46 */
47struct top_hash_entry *
48ospf_install_lsa(struct ospf_proto *p, struct ospf_lsa_header *lsa, u32 type, u32 domain, void *body)
49{
70945cb6
OZ
50 struct top_hash_entry *en;
51 int change = 0;
d82fc18d 52
70945cb6 53 en = ospf_hash_get(p->gr, domain, lsa->id, lsa->rt, type);
d82fc18d 54
70945cb6
OZ
55 if (!SNODE_VALID(en))
56 s_add_tail(&p->lsal, SNODE en);
57
58 if ((en->lsa_body == NULL) || /* No old LSA */
59 (en->lsa.length != lsa->length) ||
60 (en->lsa.type_raw != lsa->type_raw) || /* Check for OSPFv2 options */
61 (en->lsa.age == LSA_MAXAGE) ||
62 (lsa->age == LSA_MAXAGE) ||
63 memcmp(en->lsa_body, body, lsa->length - sizeof(struct ospf_lsa_header)))
64 change = 1;
65
a7a7372a
OZ
66 if ((en->lsa.age == LSA_MAXAGE) && (lsa->age == LSA_MAXAGE))
67 change = 0;
70945cb6
OZ
68
69 mb_free(en->lsa_body);
70 en->lsa_body = body;
71 en->lsa = *lsa;
72 en->init_age = en->lsa.age;
b32d557a 73 en->inst_time = current_time();
85840d4c 74 en->gr_dirty = p->gr_recovery && (lsa->rt == p->router_id);
70945cb6 75
a7a7372a
OZ
76 /*
77 * We do not set en->mode. It is either default LSA_M_BASIC, or in a special
78 * case when en is local but flushed, there is postponed LSA, self-originated
79 * LSA is received and ospf_install_lsa() is called from ospf_advance_lse(),
80 * then we have en->mode from the postponed LSA origination.
81 */
82
83 OSPF_TRACE(D_EVENTS, "Installing LSA: Type: %04x, Id: %R, Rt: %R, Seq: %08x, Age: %u",
84 en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn, en->lsa.age);
85
70945cb6 86 if (change)
1a2ad348
OZ
87 {
88 ospf_neigh_lsadb_changed(p, en);
a7a7372a 89 ospf_schedule_rtcalc(p);
1a2ad348 90 }
70945cb6
OZ
91
92 return en;
93}
94
a7a7372a
OZ
95/**
96 * ospf_advance_lsa - handle received unexpected self-originated LSA
97 * @p: OSPF protocol instance
98 * @en: current LSA entry or NULL
99 * @lsa: new LSA header
742029eb 100 * @type: type of LSA
a7a7372a
OZ
101 * @domain: domain of LSA
102 * @body: pointer to LSA body
103 *
104 * This function handles received unexpected self-originated LSA (@lsa, @body)
105 * by either advancing sequence number of the local LSA instance (@en) and
106 * propagating it, or installing the received LSA and immediately flushing it
107 * (if there is no local LSA; i.e., @en is NULL or MaxAge).
108 *
109 * The LSA body in @body is expected to be mb_allocated by the caller and its
110 * ownership is transferred to the LSA entry structure or it is freed.
111 */
70945cb6
OZ
112void
113ospf_advance_lsa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_lsa_header *lsa, u32 type, u32 domain, void *body)
114{
a7a7372a 115 /* RFC 2328 13.4 */
70945cb6
OZ
116
117 if (en && (en->lsa.age < LSA_MAXAGE))
118 {
119 if (lsa->sn != LSA_MAXSEQNO)
120 {
121 /*
122 * We simply advance current LSA to have higher seqnum than received LSA.
123 * The received LSA is ignored and the advanced LSA is propagated instead.
124 *
125 * Although this is an origination of distinct LSA instance and therefore
126 * should be limited by MinLSInterval, we do not enforce it here. Fast
127 * reaction is needed and we are already limited by MinLSArrival.
128 */
129
130 mb_free(body);
131
132 en->lsa.sn = lsa->sn + 1;
133 en->lsa.age = 0;
134 en->init_age = 0;
b32d557a 135 en->inst_time = current_time();
77edab64 136 lsa_generate_checksum(&en->lsa, en->lsa_body);
a7a7372a
OZ
137
138 OSPF_TRACE(D_EVENTS, "Advancing LSA: Type: %04x, Id: %R, Rt: %R, Seq: %08x",
139 en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn);
70945cb6
OZ
140 }
141 else
142 {
742029eb 143 /*
70945cb6
OZ
144 * Received LSA has maximal sequence number, so we cannot simply override
145 * it. We have to install it to the database, immediately flush it to
146 * implement sequence number wrapping, and schedule our current LSA to be
147 * originated after the received instance is flushed.
148 */
149
150 if (en->next_lsa_body == NULL)
151 {
152 /* Schedule current LSA */
153 en->next_lsa_blen = en->lsa.length - sizeof(struct ospf_lsa_header);
154 en->next_lsa_body = en->lsa_body;
155 en->next_lsa_opts = ospf_is_v2(p) ? lsa_get_options(&en->lsa) : 0;
156 }
157 else
158 {
159 /* There is already scheduled LSA, so we just free current one */
160 mb_free(en->lsa_body);
161 }
162
163 en->lsa_body = body;
164 en->lsa = *lsa;
165 en->lsa.age = LSA_MAXAGE;
166 en->init_age = lsa->age;
b32d557a 167 en->inst_time = current_time();
a7a7372a
OZ
168
169 OSPF_TRACE(D_EVENTS, "Resetting LSA: Type: %04x, Id: %R, Rt: %R, Seq: %08x",
170 en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn);
171 OSPF_TRACE(D_EVENTS, "Postponing LSA: Type: %04x, Id: %R, Rt: %R",
172 en->lsa_type, en->lsa.id, en->lsa.rt);
70945cb6
OZ
173 }
174 }
d82fc18d 175 else
70945cb6
OZ
176 {
177 /*
178 * We do not have received LSA in the database. We have to flush the
179 * received LSA. It has to be installed in the database to secure
180 * retransmissions. Note that the received LSA may already be MaxAge.
a7a7372a 181 * Also note that en->next_lsa_* may be defined.
70945cb6
OZ
182 */
183
184 lsa->age = LSA_MAXAGE;
185 en = ospf_install_lsa(p, lsa, type, domain, body);
186 }
187
742029eb 188 /*
70945cb6
OZ
189 * We flood the updated LSA. Although in some cases the to-be-flooded LSA is
190 * the same as the received LSA, and therefore we should propagate it as
742029eb 191 * regular received LSA (send the acknowledgement instead of the update to
70945cb6
OZ
192 * the neighbor we received it from), we cheat a bit here.
193 */
194
a7a7372a 195 ospf_flood_lsa(p, en, NULL);
d82fc18d
OZ
196}
197
d82fc18d 198
70945cb6
OZ
199static int
200ospf_do_originate_lsa(struct ospf_proto *p, struct top_hash_entry *en, void *lsa_body, u16 lsa_blen, u16 lsa_opts)
d82fc18d 201{
70945cb6 202 /* Enforce MinLSInterval */
b32d557a 203 if (!en->init_age && en->inst_time && (lsa_inst_age(en) < MINLSINTERVAL))
70945cb6
OZ
204 return 0;
205
206 /* Handle wrapping sequence number */
207 if (en->lsa.sn == LSA_MAXSEQNO)
208 {
209 /* Prepare to flush old LSA */
210 if (en->lsa.age != LSA_MAXAGE)
211 {
a7a7372a
OZ
212 OSPF_TRACE(D_EVENTS, "Resetting LSA: Type: %04x, Id: %R, Rt: %R, Seq: %08x",
213 en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn);
70945cb6
OZ
214
215 en->lsa.age = LSA_MAXAGE;
a7a7372a 216 ospf_flood_lsa(p, en, NULL);
70945cb6
OZ
217 return 0;
218 }
219
220 /* Already flushing */
221 if ((p->padj != 0) || (en->ret_count != 0))
222 return 0;
223
224 /* Flush done, just clean up seqnum, lsa_body is freed below */
225 en->lsa.sn = LSA_ZEROSEQNO;
226 }
227
6384c7d7 228 /*
70945cb6
OZ
229 * lsa.type_raw is initialized by ospf_hash_get() to OSPFv3 LSA type.
230 * lsa_set_options() implicitly converts it to OSPFv2 LSA type, assuming that
5a50a989
OZ
231 * old type is just new type masked by 0xff. That holds for most OSPFv2 types,
232 * but we have to fix it for opaque LSAs.
6384c7d7 233 */
70945cb6
OZ
234
235 if (ospf_is_v2(p))
5a50a989
OZ
236 {
237 if (lsa_is_opaque(en->lsa_type))
238 en->lsa.type_raw = LSA_T_V2_OPAQUE_ + LSA_SCOPE_ORDER(en->lsa_type);
239
70945cb6 240 lsa_set_options(&en->lsa, lsa_opts);
5a50a989 241 }
70945cb6
OZ
242
243 mb_free(en->lsa_body);
244 en->lsa_body = lsa_body;
245 en->lsa.length = sizeof(struct ospf_lsa_header) + lsa_blen;
246 en->lsa.sn++;
247 en->lsa.age = 0;
248 en->init_age = 0;
b32d557a 249 en->inst_time = current_time();
85840d4c 250 en->gr_dirty = 0;
77edab64 251 lsa_generate_checksum(&en->lsa, en->lsa_body);
70945cb6 252
a7a7372a
OZ
253 OSPF_TRACE(D_EVENTS, "Originating LSA: Type: %04x, Id: %R, Rt: %R, Seq: %08x",
254 en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn);
255
256 ospf_flood_lsa(p, en, NULL);
257
258 if (en->mode == LSA_M_BASIC)
1a2ad348
OZ
259 {
260 ospf_neigh_lsadb_changed(p, en);
a7a7372a 261 ospf_schedule_rtcalc(p);
1a2ad348 262 }
70945cb6
OZ
263
264 return 1;
d82fc18d
OZ
265}
266
70945cb6
OZ
267/**
268 * ospf_originate_lsa - originate new LSA
269 * @p: OSPF protocol instance
270 * @lsa: New LSA specification
271 *
272 * This function prepares a new LSA, installs it into the LSA database and
273 * floods it. If the new LSA cannot be originated now (because the old instance
274 * was originated within MinLSInterval, or because the LSA seqnum is currently
275 * wrapping), the origination is instead scheduled for later. If the new LSA is
276 * equivalent to the current LSA, the origination is skipped. In all cases, the
277 * corresponding LSA entry is returned. The new LSA is based on the LSA
278 * specification (@lsa) and the LSA body from lsab buffer of @p, which is
279 * emptied after the call. The opposite of this function is ospf_flush_lsa().
280 */
281struct top_hash_entry *
282ospf_originate_lsa(struct ospf_proto *p, struct ospf_new_lsa *lsa)
283{
deb84d79 284 struct top_hash_entry *en = NULL;
70945cb6
OZ
285 void *lsa_body = p->lsab;
286 u16 lsa_blen = p->lsab_used;
287 u16 lsa_length = sizeof(struct ospf_lsa_header) + lsa_blen;
b49e6f5a 288
deb84d79
OZ
289 /* RFC 3623 2 (1) - do not originate topology LSAs during graceful restart */
290 if (p->gr_recovery && (LSA_FUNCTION(lsa->type) <= LSA_FUNCTION(LSA_T_NSSA)))
291 goto drop;
292
5a50a989
OZ
293 /* For OSPFv2 Opaque LSAs, LS ID consists of Opaque Type and Opaque ID */
294 if (ospf_is_v2(p) && lsa_is_opaque(lsa->type))
295 lsa->id |= (u32) lsa_get_opaque_type(lsa->type) << 24;
296
70945cb6 297 en = ospf_hash_get(p->gr, lsa->dom, lsa->id, p->router_id, lsa->type);
b49e6f5a 298
70945cb6
OZ
299 if (!SNODE_VALID(en))
300 s_add_tail(&p->lsal, SNODE en);
301
39a6b19d 302 if (!en->nf || !en->lsa_body)
70945cb6
OZ
303 en->nf = lsa->nf;
304
305 if (en->nf != lsa->nf)
306 {
fe9f1a6d
OZ
307 log(L_ERR "%s: LSA ID collision for %N",
308 p->p.name, lsa->nf->fn.addr);
a7a7372a
OZ
309
310 en = NULL;
70945cb6
OZ
311 goto drop;
312 }
313
a7a7372a
OZ
314 if (en->mode != lsa->mode)
315 en->mode = lsa->mode;
70945cb6
OZ
316
317 if (en->next_lsa_body)
318 {
319 /* Ignore the new LSA if it is the same as the scheduled one */
a7a7372a
OZ
320 if ((lsa_blen == en->next_lsa_blen) &&
321 !memcmp(lsa_body, en->next_lsa_body, lsa_blen) &&
322 (!ospf_is_v2(p) || (lsa->opts == en->next_lsa_opts)))
70945cb6
OZ
323 goto drop;
324
325 /* Free scheduled LSA */
326 mb_free(en->next_lsa_body);
327 en->next_lsa_body = NULL;
328 en->next_lsa_blen = 0;
329 en->next_lsa_opts = 0;
330 }
331
332 /* Ignore the the new LSA if is the same as the current one */
a7a7372a
OZ
333 if ((en->lsa.age < LSA_MAXAGE) &&
334 (lsa_length == en->lsa.length) &&
335 !memcmp(lsa_body, en->lsa_body, lsa_blen) &&
1a2ad348 336 (!ospf_is_v2(p) || (lsa->opts == lsa_get_options(&en->lsa))) &&
85840d4c 337 !en->gr_dirty)
70945cb6
OZ
338 goto drop;
339
340 lsa_body = lsab_flush(p);
341
342 if (! ospf_do_originate_lsa(p, en, lsa_body, lsa_blen, lsa->opts))
343 {
a7a7372a
OZ
344 OSPF_TRACE(D_EVENTS, "Postponing LSA: Type: %04x, Id: %R, Rt: %R",
345 en->lsa_type, en->lsa.id, en->lsa.rt);
346
70945cb6
OZ
347 en->next_lsa_body = lsa_body;
348 en->next_lsa_blen = lsa_blen;
349 en->next_lsa_opts = lsa->opts;
350 }
351
352 return en;
353
354 drop:
355 lsab_reset(p);
356 return en;
357}
358
359static void
360ospf_originate_next_lsa(struct ospf_proto *p, struct top_hash_entry *en)
3d15dcdb 361{
70945cb6
OZ
362 /* Called by ospf_update_lsadb() to handle scheduled origination */
363
364 if (! ospf_do_originate_lsa(p, en, en->next_lsa_body, en->next_lsa_blen, en->next_lsa_opts))
365 return;
742029eb 366
70945cb6
OZ
367 en->next_lsa_body = NULL;
368 en->next_lsa_blen = 0;
369 en->next_lsa_opts = 0;
70945cb6
OZ
370}
371
372static void
373ospf_refresh_lsa(struct ospf_proto *p, struct top_hash_entry *en)
374{
375 /*
376 * Called by ospf_update_lsadb() for periodic LSA refresh.
377 *
378 * We know that lsa.age < LSA_MAXAGE and lsa.rt is our router ID. We can also
379 * assume that there is no scheduled LSA, because inst_time is deep in past,
380 * therefore ospf_originate_next_lsa() called before would either succeed or
381 * switched lsa.age to LSA_MAXAGE.
382 */
383
a7a7372a
OZ
384 OSPF_TRACE(D_EVENTS, "Refreshing LSA: Type: %04x, Id: %R, Rt: %R, Seq: %08x",
385 en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn);
70945cb6
OZ
386
387 ASSERT(en->next_lsa_body == NULL);
388
389 /* Handle wrapping sequence number */
390 if (en->lsa.sn == LSA_MAXSEQNO)
391 {
392 /* Copy LSA body as next LSA to get automatic origination after flush is finished */
393 en->next_lsa_blen = en->lsa.length - sizeof(struct ospf_lsa_header);
394 en->next_lsa_body = mb_alloc(p->p.pool, en->next_lsa_blen);
395 memcpy(en->next_lsa_body, en->lsa_body, en->next_lsa_blen);
396 en->next_lsa_opts = ospf_is_v2(p) ? lsa_get_options(&en->lsa) : 0;
397
398 en->lsa.age = LSA_MAXAGE;
a7a7372a 399 ospf_flood_lsa(p, en, NULL);
70945cb6
OZ
400 return;
401 }
402
403 en->lsa.sn++;
404 en->lsa.age = 0;
405 en->init_age = 0;
b32d557a 406 en->inst_time = current_time();
77edab64 407 lsa_generate_checksum(&en->lsa, en->lsa_body);
a7a7372a 408 ospf_flood_lsa(p, en, NULL);
70945cb6
OZ
409}
410
411/**
412 * ospf_flush_lsa - flush LSA from OSPF domain
413 * @p: OSPF protocol instance
414 * @en: LSA entry to flush
415 *
416 * This function flushes @en from the OSPF domain by setting its age to
417 * %LSA_MAXAGE and flooding it. That also triggers subsequent events in LSA
418 * lifecycle leading to removal of the LSA from the LSA database (e.g. the LSA
419 * content is freed when flushing is acknowledged by neighbors). The function
420 * does nothing if the LSA is already being flushed. LSA entries are not
421 * immediately removed when being flushed, the caller may assume that @en still
422 * exists after the call. The function is the opposite of ospf_originate_lsa()
423 * and is supposed to do the right thing even in cases of postponed
a7a7372a 424 * origination.
70945cb6
OZ
425 */
426void
427ospf_flush_lsa(struct ospf_proto *p, struct top_hash_entry *en)
428{
cea2e25f 429 en->nf = NULL;
85840d4c 430 en->gr_dirty = 0;
cea2e25f 431
70945cb6
OZ
432 if (en->next_lsa_body)
433 {
434 mb_free(en->next_lsa_body);
435 en->next_lsa_body = NULL;
436 en->next_lsa_blen = 0;
437 en->next_lsa_opts = 0;
438 }
439
440 if (en->lsa.age == LSA_MAXAGE)
441 return;
442
6f8bbaa1
OZ
443 OSPF_TRACE(D_EVENTS, "Flushing LSA: Type: %04x, Id: %R, Rt: %R, Seq: %08x",
444 en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn);
445
70945cb6 446 en->lsa.age = LSA_MAXAGE;
a7a7372a
OZ
447 ospf_flood_lsa(p, en, NULL);
448
449 if (en->mode == LSA_M_BASIC)
1a2ad348
OZ
450 {
451 ospf_neigh_lsadb_changed(p, en);
a7a7372a 452 ospf_schedule_rtcalc(p);
1a2ad348 453 }
a7a7372a
OZ
454
455 en->mode = LSA_M_BASIC;
70945cb6
OZ
456}
457
458static void
459ospf_clear_lsa(struct ospf_proto *p, struct top_hash_entry *en)
460{
461 /*
462 * Called by ospf_update_lsadb() as part of LSA flushing process.
463 * Flushed LSA was acknowledged by neighbors and we can free its content.
6f8bbaa1 464 * The log message is for 'remove' - we hide empty LSAs from users.
70945cb6
OZ
465 */
466
6f8bbaa1
OZ
467 OSPF_TRACE(D_EVENTS, "Removing LSA: Type: %04x, Id: %R, Rt: %R, Seq: %08x",
468 en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn);
469
70945cb6
OZ
470 if (en->lsa.sn == LSA_MAXSEQNO)
471 en->lsa.sn = LSA_ZEROSEQNO;
472
473 mb_free(en->lsa_body);
474 en->lsa_body = NULL;
475}
476
477static void
478ospf_remove_lsa(struct ospf_proto *p, struct top_hash_entry *en)
479{
480 /*
481 * Called by ospf_update_lsadb() as part of LSA flushing process.
482 * Both lsa_body and next_lsa_body are NULL.
483 */
484
485 s_rem_node(SNODE en);
486 ospf_hash_delete(p->gr, en);
487}
488
489/**
490 * ospf_update_lsadb - update LSA database
491 * @p: OSPF protocol instance
492 *
493 * This function is periodicaly invoked from ospf_disp(). It does some periodic
494 * or postponed processing related to LSA entries. It originates postponed LSAs
495 * scheduled by ospf_originate_lsa(), It continues in flushing processes started
496 * by ospf_flush_lsa(). It also periodically refreshs locally originated LSAs --
497 * when the current instance is older %LSREFRESHTIME, a new instance is originated.
498 * Finally, it also ages stored LSAs and flushes ones that reached %LSA_MAXAGE.
499 *
500 * The RFC 2328 says that a router should periodically check checksums of all
501 * stored LSAs to detect hardware problems. This is not implemented.
502 */
503void
504ospf_update_lsadb(struct ospf_proto *p)
505{
506 struct top_hash_entry *en, *nxt;
b32d557a
OZ
507 btime now_ = current_time();
508 int real_age;
70945cb6
OZ
509
510 WALK_SLIST_DELSAFE(en, nxt, p->lsal)
511 {
512 if (en->next_lsa_body)
513 ospf_originate_next_lsa(p, en);
514
b32d557a 515 real_age = en->init_age + (now_ - en->inst_time) TO_S;
70945cb6
OZ
516
517 if (en->lsa.age == LSA_MAXAGE)
518 {
519 if (en->lsa_body && (p->padj == 0) && (en->ret_count == 0))
520 ospf_clear_lsa(p, en);
521
522 if ((en->lsa_body == NULL) && (en->next_lsa_body == NULL) &&
523 ((en->lsa.rt != p->router_id) || (real_age >= LSA_MAXAGE)))
524 ospf_remove_lsa(p, en);
525
526 continue;
527 }
528
529 if ((en->lsa.rt == p->router_id) && (real_age >= LSREFRESHTIME))
530 {
531 ospf_refresh_lsa(p, en);
532 continue;
533 }
534
535 if (real_age >= LSA_MAXAGE)
3d15dcdb 536 {
70945cb6 537 ospf_flush_lsa(p, en);
70945cb6 538 continue;
3d15dcdb 539 }
70945cb6
OZ
540
541 en->lsa.age = real_age;
542 }
543}
544
1a2ad348 545void
85840d4c 546ospf_feed_begin(struct channel *C, int initial UNUSED)
1a2ad348 547{
85840d4c 548 struct ospf_proto *p = (struct ospf_proto *) C->proto;
1a2ad348
OZ
549 struct top_hash_entry *en;
550
85840d4c 551 /* Mark all external LSAs as stale */
1a2ad348 552 WALK_SLIST(en, p->lsal)
85840d4c
OZ
553 if (en->mode == LSA_M_EXPORT)
554 en->mode = LSA_M_EXPORT_STALE;
555}
556
557void
558ospf_feed_end(struct channel *C)
559{
560 struct ospf_proto *p = (struct ospf_proto *) C->proto;
561 struct top_hash_entry *en;
562
563 /* Flush stale LSAs */
564 WALK_SLIST(en, p->lsal)
565 if (en->mode == LSA_M_EXPORT_STALE)
566 ospf_flush_lsa(p, en);
1a2ad348 567}
70945cb6 568
74c838a8 569static u32
70945cb6
OZ
570ort_to_lsaid(struct ospf_proto *p, ort *nf)
571{
572 /*
573 * In OSPFv2, We have to map IP prefixes to u32 in such manner that resulting
574 * u32 interpreted as IP address is a member of given prefix. Therefore, /32
fe9f1a6d
OZ
575 * prefix has to be mapped on itself. All received prefixes have to be mapped
576 * on different u32s.
70945cb6
OZ
577 *
578 * We have an assumption that if there is nontrivial (non-/32) network prefix,
579 * then there is not /32 prefix for the first and the last IP address of the
580 * network (these are usually reserved, therefore it is not an important
581 * restriction). The network prefix is mapped to the first or the last IP
582 * address in the manner that disallow collisions - we use the IP address that
583 * cannot be used by the parent prefix.
584 *
585 * For example:
586 * 192.168.0.0/24 maps to 192.168.0.255
587 * 192.168.1.0/24 maps to 192.168.1.0
588 * because 192.168.0.0 and 192.168.1.255 might be used by 192.168.0.0/23 .
589 *
590 * Appendig E of RFC 2328 suggests different algorithm, that tries to maximize
591 * both compatibility and subnetting. But as it is not possible to have both
592 * reliably and the suggested algorithm was unnecessary complicated and it
593 * does crazy things like changing LSA ID for a network because different
594 * network appeared, we choose a different way.
595 *
596 * In OSPFv3, it is simpler. There is not a requirement for membership of the
74c838a8
OZ
597 * result in the input network, so we just allocate a unique ID from ID map
598 * and store it in nf->lsa_id for further reference.
70945cb6
OZ
599 */
600
601 if (ospf_is_v3(p))
74c838a8
OZ
602 {
603 if (!nf->lsa_id)
604 nf->lsa_id = idm_alloc(&p->idm);
605
606 return nf->lsa_id;
607 }
70945cb6 608
fe9f1a6d
OZ
609 net_addr_ip4 *net = (void *) nf->fn.addr;
610 u32 id = ip4_to_u32(net->prefix);
611 int pxlen = net->pxlen;
70945cb6
OZ
612
613 if ((pxlen == 0) || (pxlen == 32))
614 return id;
615
616 if (id & (1 << (32 - pxlen)))
617 return id;
618 else
619 return id | ~u32_mkmask(pxlen);
620}
621
622
623static void *
a7a7372a 624lsab_alloc(struct ospf_proto *p, uint size)
70945cb6 625{
a7a7372a 626 uint offset = p->lsab_used;
70945cb6
OZ
627 p->lsab_used += size;
628 if (p->lsab_used > p->lsab_size)
629 {
630 p->lsab_size = MAX(p->lsab_used, 2 * p->lsab_size);
631 p->lsab = p->lsab ? mb_realloc(p->lsab, p->lsab_size):
632 mb_alloc(p->p.pool, p->lsab_size);
633 }
634 return ((byte *) p->lsab) + offset;
3d15dcdb
OZ
635}
636
637static inline void *
a7a7372a 638lsab_allocz(struct ospf_proto *p, uint size)
3d15dcdb 639{
70945cb6 640 void *r = lsab_alloc(p, size);
3d15dcdb
OZ
641 bzero(r, size);
642 return r;
643}
644
645static inline void *
70945cb6 646lsab_flush(struct ospf_proto *p)
3d15dcdb 647{
70945cb6
OZ
648 void *r = mb_alloc(p->p.pool, p->lsab_used);
649 memcpy(r, p->lsab, p->lsab_used);
650 p->lsab_used = 0;
3d15dcdb
OZ
651 return r;
652}
653
70945cb6
OZ
654static inline void
655lsab_reset(struct ospf_proto *p)
c3226991 656{
70945cb6 657 p->lsab_used = 0;
c3226991
OZ
658}
659
660static inline void *
a7a7372a 661lsab_offset(struct ospf_proto *p, uint offset)
c3226991 662{
70945cb6 663 return ((byte *) p->lsab) + offset;
c3226991
OZ
664}
665
3e236955 666static inline void * UNUSED
70945cb6 667lsab_end(struct ospf_proto *p)
52572e94 668{
70945cb6 669 return ((byte *) p->lsab) + p->lsab_used;
52572e94
OZ
670}
671
c3226991 672
70945cb6
OZ
673/*
674 * Router-LSA handling
675 * Type = LSA_T_RT
676 */
677
38675202
OZ
678static int
679configured_stubnet(struct ospf_area *oa, struct ifa *a)
680{
52a43ae3 681 /* Does not work for IA_PEER addresses, but it is not called on these */
38675202
OZ
682 struct ospf_stubnet_config *sn;
683 WALK_LIST(sn, oa->ac->stubnet_list)
70945cb6
OZ
684 {
685 if (sn->summary)
38675202 686 {
d44e686e 687 if (net_in_netX(&a->prefix, &sn->prefix))
70945cb6 688 return 1;
38675202 689 }
70945cb6
OZ
690 else
691 {
d44e686e 692 if (net_equal(&a->prefix, &sn->prefix))
70945cb6
OZ
693 return 1;
694 }
695 }
696
38675202
OZ
697 return 0;
698}
3d15dcdb 699
70945cb6 700static int
c3226991
OZ
701bcast_net_active(struct ospf_iface *ifa)
702{
703 struct ospf_neighbor *neigh;
704
705 if (ifa->state == OSPF_IS_WAITING)
706 return 0;
707
708 WALK_LIST(neigh, ifa->neigh_list)
70945cb6
OZ
709 {
710 if (neigh->state == NEIGHBOR_FULL)
c3226991 711 {
70945cb6
OZ
712 if (neigh->rid == ifa->drid)
713 return 1;
c3226991 714
70945cb6
OZ
715 if (ifa->state == OSPF_IS_DR)
716 return 1;
c3226991 717 }
70945cb6 718 }
c3226991
OZ
719
720 return 0;
721}
722
70945cb6
OZ
723static inline u32
724get_rt_options(struct ospf_proto *p, struct ospf_area *oa, int bitv)
725{
726 u32 opts = 0;
c3226991 727
70945cb6
OZ
728 if (p->areano > 1)
729 opts |= OPT_RT_B;
c3226991 730
70945cb6
OZ
731 if ((p->areano > 1) && oa_is_nssa(oa) && oa->ac->translator)
732 opts |= OPT_RT_NT;
ce17d4c1 733
70945cb6
OZ
734 if (p->asbr && !oa_is_stub(oa))
735 opts |= OPT_RT_E;
c3226991 736
70945cb6
OZ
737 if (bitv)
738 opts |= OPT_RT_V;
c3226991 739
70945cb6
OZ
740 return opts;
741}
c3226991 742
70945cb6
OZ
743static inline void
744add_rt2_lsa_link(struct ospf_proto *p, u8 type, u32 id, u32 data, u16 metric)
745{
746 struct ospf_lsa_rt2_link *ln = lsab_alloc(p, sizeof(struct ospf_lsa_rt2_link));
747 ln->type = type;
748 ln->id = id;
749 ln->data = data;
750 ln->metric = metric;
751 ln->no_tos = 0;
752}
4160a9dd 753
70945cb6
OZ
754static void
755prepare_rt2_lsa_body(struct ospf_proto *p, struct ospf_area *oa)
756{
757 struct ospf_iface *ifa;
758 int i = 0, bitv = 0;
759 struct ospf_neighbor *neigh;
c3226991 760
70945cb6
OZ
761 ASSERT(p->lsab_used == 0);
762 lsab_allocz(p, sizeof(struct ospf_lsa_rt));
763 /* ospf_lsa_rt header will be filled later */
b9ed99f7 764
70945cb6 765 WALK_LIST(ifa, p->iface_list)
ce17d4c1 766 {
353729f5 767 int net_lsa = 0;
70945cb6 768 u32 link_cost = p->stub_router ? 0xffff : ifa->cost;
3d15dcdb
OZ
769
770 if ((ifa->type == OSPF_IT_VLINK) && (ifa->voa == oa) &&
771 (!EMPTY_LIST(ifa->neigh_list)))
5d3f5552
OF
772 {
773 neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list);
774 if ((neigh->state == NEIGHBOR_FULL) && (ifa->cost <= 0xffff))
3d15dcdb 775 bitv = 1;
5d3f5552 776 }
3b16080c
OF
777
778 if ((ifa->oa != oa) || (ifa->state == OSPF_IS_DOWN))
b9ed99f7 779 continue;
3b580a23 780
e7b4948c
OZ
781 ifa->rt_pos_beg = i;
782
70945cb6 783 /* RFC 2328 - 12.4.1.1-4 */
3d15dcdb 784 switch (ifa->type)
70945cb6
OZ
785 {
786 case OSPF_IT_PTP:
787 case OSPF_IT_PTMP:
788 WALK_LIST(neigh, ifa->neigh_list)
789 if (neigh->state == NEIGHBOR_FULL)
98ac6176 790 {
70945cb6
OZ
791 /*
792 * ln->data should be ifa->iface_id in case of no/ptp
793 * address (ifa->addr->flags & IA_PEER) on PTP link (see
794 * RFC 2328 12.4.1.1.), but the iface ID value has no use,
795 * while using IP address even in this case is here for
796 * compatibility with some broken implementations that use
797 * this address as a next-hop.
798 */
799 add_rt2_lsa_link(p, LSART_PTP, neigh->rid, ipa_to_u32(ifa->addr->ip), link_cost);
3d15dcdb 800 i++;
70945cb6
OZ
801 }
802 break;
3d15dcdb 803
70945cb6
OZ
804 case OSPF_IT_BCAST:
805 case OSPF_IT_NBMA:
806 if (bcast_net_active(ifa))
807 {
808 add_rt2_lsa_link(p, LSART_NET, ipa_to_u32(ifa->drip), ipa_to_u32(ifa->addr->ip), link_cost);
809 i++;
810 net_lsa = 1;
ce17d4c1 811 }
70945cb6
OZ
812 break;
813
814 case OSPF_IT_VLINK:
815 neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list);
816 if ((!EMPTY_LIST(ifa->neigh_list)) && (neigh->state == NEIGHBOR_FULL) && (ifa->cost <= 0xffff))
817 add_rt2_lsa_link(p, LSART_VLNK, neigh->rid, ipa_to_u32(ifa->addr->ip), link_cost), i++;
818 break;
819
820 default:
f8fefde3 821 log(L_BUG "OSPF: Unknown interface type");
70945cb6
OZ
822 break;
823 }
3d15dcdb 824
e7b4948c
OZ
825 ifa->rt_pos_end = i;
826
0aad2b92
OZ
827 /* Now we will originate stub area if there is no primary */
828 if (net_lsa ||
829 (ifa->type == OSPF_IT_VLINK) ||
a55a90fa 830 ((ifa->addr->flags & IA_PEER) && ! ifa->cf->stub) ||
0aad2b92
OZ
831 configured_stubnet(oa, ifa->addr))
832 continue;
3d15dcdb 833
70945cb6 834 /* Host or network stub entry */
52a43ae3
OZ
835 if ((ifa->addr->flags & IA_HOST) ||
836 (ifa->state == OSPF_IS_LOOP) ||
837 (ifa->type == OSPF_IT_PTMP))
70945cb6 838 add_rt2_lsa_link(p, LSART_STUB, ipa_to_u32(ifa->addr->ip), 0xffffffff, 0);
742029eb 839 else
d44e686e
OZ
840 add_rt2_lsa_link(p, LSART_STUB, ip4_to_u32(net4_prefix(&ifa->addr->prefix)),
841 u32_mkmask(net4_pxlen(&ifa->addr->prefix)), ifa->cost);
0aad2b92 842 i++;
e7b4948c
OZ
843
844 ifa->rt_pos_end = i;
ce17d4c1 845 }
3d15dcdb 846
38675202 847 struct ospf_stubnet_config *sn;
70945cb6
OZ
848 WALK_LIST(sn, oa->ac->stubnet_list)
849 if (!sn->hidden)
d44e686e
OZ
850 add_rt2_lsa_link(p, LSART_STUB, ip4_to_u32(net4_prefix(&sn->prefix)),
851 u32_mkmask(net4_pxlen(&sn->prefix)), sn->cost), i++;
c3226991 852
70945cb6 853 struct ospf_lsa_rt *rt = p->lsab;
742029eb 854 /* Store number of links in lower half of options */
70945cb6 855 rt->options = get_rt_options(p, oa, bitv) | (u16) i;
ce17d4c1 856}
c45f48fb 857
70945cb6
OZ
858static inline void
859add_rt3_lsa_link(struct ospf_proto *p, u8 type, struct ospf_iface *ifa, u32 nif, u32 id)
c3226991 860{
70945cb6 861 struct ospf_lsa_rt3_link *ln = lsab_alloc(p, sizeof(struct ospf_lsa_rt3_link));
c3226991
OZ
862 ln->type = type;
863 ln->padding = 0;
864 ln->metric = ifa->cost;
dd4da6f6 865 ln->lif = ifa->iface_id;
c3226991
OZ
866 ln->nif = nif;
867 ln->id = id;
868}
869
70945cb6
OZ
870static void
871prepare_rt3_lsa_body(struct ospf_proto *p, struct ospf_area *oa)
c3226991 872{
c3226991 873 struct ospf_iface *ifa;
70945cb6 874 struct ospf_neighbor *neigh;
b49e6f5a 875 int bitv = 0;
e7b4948c 876 int i = 0;
4160a9dd 877
70945cb6
OZ
878 ASSERT(p->lsab_used == 0);
879 lsab_allocz(p, sizeof(struct ospf_lsa_rt));
880 /* ospf_lsa_rt header will be filled later */
c3226991 881
70945cb6 882 WALK_LIST(ifa, p->iface_list)
c3226991
OZ
883 {
884 if ((ifa->type == OSPF_IT_VLINK) && (ifa->voa == oa) &&
885 (!EMPTY_LIST(ifa->neigh_list)))
886 {
887 neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list);
888 if ((neigh->state == NEIGHBOR_FULL) && (ifa->cost <= 0xffff))
889 bitv = 1;
890 }
891
892 if ((ifa->oa != oa) || (ifa->state == OSPF_IS_DOWN))
893 continue;
894
e7b4948c
OZ
895 ifa->rt_pos_beg = i;
896
70945cb6 897 /* RFC 5340 - 4.4.3.2 */
c3226991 898 switch (ifa->type)
70945cb6
OZ
899 {
900 case OSPF_IT_PTP:
901 case OSPF_IT_PTMP:
902 WALK_LIST(neigh, ifa->neigh_list)
903 if (neigh->state == NEIGHBOR_FULL)
904 add_rt3_lsa_link(p, LSART_PTP, ifa, neigh->iface_id, neigh->rid), i++;
905 break;
e7b4948c 906
70945cb6
OZ
907 case OSPF_IT_BCAST:
908 case OSPF_IT_NBMA:
909 if (bcast_net_active(ifa))
910 add_rt3_lsa_link(p, LSART_NET, ifa, ifa->dr_iface_id, ifa->drid), i++;
911 break;
c3226991 912
70945cb6
OZ
913 case OSPF_IT_VLINK:
914 neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list);
915 if ((!EMPTY_LIST(ifa->neigh_list)) && (neigh->state == NEIGHBOR_FULL) && (ifa->cost <= 0xffff))
916 add_rt3_lsa_link(p, LSART_VLNK, ifa, neigh->iface_id, neigh->rid), i++;
917 break;
918
919 default:
f8fefde3 920 log(L_BUG "OSPF: Unknown interface type");
70945cb6 921 break;
c3226991
OZ
922 }
923
70945cb6
OZ
924 ifa->rt_pos_end = i;
925 }
c3226991 926
70945cb6
OZ
927 struct ospf_lsa_rt *rt = p->lsab;
928 rt->options = get_rt_options(p, oa, bitv) | (oa->options & LSA_OPTIONS_MASK);
929}
c3226991 930
70945cb6
OZ
931static void
932ospf_originate_rt_lsa(struct ospf_proto *p, struct ospf_area *oa)
d8852b36 933{
70945cb6
OZ
934 struct ospf_new_lsa lsa = {
935 .type = LSA_T_RT,
936 .dom = oa->areaid,
937 .id = ospf_is_v2(p) ? p->router_id : 0,
938 .opts = oa->options
939 };
d8852b36 940
a7a7372a
OZ
941 OSPF_TRACE(D_EVENTS, "Updating router state for area %R", oa->areaid);
942
70945cb6
OZ
943 if (ospf_is_v2(p))
944 prepare_rt2_lsa_body(p, oa);
945 else
946 prepare_rt3_lsa_body(p, oa);
b9ed99f7 947
70945cb6
OZ
948 oa->rt = ospf_originate_lsa(p, &lsa);
949}
cf31112f 950
c3226991 951
70945cb6
OZ
952/*
953 * Net-LSA handling
954 * Type = LSA_T_NET
955 */
b49e6f5a 956
70945cb6
OZ
957static void
958prepare_net2_lsa_body(struct ospf_proto *p, struct ospf_iface *ifa)
b49e6f5a 959{
70945cb6
OZ
960 struct ospf_lsa_net *net;
961 struct ospf_neighbor *n;
962 int nodes = ifa->fadj + 1;
963 u16 i = 1;
b49e6f5a 964
70945cb6
OZ
965 ASSERT(p->lsab_used == 0);
966 net = lsab_alloc(p, sizeof(struct ospf_lsa_net) + 4 * nodes);
b49e6f5a 967
d44e686e 968 net->optx = u32_mkmask(ifa->addr->prefix.pxlen);
70945cb6 969 net->routers[0] = p->router_id;
b49e6f5a 970
70945cb6
OZ
971 WALK_LIST(n, ifa->neigh_list)
972 {
973 if (n->state == NEIGHBOR_FULL)
974 {
975 net->routers[i] = n->rid;
976 i++;
977 }
978 }
979 ASSERT(i == nodes);
ab56f6b1
OF
980}
981
70945cb6
OZ
982static void
983prepare_net3_lsa_body(struct ospf_proto *p, struct ospf_iface *ifa)
0bf2f203 984{
d345cda5 985 struct ospf_lsa_net *net;
c3226991 986 int nodes = ifa->fadj + 1;
c3226991 987 u32 options = 0;
70945cb6
OZ
988 u16 i = 1;
989
990 ASSERT(p->lsab_used == 0);
991 net = lsab_alloc(p, sizeof(struct ospf_lsa_net) + 4 * nodes);
c3226991 992
70945cb6 993 net->routers[0] = p->router_id;
d345cda5 994
70945cb6 995 struct ospf_neighbor *n;
b9ed99f7 996 WALK_LIST(n, ifa->neigh_list)
0bf2f203 997 {
b9ed99f7 998 if (n->state == NEIGHBOR_FULL)
0bf2f203 999 {
70945cb6
OZ
1000 /* In OSPFv3, we would like to merge options from Link LSAs of added neighbors */
1001
1002 struct top_hash_entry *en =
1003 ospf_hash_find(p->gr, ifa->iface_id, n->iface_id, n->rid, LSA_T_LINK);
1004
c3226991
OZ
1005 if (en)
1006 options |= ((struct ospf_lsa_link *) en->lsa_body)->options;
c3226991
OZ
1007
1008 net->routers[i] = n->rid;
0bf2f203
OF
1009 i++;
1010 }
1011 }
c3226991
OZ
1012 ASSERT(i == nodes);
1013
70945cb6 1014 net->optx = options & LSA_OPTIONS_MASK;
0bf2f203
OF
1015}
1016
70945cb6
OZ
1017static void
1018ospf_originate_net_lsa(struct ospf_proto *p, struct ospf_iface *ifa)
1019{
1020 struct ospf_new_lsa lsa = {
1021 .type = LSA_T_NET,
1022 .dom = ifa->oa->areaid,
1023 .id = ospf_is_v2(p) ? ipa_to_u32(ifa->addr->ip) : ifa->iface_id,
1024 .opts = ifa->oa->options,
1025 .ifa = ifa
1026 };
1027
a7a7372a
OZ
1028 OSPF_TRACE(D_EVENTS, "Updating network state for %s (Id: %R)", ifa->ifname, lsa.id);
1029
70945cb6
OZ
1030 if (ospf_is_v2(p))
1031 prepare_net2_lsa_body(p, ifa);
b49e6f5a 1032 else
70945cb6 1033 prepare_net3_lsa_body(p, ifa);
9727681a 1034
70945cb6 1035 ifa->net_lsa = ospf_originate_lsa(p, &lsa);
9727681a
OZ
1036}
1037
7ff5803b 1038
70945cb6
OZ
1039/*
1040 * (Net|Rt)-summary-LSA handling
1041 * (a.k.a. Inter-Area-(Prefix|Router)-LSA)
1042 * Type = LSA_T_SUM_NET, LSA_T_SUM_RT
1043 */
0077aab4 1044
70945cb6
OZ
1045static inline void
1046prepare_sum2_lsa_body(struct ospf_proto *p, uint pxlen, u32 metric)
0077aab4 1047{
70945cb6 1048 struct ospf_lsa_sum2 *sum;
c3226991 1049
70945cb6
OZ
1050 sum = lsab_allocz(p, sizeof(struct ospf_lsa_sum2));
1051 sum->netmask = u32_mkmask(pxlen);
c3226991 1052 sum->metric = metric;
c3226991
OZ
1053}
1054
70945cb6
OZ
1055static inline void
1056prepare_sum3_net_lsa_body(struct ospf_proto *p, ort *nf, u32 metric)
9727681a 1057{
70945cb6 1058 struct ospf_lsa_sum3_net *sum;
9727681a 1059
fe9f1a6d
OZ
1060 sum = lsab_allocz(p, sizeof(struct ospf_lsa_sum3_net) +
1061 IPV6_PREFIX_SPACE(nf->fn.addr->pxlen));
70945cb6 1062 sum->metric = metric;
d3f4f92b 1063 ospf3_put_prefix(sum->prefix, nf->fn.addr, 0, 0);
9727681a
OZ
1064}
1065
70945cb6
OZ
1066static inline void
1067prepare_sum3_rt_lsa_body(struct ospf_proto *p, u32 drid, u32 metric, u32 options)
c3226991 1068{
70945cb6 1069 struct ospf_lsa_sum3_rt *sum;
c3226991 1070
70945cb6 1071 sum = lsab_allocz(p, sizeof(struct ospf_lsa_sum3_rt));
7ff5803b 1072 sum->options = options;
c3226991
OZ
1073 sum->metric = metric;
1074 sum->drid = drid;
7ff5803b
OZ
1075}
1076
98ac6176 1077void
70945cb6 1078ospf_originate_sum_net_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, int metric)
98ac6176 1079{
70945cb6
OZ
1080 struct ospf_new_lsa lsa = {
1081 .type = LSA_T_SUM_NET,
a7a7372a 1082 .mode = LSA_M_RTCALC,
70945cb6
OZ
1083 .dom = oa->areaid,
1084 .id = ort_to_lsaid(p, nf),
1085 .opts = oa->options,
1086 .nf = nf
1087 };
7ff5803b 1088
70945cb6 1089 if (ospf_is_v2(p))
fe9f1a6d 1090 prepare_sum2_lsa_body(p, nf->fn.addr->pxlen, metric);
70945cb6
OZ
1091 else
1092 prepare_sum3_net_lsa_body(p, nf, metric);
c3226991 1093
a7a7372a 1094 ospf_originate_lsa(p, &lsa);
9727681a 1095}
c3226991 1096
9727681a 1097void
fe9f1a6d 1098ospf_originate_sum_rt_lsa(struct ospf_proto *p, struct ospf_area *oa, u32 drid, int metric, u32 options)
9727681a 1099{
70945cb6
OZ
1100 struct ospf_new_lsa lsa = {
1101 .type = LSA_T_SUM_RT,
a7a7372a 1102 .mode = LSA_M_RTCALC,
70945cb6 1103 .dom = oa->areaid,
fe9f1a6d 1104 .id = drid, /* Router ID of ASBR, irrelevant for OSPFv3 */
70945cb6
OZ
1105 .opts = oa->options
1106 };
98ac6176 1107
70945cb6
OZ
1108 if (ospf_is_v2(p))
1109 prepare_sum2_lsa_body(p, 0, metric);
c3226991 1110 else
fe9f1a6d 1111 prepare_sum3_rt_lsa_body(p, drid, metric, options & LSA_OPTIONS_MASK);
9727681a 1112
a7a7372a 1113 ospf_originate_lsa(p, &lsa);
98ac6176
OF
1114}
1115
c3226991 1116
7ff5803b 1117/*
70945cb6
OZ
1118 * AS-external-LSA and NSSA-LSA handling
1119 * Type = LSA_T_EXT, LSA_T_NSSA
7ff5803b 1120 */
c3226991 1121
70945cb6
OZ
1122static inline void
1123prepare_ext2_lsa_body(struct ospf_proto *p, uint pxlen,
1124 u32 metric, u32 ebit, ip_addr fwaddr, u32 tag)
7ff5803b 1125{
70945cb6 1126 struct ospf_lsa_ext2 *ext;
7ff5803b 1127
70945cb6
OZ
1128 ext = lsab_allocz(p, sizeof(struct ospf_lsa_ext2));
1129 ext->metric = metric & LSA_METRIC_MASK;
1130 ext->netmask = u32_mkmask(pxlen);
1131 ext->fwaddr = ipa_to_u32(fwaddr);
1132 ext->tag = tag;
7ff5803b 1133
70945cb6
OZ
1134 if (ebit)
1135 ext->metric |= LSA_EXT2_EBIT;
7ff5803b 1136}
c3226991 1137
70945cb6
OZ
1138static inline void
1139prepare_ext3_lsa_body(struct ospf_proto *p, ort *nf,
4a3f5b36 1140 u32 metric, u32 ebit, ip_addr fwaddr, u32 tag, int pbit, int dn)
7ff5803b 1141{
70945cb6
OZ
1142 struct ospf_lsa_ext3 *ext;
1143 int bsize = sizeof(struct ospf_lsa_ext3)
fe9f1a6d 1144 + IPV6_PREFIX_SPACE(nf->fn.addr->pxlen)
7ff5803b
OZ
1145 + (ipa_nonzero(fwaddr) ? 16 : 0)
1146 + (tag ? 4 : 0);
1147
70945cb6
OZ
1148 ext = lsab_allocz(p, bsize);
1149 ext->metric = metric & LSA_METRIC_MASK;
1150 u32 *buf = ext->rest;
7ff5803b 1151
4a3f5b36
OZ
1152 uint flags = (pbit ? OPT_PX_P : 0) | (dn ? OPT_PX_DN : 0);
1153 buf = ospf3_put_prefix(buf, nf->fn.addr, flags, 0);
7ff5803b 1154
70945cb6
OZ
1155 if (ebit)
1156 ext->metric |= LSA_EXT3_EBIT;
c3226991 1157
7ff5803b
OZ
1158 if (ipa_nonzero(fwaddr))
1159 {
70945cb6 1160 ext->metric |= LSA_EXT3_FBIT;
d3f4f92b 1161 buf = ospf3_put_addr(buf, fwaddr);
7ff5803b 1162 }
c3226991
OZ
1163
1164 if (tag)
7ff5803b 1165 {
70945cb6 1166 ext->metric |= LSA_EXT3_TBIT;
7ff5803b
OZ
1167 *buf++ = tag;
1168 }
c3226991
OZ
1169}
1170
70945cb6
OZ
1171/**
1172 * originate_ext_lsa - new route received from nest and filters
a7a7372a 1173 * @p: OSPF protocol instance
70945cb6
OZ
1174 * @oa: ospf_area for which LSA is originated
1175 * @nf: network prefix and mask
a7a7372a
OZ
1176 * @mode: the mode of the LSA (LSA_M_EXPORT or LSA_M_RTCALC)
1177 * @metric: the metric of a route
1178 * @ebit: E-bit for route metric (bool)
70945cb6
OZ
1179 * @fwaddr: the forwarding address
1180 * @tag: the route tag
a7a7372a 1181 * @pbit: P-bit for NSSA LSAs (bool), ignored for external LSAs
70945cb6
OZ
1182 *
1183 * If I receive a message that new route is installed, I try to originate an
1184 * external LSA. If @oa is an NSSA area, NSSA-LSA is originated instead.
1185 * @oa should not be a stub area. @src does not specify whether the LSA
742029eb 1186 * is external or NSSA, but it specifies the source of origination -
70945cb6
OZ
1187 * the export from ospf_rt_notify(), or the NSSA-EXT translation.
1188 */
1189void
a7a7372a 1190ospf_originate_ext_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, u8 mode,
4a3f5b36 1191 u32 metric, u32 ebit, ip_addr fwaddr, u32 tag, int pbit, int dn)
7ff5803b 1192{
70945cb6
OZ
1193 struct ospf_new_lsa lsa = {
1194 .type = oa ? LSA_T_NSSA : LSA_T_EXT,
a7a7372a 1195 .mode = mode, /* LSA_M_EXPORT or LSA_M_RTCALC */
70945cb6
OZ
1196 .dom = oa ? oa->areaid : 0,
1197 .id = ort_to_lsaid(p, nf),
4a3f5b36 1198 .opts = (oa ? (pbit ? OPT_P : 0) : OPT_E) | (dn ? OPT_DN : 0),
70945cb6
OZ
1199 .nf = nf
1200 };
7ff5803b 1201
70945cb6 1202 if (ospf_is_v2(p))
fe9f1a6d 1203 prepare_ext2_lsa_body(p, nf->fn.addr->pxlen, metric, ebit, fwaddr, tag);
70945cb6 1204 else
4a3f5b36 1205 prepare_ext3_lsa_body(p, nf, metric, ebit, fwaddr, tag, oa && pbit, dn);
7ff5803b 1206
a7a7372a 1207 ospf_originate_lsa(p, &lsa);
70945cb6
OZ
1208}
1209
6f8bbaa1
OZ
1210static struct top_hash_entry *
1211ospf_hash_find_(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type);
1212
70945cb6
OZ
1213static void
1214ospf_flush_ext_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf)
1215{
1216 struct top_hash_entry *en;
d395fe48 1217
70945cb6
OZ
1218 u32 type = oa ? LSA_T_NSSA : LSA_T_EXT;
1219 u32 dom = oa ? oa->areaid : 0;
1220 u32 id = ort_to_lsaid(p, nf);
7ff5803b 1221
6f8bbaa1 1222 en = ospf_hash_find_(p->gr, dom, id, p->router_id, type);
7ff5803b 1223
70945cb6
OZ
1224 if (!en || (en->nf != nf))
1225 return;
7ff5803b 1226
70945cb6 1227 ospf_flush_lsa(p, en);
7ff5803b
OZ
1228}
1229
70945cb6
OZ
1230static inline int
1231use_gw_for_fwaddr(struct ospf_proto *p, ip_addr gw, struct iface *iface)
1232{
1233 struct ospf_iface *ifa;
1234
1235 if (ipa_zero(gw) || ipa_is_link_local(gw))
1236 return 0;
7ff5803b 1237
70945cb6
OZ
1238 WALK_LIST(ifa, p->iface_list)
1239 if ((ifa->iface == iface) &&
d44e686e 1240 (!ospf_is_v2(p) || ipa_in_netX(gw, &ifa->addr->prefix)))
70945cb6
OZ
1241 return 1;
1242
1243 return 0;
1244}
7ff5803b 1245
2918e610 1246static inline ip_addr
70945cb6 1247find_surrogate_fwaddr(struct ospf_proto *p, struct ospf_area *oa)
2918e610 1248{
2918e610
OZ
1249 struct ospf_iface *ifa;
1250 struct ifa *a, *cur_addr = NULL;
1251 int np, cur_np = 0;
1252
70945cb6
OZ
1253 /* RFC 3101 2.3 - surrogate forwarding address selection */
1254
1255 WALK_LIST(ifa, p->iface_list)
2918e610
OZ
1256 {
1257 if ((ifa->oa != oa) ||
2918e610
OZ
1258 (ifa->type == OSPF_IT_VLINK))
1259 continue;
1260
70945cb6 1261 if (ospf_is_v2(p))
2918e610 1262 {
70945cb6
OZ
1263 a = ifa->addr;
1264 if (a->flags & IA_PEER)
2918e610
OZ
1265 continue;
1266
70945cb6 1267 np = (a->flags & IA_HOST) ? 3 : (ifa->stub ? 2 : 1);
2918e610
OZ
1268 if (np > cur_np)
1269 {
1270 cur_addr = a;
1271 cur_np = np;
1272 }
1273 }
70945cb6
OZ
1274 else /* OSPFv3 */
1275 {
1276 WALK_LIST(a, ifa->iface->addrs)
1277 {
d3f4f92b 1278 if ((a->prefix.type != ospf_get_af(p)) ||
d44e686e 1279 (a->flags & IA_SECONDARY) ||
70945cb6
OZ
1280 (a->flags & IA_PEER) ||
1281 (a->scope <= SCOPE_LINK))
1282 continue;
1283
1284 np = (a->flags & IA_HOST) ? 3 : (ifa->stub ? 2 : 1);
1285 if (np > cur_np)
1286 {
1287 cur_addr = a;
1288 cur_np = np;
1289 }
1290 }
1291 }
2918e610
OZ
1292 }
1293
1294 return cur_addr ? cur_addr->ip : IPA_NONE;
1295}
1296
e8085aba 1297void
13c0be19 1298ospf_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte *old UNUSED)
e8085aba 1299{
70945cb6
OZ
1300 struct ospf_proto *p = (struct ospf_proto *) P;
1301 struct ospf_area *oa = NULL; /* non-NULL for NSSA-LSA */
1302 ort *nf;
41b612c3 1303
70945cb6
OZ
1304 /*
1305 * There are several posibilities:
1306 * 1) router in regular area - originate external LSA with global scope
1307 * 2) router in NSSA area - originate area-specific NSSA-LSA
1308 * 3) router in stub area - cannot export routes
1309 * 4) area border router - same as (1), it is attached to backbone
1310 */
b9ed99f7 1311
70945cb6
OZ
1312 if ((p->areano == 1) && oa_is_nssa(HEAD(p->area_list)))
1313 oa = HEAD(p->area_list);
273fd2c1 1314
70945cb6 1315 if (!new)
41b612c3 1316 {
fe9f1a6d 1317 nf = fib_find(&p->rtf, n->n.addr);
2918e610 1318
70945cb6 1319 if (!nf || !nf->external_rte)
2918e610 1320 return;
41b612c3 1321
70945cb6
OZ
1322 ospf_flush_ext_lsa(p, oa, nf);
1323 nf->external_rte = 0;
273fd2c1 1324
70945cb6
OZ
1325 /* Old external route might blocked some NSSA translation */
1326 if ((p->areano > 1) && rt_is_nssa(nf) && nf->n.oa->translate)
a7a7372a 1327 ospf_schedule_rtcalc(p);
7ff5803b 1328
70945cb6
OZ
1329 return;
1330 }
c3226991 1331
70945cb6 1332 ASSERT(p->asbr);
2918e610 1333
70945cb6
OZ
1334 /* Get route attributes */
1335 rta *a = new->attrs;
8bd718b3
OZ
1336 eattr *m1a = ea_find(a->eattrs, EA_OSPF_METRIC1);
1337 eattr *m2a = ea_find(a->eattrs, EA_OSPF_METRIC2);
feae132e
OZ
1338 uint m1 = m1a ? m1a->u.data : 0;
1339 uint m2 = m2a ? m2a->u.data : 10000;
fdb19982 1340
feae132e
OZ
1341 if (m1 > LSINFINITY)
1342 {
1343 log(L_WARN "%s: Invalid ospf_metric1 value %u for route %N",
1344 p->p.name, m1, n->n.addr);
1345 m1 = LSINFINITY;
1346 }
e8085aba 1347
feae132e
OZ
1348 if (m2 > LSINFINITY)
1349 {
1350 log(L_WARN "%s: Invalid ospf_metric2 value %u for route %N",
1351 p->p.name, m2, n->n.addr);
1352 m2 = LSINFINITY;
1353 }
1354
1355 /* Ensure monotonicity of metric if both m1 and m2 are used */
1356 if ((m1 > 0) && (m2 < LSINFINITY))
1357 m2++;
1358
1359 uint ebit = m2a || !m1a;
1360 uint metric = ebit ? m2 : m1;
8bd718b3 1361 uint tag = ea_get_int(a->eattrs, EA_OSPF_TAG, 0);
feae132e
OZ
1362
1363 ip_addr fwd = IPA_NONE;
4e276a89
JMM
1364 if ((a->dest == RTD_UNICAST) && use_gw_for_fwaddr(p, a->nh.gw, a->nh.iface))
1365 fwd = a->nh.gw;
be862406 1366
70945cb6
OZ
1367 /* NSSA-LSA with P-bit set must have non-zero forwarding address */
1368 if (oa && ipa_zero(fwd))
1369 {
1370 fwd = find_surrogate_fwaddr(p, oa);
c3226991 1371
70945cb6 1372 if (ipa_zero(fwd))
c3226991 1373 {
fe9f1a6d
OZ
1374 log(L_ERR "%s: Cannot find forwarding address for NSSA-LSA %N",
1375 p->p.name, n->n.addr);
70945cb6 1376 return;
c3226991 1377 }
70945cb6
OZ
1378 }
1379
fe9f1a6d 1380 nf = fib_get(&p->rtf, n->n.addr);
4a3f5b36 1381 ospf_originate_ext_lsa(p, oa, nf, LSA_M_EXPORT, metric, ebit, fwd, tag, 1, p->vpn_pe);
70945cb6 1382 nf->external_rte = 1;
c3226991
OZ
1383}
1384
1385
70945cb6
OZ
1386/*
1387 * Link-LSA handling (assume OSPFv3)
1388 * Type = LSA_T_LINK
1389 */
c3226991 1390
70945cb6 1391static inline void
d3f4f92b 1392lsab_put_prefix(struct ospf_proto *p, net_addr *n, u32 cost)
70945cb6 1393{
d3f4f92b
OZ
1394 void *buf = lsab_alloc(p, IPV6_PREFIX_SPACE(net_pxlen(n)));
1395 uint max = (n->type == NET_IP4) ? IP4_MAX_PREFIX_LENGTH : IP6_MAX_PREFIX_LENGTH;
1396 u8 flags = (net_pxlen(n) < max) ? 0 : OPT_PX_LA;
1397 ospf3_put_prefix(buf, n, flags, cost);
70945cb6
OZ
1398}
1399
1400static void
1401prepare_link_lsa_body(struct ospf_proto *p, struct ospf_iface *ifa)
c3226991 1402{
d3f4f92b 1403 ip_addr nh = ospf_is_ip4(p) ? IPA_NONE : ifa->addr->ip;
c3226991 1404 int i = 0;
c3226991 1405
d3f4f92b 1406 /* Preallocating space for header */
70945cb6 1407 ASSERT(p->lsab_used == 0);
d3f4f92b 1408 lsab_allocz(p, sizeof(struct ospf_lsa_link));
c3226991
OZ
1409
1410 struct ifa *a;
1411 WALK_LIST(a, ifa->iface->addrs)
70945cb6 1412 {
d3f4f92b 1413 if ((a->prefix.type != ospf_get_af(p)) ||
d44e686e
OZ
1414 (a->flags & IA_SECONDARY) ||
1415 (a->scope <= SCOPE_LINK))
70945cb6 1416 continue;
c3226991 1417
d3f4f92b
OZ
1418 if (ospf_is_ip4(p) && ipa_zero(nh))
1419 nh = a->ip;
1420
d44e686e 1421 lsab_put_prefix(p, &a->prefix, 0);
70945cb6
OZ
1422 i++;
1423 }
c3226991 1424
d3f4f92b
OZ
1425 /* Filling the preallocated header */
1426 struct ospf_lsa_link *ll = p->lsab;
1427 ll->options = ifa->oa->options | (ifa->priority << 24);
1428 ll->lladdr = ospf_is_ip4(p) ? ospf3_4to6(ipa_to_ip4(nh)) : ipa_to_ip6(nh);
c3226991 1429 ll->pxcount = i;
d3f4f92b
OZ
1430
1431 if (ipa_zero(nh))
1432 log(L_ERR "%s: Cannot find next hop address for %s", p->p.name, ifa->ifname);
c3226991
OZ
1433}
1434
70945cb6
OZ
1435static void
1436ospf_originate_link_lsa(struct ospf_proto *p, struct ospf_iface *ifa)
c3226991 1437{
70945cb6 1438 if (ospf_is_v2(p))
48e5f32d
OZ
1439 return;
1440
70945cb6
OZ
1441 struct ospf_new_lsa lsa = {
1442 .type = LSA_T_LINK,
1443 .dom = ifa->iface_id,
1444 .id = ifa->iface_id,
1445 .ifa = ifa
1446 };
c3226991 1447
a7a7372a
OZ
1448 OSPF_TRACE(D_EVENTS, "Updating link state for %s (Id: %R)", ifa->ifname, lsa.id);
1449
70945cb6 1450 prepare_link_lsa_body(p, ifa);
be862406 1451
70945cb6 1452 ifa->link_lsa = ospf_originate_lsa(p, &lsa);
c3226991
OZ
1453}
1454
1455
70945cb6
OZ
1456/*
1457 * Prefix-Rt-LSA handling (assume OSPFv3)
1458 * Type = LSA_T_PREFIX, referred type = LSA_T_RT
1459 */
d9e7e1b1 1460
70945cb6
OZ
1461static void
1462prepare_prefix_rt_lsa_body(struct ospf_proto *p, struct ospf_area *oa)
c3226991 1463{
70945cb6 1464 struct ospf_config *cf = (struct ospf_config *) (p->p.cf);
c3226991
OZ
1465 struct ospf_iface *ifa;
1466 struct ospf_lsa_prefix *lp;
6ff81197 1467 uint max = ospf_is_ip4(p) ? IP4_MAX_PREFIX_LENGTH : IP6_MAX_PREFIX_LENGTH;
3b89a232 1468 int host_addr = 0;
c3226991
OZ
1469 int net_lsa;
1470 int i = 0;
c3226991 1471
70945cb6
OZ
1472 ASSERT(p->lsab_used == 0);
1473 lp = lsab_allocz(p, sizeof(struct ospf_lsa_prefix));
c3226991
OZ
1474 lp->ref_type = LSA_T_RT;
1475 lp->ref_id = 0;
70945cb6 1476 lp->ref_rt = p->router_id;
c3226991
OZ
1477 lp = NULL; /* buffer might be reallocated later */
1478
70945cb6 1479 WALK_LIST(ifa, p->iface_list)
c3226991 1480 {
e4404cef 1481 if ((ifa->oa != oa) || (ifa->type == OSPF_IT_VLINK) || (ifa->state == OSPF_IS_DOWN))
c3226991
OZ
1482 continue;
1483
e7b4948c
OZ
1484 ifa->px_pos_beg = i;
1485
c3226991
OZ
1486 if ((ifa->type == OSPF_IT_BCAST) ||
1487 (ifa->type == OSPF_IT_NBMA))
1488 net_lsa = bcast_net_active(ifa);
1489 else
1490 net_lsa = 0;
1491
1492 struct ifa *a;
1493 WALK_LIST(a, ifa->iface->addrs)
70945cb6 1494 {
d3f4f92b 1495 if ((a->prefix.type != ospf_get_af(p)) ||
d44e686e 1496 (a->flags & IA_SECONDARY) ||
70945cb6
OZ
1497 (a->flags & IA_PEER) ||
1498 (a->scope <= SCOPE_LINK))
1499 continue;
3b89a232 1500
6ff81197 1501 if (((a->prefix.pxlen < max) && net_lsa) ||
70945cb6
OZ
1502 configured_stubnet(oa, a))
1503 continue;
c3226991 1504
70945cb6
OZ
1505 if ((a->flags & IA_HOST) ||
1506 (ifa->state == OSPF_IS_LOOP) ||
1507 (ifa->type == OSPF_IT_PTMP))
1508 {
6ff81197
OZ
1509 net_addr net;
1510 if (a->prefix.type == NET_IP4)
1511 net_fill_ip4(&net, ipa_to_ip4(a->ip), IP4_MAX_PREFIX_LENGTH);
1512 else
1513 net_fill_ip6(&net, ipa_to_ip6(a->ip), IP6_MAX_PREFIX_LENGTH);
1514
1515 lsab_put_prefix(p, &net, 0);
70945cb6 1516 host_addr = 1;
c3226991 1517 }
70945cb6 1518 else
d44e686e 1519 lsab_put_prefix(p, &a->prefix, ifa->cost);
70945cb6
OZ
1520 i++;
1521 }
e7b4948c
OZ
1522
1523 ifa->px_pos_end = i;
c3226991
OZ
1524 }
1525
c3226991 1526 struct ospf_stubnet_config *sn;
70945cb6
OZ
1527 WALK_LIST(sn, oa->ac->stubnet_list)
1528 if (!sn->hidden)
1529 {
d44e686e 1530 lsab_put_prefix(p, &sn->prefix, sn->cost);
6ff81197 1531 if (sn->prefix.pxlen == max)
70945cb6
OZ
1532 host_addr = 1;
1533 i++;
1534 }
e4404cef
OZ
1535
1536 /* If there are some configured vlinks, find some global address
1537 (even from another area), which will be used as a vlink endpoint. */
d3f4f92b 1538 if (!EMPTY_LIST(cf->vlink_list) && !host_addr && ospf_is_ip6(p))
e4404cef 1539 {
70945cb6 1540 WALK_LIST(ifa, p->iface_list)
e4404cef
OZ
1541 {
1542 if ((ifa->type == OSPF_IT_VLINK) || (ifa->state == OSPF_IS_DOWN))
1543 continue;
1544
1545 struct ifa *a;
1546 WALK_LIST(a, ifa->iface->addrs)
1547 {
d44e686e
OZ
1548 if ((a->prefix.type != NET_IP6) ||
1549 (a->flags & IA_SECONDARY) ||
1550 (a->scope <= SCOPE_LINK))
e4404cef
OZ
1551 continue;
1552
1553 /* Found some IP */
d44e686e
OZ
1554 net_addr_ip6 net = NET_ADDR_IP6(a->ip, IP6_MAX_PREFIX_LENGTH);
1555 lsab_put_prefix(p, (net_addr *) &net, 0);
c3226991 1556 i++;
e4404cef 1557 goto done;
c3226991 1558 }
e4404cef
OZ
1559 }
1560 }
c3226991 1561
e4404cef 1562 done:
70945cb6 1563 lp = p->lsab;
c3226991 1564 lp->pxcount = i;
c3226991
OZ
1565}
1566
70945cb6
OZ
1567static void
1568ospf_originate_prefix_rt_lsa(struct ospf_proto *p, struct ospf_area *oa)
c3226991 1569{
70945cb6
OZ
1570 if (ospf_is_v2(p))
1571 return;
c3226991 1572
70945cb6
OZ
1573 struct ospf_new_lsa lsa = {
1574 .type = LSA_T_PREFIX,
1575 .dom = oa->areaid,
1576 .id = 0
1577 };
be862406 1578
70945cb6 1579 prepare_prefix_rt_lsa_body(p, oa);
c3226991 1580
70945cb6 1581 ospf_originate_lsa(p, &lsa);
c3226991
OZ
1582}
1583
1584
70945cb6
OZ
1585/*
1586 * Prefix-Net-LSA handling (assume OSPFv3)
1587 * Type = LSA_T_PREFIX, referred type = LSA_T_NET
1588 */
1589
c3226991
OZ
1590static inline int
1591prefix_space(u32 *buf)
1592{
1593 int pxl = *buf >> 24;
1594 return IPV6_PREFIX_SPACE(pxl);
1595}
1596
1597static inline int
1598prefix_same(u32 *b1, u32 *b2)
1599{
1600 int pxl1 = *b1 >> 24;
1601 int pxl2 = *b2 >> 24;
1602 int pxs, i;
742029eb 1603
c3226991
OZ
1604 if (pxl1 != pxl2)
1605 return 0;
1606
1607 pxs = IPV6_PREFIX_WORDS(pxl1);
1608 for (i = 1; i < pxs; i++)
1609 if (b1[i] != b2[i])
1610 return 0;
1611
1612 return 1;
1613}
1614
1615static inline u32 *
1616prefix_advance(u32 *buf)
1617{
be862406
OZ
1618 int pxl = *buf >> 24;
1619 return buf + IPV6_PREFIX_WORDS(pxl);
c3226991
OZ
1620}
1621
2918e610 1622/* FIXME eliminate items with LA bit set? see 4.4.3.9 */
c3226991 1623static void
70945cb6 1624add_prefix(struct ospf_proto *p, u32 *px, int offset, int *pxc)
c3226991 1625{
70945cb6 1626 u32 *pxl = lsab_offset(p, offset);
c3226991 1627 int i;
e4404cef
OZ
1628 for (i = 0; i < *pxc; pxl = prefix_advance(pxl), i++)
1629 if (prefix_same(px, pxl))
c3226991 1630 {
e4404cef
OZ
1631 /* Options should be logically OR'ed together */
1632 *pxl |= (*px & 0x00FF0000);
1633 return;
c3226991
OZ
1634 }
1635
70945cb6 1636 ASSERT(pxl == lsab_end(p));
c3226991
OZ
1637
1638 int pxspace = prefix_space(px);
70945cb6 1639 pxl = lsab_alloc(p, pxspace);
c3226991 1640 memcpy(pxl, px, pxspace);
e4404cef 1641 *pxl &= 0xFFFF0000; /* Set metric to zero */
c3226991
OZ
1642 (*pxc)++;
1643}
1644
be862406 1645static void
70945cb6 1646add_link_lsa(struct ospf_proto *p, struct ospf_lsa_link *ll, int offset, int *pxc)
be862406 1647{
be862406 1648 u32 *pxb = ll->rest;
3e236955 1649 uint j;
be862406 1650
e4404cef
OZ
1651 for (j = 0; j < ll->pxcount; pxb = prefix_advance(pxb), j++)
1652 {
1653 u8 pxlen = (pxb[0] >> 24);
1654 u8 pxopts = (pxb[0] >> 16);
1655
1656 /* Skip NU or LA prefixes */
1657 if (pxopts & (OPT_PX_NU | OPT_PX_LA))
1658 continue;
1659
1660 /* Skip link-local prefixes */
d3f4f92b 1661 if (ospf_is_ip6(p) && (pxlen >= 10) && ((pxb[1] & 0xffc00000) == 0xfe800000))
e4404cef
OZ
1662 continue;
1663
70945cb6 1664 add_prefix(p, pxb, offset, pxc);
e4404cef 1665 }
be862406
OZ
1666}
1667
70945cb6
OZ
1668static void
1669prepare_prefix_net_lsa_body(struct ospf_proto *p, struct ospf_iface *ifa)
c3226991 1670{
c3226991 1671 struct ospf_lsa_prefix *lp;
c3226991
OZ
1672 struct ospf_neighbor *n;
1673 struct top_hash_entry *en;
be862406 1674 int pxc, offset;
c3226991 1675
70945cb6
OZ
1676 ASSERT(p->lsab_used == 0);
1677 lp = lsab_allocz(p, sizeof(struct ospf_lsa_prefix));
c3226991
OZ
1678 lp->ref_type = LSA_T_NET;
1679 lp->ref_id = ifa->net_lsa->lsa.id;
70945cb6 1680 lp->ref_rt = p->router_id;
c3226991
OZ
1681 lp = NULL; /* buffer might be reallocated later */
1682
be862406 1683 pxc = 0;
70945cb6 1684 offset = p->lsab_used;
c3226991 1685
be862406 1686 /* Find all Link LSAs associated with the link and merge their prefixes */
70945cb6
OZ
1687 if (en = ifa->link_lsa)
1688 add_link_lsa(p, en->next_lsa_body ?: en->lsa_body, offset, &pxc);
be862406 1689
c3226991
OZ
1690 WALK_LIST(n, ifa->neigh_list)
1691 if ((n->state == NEIGHBOR_FULL) &&
742029eb 1692 (en = ospf_hash_find(p->gr, ifa->iface_id, n->iface_id, n->rid, LSA_T_LINK)))
70945cb6 1693 add_link_lsa(p, en->lsa_body, offset, &pxc);
c3226991 1694
70945cb6 1695 lp = p->lsab;
be862406 1696 lp->pxcount = pxc;
c3226991
OZ
1697}
1698
70945cb6
OZ
1699static void
1700ospf_originate_prefix_net_lsa(struct ospf_proto *p, struct ospf_iface *ifa)
c3226991 1701{
70945cb6
OZ
1702 if (ospf_is_v2(p))
1703 return;
c3226991 1704
70945cb6
OZ
1705 struct ospf_new_lsa lsa = {
1706 .type = LSA_T_PREFIX,
1707 .dom = ifa->oa->areaid,
1708 .id = ifa->iface_id,
1709 .ifa = ifa
1710 };
be862406 1711
70945cb6 1712 prepare_prefix_net_lsa_body(p, ifa);
c3226991 1713
70945cb6 1714 ifa->pxn_lsa = ospf_originate_lsa(p, &lsa);
c3226991
OZ
1715}
1716
5a50a989 1717
1a2ad348
OZ
1718/*
1719 * Grace LSA handling
1720 * Type = LSA_T_GR, opaque type = LSA_OT_GR
1721 */
1722
1723static inline void
1724ospf_add_gr_period_tlv(struct ospf_proto *p, uint period)
1725{
1726 struct ospf_tlv *tlv = lsab_allocz(p, sizeof(struct ospf_tlv) + sizeof(u32));
1727 tlv->type = LSA_GR_PERIOD;
1728 tlv->length = 4;
1729 tlv->data[0] = period;
1730}
1731
1732static inline void
1733ospf_add_gr_reason_tlv(struct ospf_proto *p, uint reason)
1734{
1735 struct ospf_tlv *tlv = lsab_allocz(p, sizeof(struct ospf_tlv) + sizeof(u32));
1736 tlv->type = LSA_GR_REASON;
1737 tlv->length = 1;
1738 tlv->data[0] = reason << 24;
1739}
1740
1741static inline void
1742ospf_add_gr_address_tlv(struct ospf_proto *p, ip4_addr addr)
1743{
1744 struct ospf_tlv *tlv = lsab_allocz(p, sizeof(struct ospf_tlv) + sizeof(u32));
1745 tlv->type = LSA_GR_ADDRESS;
1746 tlv->length = 4;
1747 tlv->data[0] = ip4_to_u32(addr);
1748}
1749
1750void
1751ospf_originate_gr_lsa(struct ospf_proto *p, struct ospf_iface *ifa)
1752{
1753 struct ospf_new_lsa lsa = {
1754 .type = LSA_T_GR,
1755 .dom = ifa->iface_id,
1756 .id = ospf_is_v2(p) ? 0 : ifa->iface_id,
1757 .ifa = ifa
1758 };
1759
1760 ospf_add_gr_period_tlv(p, p->gr_time);
1761 ospf_add_gr_reason_tlv(p, 0);
1762
1763 uint t = ifa->type;
1764 if (ospf_is_v2(p) && ((t == OSPF_IT_BCAST) || (t == OSPF_IT_NBMA) || (t == OSPF_IT_PTMP)))
1765 ospf_add_gr_address_tlv(p, ipa_to_ip4(ifa->addr->ip));
1766
1767 ospf_originate_lsa(p, &lsa);
1768}
1769
1770
5a50a989
OZ
1771/*
1772 * Router Information LSA handling
1773 * Type = LSA_T_RI_AREA, opaque type = LSA_OT_RI
1774 */
1775
1776void
1777ospf_add_ric_tlv(struct ospf_proto *p)
1778{
1779 struct ospf_tlv *ri = lsab_allocz(p, sizeof(struct ospf_tlv) + sizeof(u32));
1780 ri->type = LSA_RI_RIC;
1781 ri->length = sizeof(struct ospf_tlv) + sizeof(u32);
1782
1783 BIT32R_SET(ri->data, LSA_RIC_STUB_ROUTER);
1784}
1785
1786void
1787ospf_originate_ri_lsa(struct ospf_proto *p, struct ospf_area *oa)
1788{
1789 struct ospf_new_lsa lsa = {
1790 .type = LSA_T_RI_AREA,
1791 .dom = oa->areaid,
1792 .id = p->instance_id
1793 };
1794
1795 ospf_add_ric_tlv(p);
1796
1797 ospf_originate_lsa(p, &lsa);
1798}
1799
1800
1801/*
1802 * Generic topology code
1803 */
1804
a7a7372a 1805static inline int breaks_minlsinterval(struct top_hash_entry *en)
b32d557a 1806{ return en && (en->lsa.age < LSA_MAXAGE) && (lsa_inst_age(en) < MINLSINTERVAL); }
70945cb6 1807
061ab802 1808void
70945cb6 1809ospf_update_topology(struct ospf_proto *p)
061ab802 1810{
70945cb6
OZ
1811 struct ospf_area *oa;
1812 struct ospf_iface *ifa;
061ab802 1813
1a2ad348
OZ
1814 /* No LSA reorigination during GR recovery */
1815 if (p->gr_recovery)
1816 return;
1817
70945cb6
OZ
1818 WALK_LIST(oa, p->area_list)
1819 {
1820 if (oa->update_rt_lsa)
1821 {
a7a7372a
OZ
1822 /*
1823 * Generally, MinLSInterval is enforced in ospf_do_originate_lsa(), but
1824 * origination of (prefix) router LSA is a special case. We do not want to
1825 * prepare a new router LSA body and then postpone it in en->next_lsa_body
1826 * for later origination, because there are side effects (updates of
1827 * rt_pos_* and px_pos_* in ospf_iface structures) during that, which may
1828 * confuse routing table calculation if executed after LSA body
1829 * preparation but before final LSA origination (as rtcalc would use
1830 * current rt_pos_* indexes but the old router LSA body).
1831 *
1832 * Here, we ensure that MinLSInterval is observed and we do not even try
1833 * to originate these LSAs if it is not. Therefore, origination, when
1834 * requested, will succeed unless there is also a seqnum wrapping, which
1835 * is not a problem because in that case rtcalc is blocked by MaxAge.
1836 */
1837
1838 if (breaks_minlsinterval(oa->rt) || breaks_minlsinterval(oa->pxr_lsa))
1839 continue;
1840
70945cb6
OZ
1841 ospf_originate_rt_lsa(p, oa);
1842 ospf_originate_prefix_rt_lsa(p, oa);
1e958e52 1843 // ospf_originate_ri_lsa(p, oa);
70945cb6
OZ
1844 oa->update_rt_lsa = 0;
1845 }
1846 }
061ab802 1847
70945cb6
OZ
1848 WALK_LIST(ifa, p->iface_list)
1849 {
1850 if (ifa->type == OSPF_IT_VLINK)
1851 continue;
be862406 1852
70945cb6
OZ
1853 if (ifa->update_link_lsa)
1854 {
1855 if ((ifa->state > OSPF_IS_LOOP) && !ifa->link_lsa_suppression)
1856 ospf_originate_link_lsa(p, ifa);
1857 else
1858 ospf_flush2_lsa(p, &ifa->link_lsa);
061ab802 1859
70945cb6
OZ
1860 ifa->update_link_lsa = 0;
1861 }
061ab802 1862
70945cb6
OZ
1863 if (ifa->update_net_lsa)
1864 {
1865 if ((ifa->state == OSPF_IS_DR) && (ifa->fadj > 0))
1866 {
1867 ospf_originate_net_lsa(p, ifa);
1868 ospf_originate_prefix_net_lsa(p, ifa);
1869 }
1870 else
1871 {
1872 ospf_flush2_lsa(p, &ifa->net_lsa);
1873 ospf_flush2_lsa(p, &ifa->pxn_lsa);
1874 }
1875
1876 ifa->update_net_lsa = 0;
1877 }
1878 }
70945cb6 1879}
e8085aba 1880
b49e6f5a 1881
6ba36f06
MM
1882static void
1883ospf_top_ht_alloc(struct top_graph *f)
1884{
1885 f->hash_size = 1 << f->hash_order;
1886 f->hash_mask = f->hash_size - 1;
1887 if (f->hash_order > HASH_HI_MAX - HASH_HI_STEP)
1888 f->hash_entries_max = ~0;
1889 else
1890 f->hash_entries_max = f->hash_size HASH_HI_MARK;
1891 if (f->hash_order < HASH_LO_MIN + HASH_LO_STEP)
1892 f->hash_entries_min = 0;
1893 else
1894 f->hash_entries_min = f->hash_size HASH_LO_MARK;
1895 DBG("Allocating OSPF hash of order %d: %d hash_entries, %d low, %d high\n",
1896 f->hash_order, f->hash_size, f->hash_entries_min, f->hash_entries_max);
b9ed99f7
OF
1897 f->hash_table =
1898 mb_alloc(f->pool, f->hash_size * sizeof(struct top_hash_entry *));
6ba36f06
MM
1899 bzero(f->hash_table, f->hash_size * sizeof(struct top_hash_entry *));
1900}
1901
1902static inline void
1903ospf_top_ht_free(struct top_hash_entry **h)
1904{
1905 mb_free(h);
1906}
1907
1908static inline u32
1909ospf_top_hash_u32(u32 a)
1910{
1911 /* Shamelessly stolen from IP address hashing in ipv4.h */
1912 a ^= a >> 16;
1913 a ^= a << 10;
1914 return a;
1915}
1916
a7a7372a 1917static uint
c3226991
OZ
1918ospf_top_hash(struct top_graph *f, u32 domain, u32 lsaid, u32 rtrid, u32 type)
1919{
be862406 1920 /* In OSPFv2, we don't know Router ID when looking for network LSAs.
9f0ba7b1
OZ
1921 In OSPFv3, we don't know LSA ID when looking for router LSAs.
1922 In both cases, there is (usually) just one (or small number)
1923 appropriate LSA, so we just clear unknown part of key. */
c3226991 1924
70945cb6
OZ
1925 return (((f->ospf2 && (type == LSA_T_NET)) ? 0 : ospf_top_hash_u32(rtrid)) +
1926 ((!f->ospf2 && (type == LSA_T_RT)) ? 0 : ospf_top_hash_u32(lsaid)) +
9f0ba7b1 1927 type + domain) & f->hash_mask;
c3226991
OZ
1928
1929 /*
b9ed99f7 1930 return (ospf_top_hash_u32(lsaid) + ospf_top_hash_u32(rtrid) +
86c84d76 1931 type + areaid) & f->hash_mask;
c3226991 1932 */
6ba36f06
MM
1933}
1934
7ab3ff6a
OF
1935/**
1936 * ospf_top_new - allocated new topology database
70945cb6 1937 * @p: OSPF protocol instance
a7a7372a 1938 * @pool: pool for allocation
7ab3ff6a 1939 *
a7a7372a
OZ
1940 * This dynamically hashed structure is used for keeping LSAs. Mainly it is used
1941 * for the LSA database of the OSPF protocol, but also for LSA retransmission
1942 * and request lists of OSPF neighbors.
7ab3ff6a 1943 */
6ba36f06 1944struct top_graph *
a7a7372a 1945ospf_top_new(struct ospf_proto *p, pool *pool)
6ba36f06
MM
1946{
1947 struct top_graph *f;
1948
035f6acb
OF
1949 f = mb_allocz(pool, sizeof(struct top_graph));
1950 f->pool = pool;
6ba36f06
MM
1951 f->hash_slab = sl_new(f->pool, sizeof(struct top_hash_entry));
1952 f->hash_order = HASH_DEF_ORDER;
1953 ospf_top_ht_alloc(f);
1954 f->hash_entries = 0;
1955 f->hash_entries_min = 0;
a7a7372a 1956 f->ospf2 = ospf_is_v2(p);
6ba36f06
MM
1957 return f;
1958}
1959
1960void
1961ospf_top_free(struct top_graph *f)
1962{
1963 rfree(f->hash_slab);
1964 ospf_top_ht_free(f->hash_table);
1965 mb_free(f);
1966}
1967
1968static void
1969ospf_top_rehash(struct top_graph *f, int step)
1970{
6ba36f06 1971 struct top_hash_entry **n, **oldt, **newt, *e, *x;
a7a7372a 1972 uint oldn, oldh;
6ba36f06
MM
1973
1974 oldn = f->hash_size;
1975 oldt = f->hash_table;
b49e6f5a 1976 DBG("re-hashing topology hash from order %d to %d\n", f->hash_order,
b9ed99f7 1977 f->hash_order + step);
6ba36f06
MM
1978 f->hash_order += step;
1979 ospf_top_ht_alloc(f);
1980 newt = f->hash_table;
1981
b9ed99f7
OF
1982 for (oldh = 0; oldh < oldn; oldh++)
1983 {
1984 e = oldt[oldh];
1985 while (e)
6ba36f06 1986 {
b9ed99f7 1987 x = e->next;
70945cb6 1988 n = newt + ospf_top_hash(f, e->domain, e->lsa.id, e->lsa.rt, e->lsa_type);
b9ed99f7
OF
1989 e->next = *n;
1990 *n = e;
1991 e = x;
6ba36f06 1992 }
b9ed99f7 1993 }
6ba36f06
MM
1994 ospf_top_ht_free(oldt);
1995}
1996
6f8bbaa1
OZ
1997static struct top_hash_entry *
1998ospf_hash_find_(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
6ba36f06 1999{
86c84d76 2000 struct top_hash_entry *e;
c3226991 2001 e = f->hash_table[ospf_top_hash(f, domain, lsa, rtr, type)];
86c84d76 2002
70945cb6
OZ
2003 while (e && (e->lsa.id != lsa || e->lsa.rt != rtr ||
2004 e->lsa_type != type || e->domain != domain))
9f0ba7b1
OZ
2005 e = e->next;
2006
6f8bbaa1
OZ
2007 return e;
2008}
2009
2010struct top_hash_entry *
2011ospf_hash_find(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
2012{
2013 struct top_hash_entry *e = ospf_hash_find_(f, domain, lsa, rtr, type);
2014
70945cb6 2015 /* Hide hash entry with empty lsa_body */
a7a7372a 2016 return (e && e->lsa_body) ? e : NULL;
9f0ba7b1 2017}
86c84d76 2018
70945cb6
OZ
2019/* In OSPFv2, lsa.id is the same as lsa.rt for router LSA. In OSPFv3, we don't know
2020 lsa.id when looking for router LSAs. We return matching LSA with smallest lsa.id. */
9f0ba7b1
OZ
2021struct top_hash_entry *
2022ospf_hash_find_rt(struct top_graph *f, u32 domain, u32 rtr)
2023{
2024 struct top_hash_entry *rv = NULL;
2025 struct top_hash_entry *e;
70945cb6
OZ
2026 /* We can put rtr for lsa.id to hash fn, it is ignored in OSPFv3 */
2027 e = f->hash_table[ospf_top_hash(f, domain, rtr, rtr, LSA_T_RT)];
2028
9f0ba7b1 2029 while (e)
70945cb6
OZ
2030 {
2031 if (e->lsa.rt == rtr && e->lsa_type == LSA_T_RT && e->domain == domain && e->lsa_body)
9f0ba7b1 2032 {
70945cb6
OZ
2033 if (f->ospf2 && (e->lsa.id == rtr))
2034 return e;
2035 if (!f->ospf2 && (!rv || e->lsa.id < rv->lsa.id))
2036 rv = e;
9f0ba7b1 2037 }
70945cb6
OZ
2038 e = e->next;
2039 }
9f0ba7b1
OZ
2040
2041 return rv;
2042}
2043
a7a7372a
OZ
2044/*
2045 * ospf_hash_find_rt3_first() and ospf_hash_find_rt3_next() are used exclusively
2046 * for lsa_walk_rt_init(), lsa_walk_rt(), therefore they skip MaxAge entries.
2047 */
9f0ba7b1 2048static inline struct top_hash_entry *
70945cb6 2049find_matching_rt3(struct top_hash_entry *e, u32 domain, u32 rtr)
9f0ba7b1 2050{
70945cb6 2051 while (e && (e->lsa.rt != rtr || e->lsa_type != LSA_T_RT ||
a7a7372a 2052 e->domain != domain || e->lsa.age == LSA_MAXAGE))
9f0ba7b1 2053 e = e->next;
6ba36f06
MM
2054 return e;
2055}
2056
9f0ba7b1 2057struct top_hash_entry *
70945cb6 2058ospf_hash_find_rt3_first(struct top_graph *f, u32 domain, u32 rtr)
9f0ba7b1
OZ
2059{
2060 struct top_hash_entry *e;
2061 e = f->hash_table[ospf_top_hash(f, domain, 0, rtr, LSA_T_RT)];
70945cb6 2062 return find_matching_rt3(e, domain, rtr);
9f0ba7b1
OZ
2063}
2064
2065struct top_hash_entry *
70945cb6 2066ospf_hash_find_rt3_next(struct top_hash_entry *e)
9f0ba7b1 2067{
70945cb6 2068 return find_matching_rt3(e->next, e->domain, e->lsa.rt);
9f0ba7b1
OZ
2069}
2070
70945cb6
OZ
2071/* In OSPFv2, we don't know Router ID when looking for network LSAs.
2072 There should be just one, so we find any match. */
2073struct top_hash_entry *
2074ospf_hash_find_net2(struct top_graph *f, u32 domain, u32 id)
2075{
2076 struct top_hash_entry *e;
2077 e = f->hash_table[ospf_top_hash(f, domain, id, 0, LSA_T_NET)];
2078
2079 while (e && (e->lsa.id != id || e->lsa_type != LSA_T_NET ||
2080 e->domain != domain || e->lsa_body == NULL))
2081 e = e->next;
2082
2083 return e;
2084}
9f0ba7b1
OZ
2085
2086
6ba36f06 2087struct top_hash_entry *
b49e6f5a 2088ospf_hash_get(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
6ba36f06 2089{
86c84d76
OF
2090 struct top_hash_entry **ee;
2091 struct top_hash_entry *e;
86c84d76 2092
c3226991 2093 ee = f->hash_table + ospf_top_hash(f, domain, lsa, rtr, type);
86c84d76
OF
2094 e = *ee;
2095
742029eb 2096 while (e && (e->lsa.id != lsa || e->lsa.rt != rtr ||
70945cb6 2097 e->lsa_type != type || e->domain != domain))
c3226991 2098 e = e->next;
6ba36f06 2099
6ba36f06
MM
2100 if (e)
2101 return e;
933bfdde 2102
6ba36f06 2103 e = sl_alloc(f->hash_slab);
70945cb6
OZ
2104 bzero(e, sizeof(struct top_hash_entry));
2105
933bfdde
OF
2106 e->color = OUTSPF;
2107 e->dist = LSINFINITY;
70945cb6 2108 e->lsa.type_raw = type;
ce17d4c1
OF
2109 e->lsa.id = lsa;
2110 e->lsa.rt = rtr;
70945cb6
OZ
2111 e->lsa.sn = LSA_ZEROSEQNO;
2112 e->lsa_type = type;
c3226991 2113 e->domain = domain;
933bfdde 2114 e->next = *ee;
b9ed99f7 2115 *ee = e;
6ba36f06
MM
2116 if (f->hash_entries++ > f->hash_entries_max)
2117 ospf_top_rehash(f, HASH_HI_STEP);
2118 return e;
2119}
2120
2121void
2122ospf_hash_delete(struct top_graph *f, struct top_hash_entry *e)
2123{
742029eb 2124 struct top_hash_entry **ee = f->hash_table +
70945cb6 2125 ospf_top_hash(f, e->domain, e->lsa.id, e->lsa.rt, e->lsa_type);
6ba36f06
MM
2126
2127 while (*ee)
b9ed99f7
OF
2128 {
2129 if (*ee == e)
6ba36f06 2130 {
b9ed99f7
OF
2131 *ee = e->next;
2132 sl_free(f->hash_slab, e);
2133 if (f->hash_entries-- < f->hash_entries_min)
2134 ospf_top_rehash(f, -HASH_LO_STEP);
2135 return;
6ba36f06 2136 }
b9ed99f7
OF
2137 ee = &((*ee)->next);
2138 }
6ba36f06
MM
2139 bug("ospf_hash_delete() called for invalid node");
2140}
2141
e81b440f 2142/*
226cb2bc
OF
2143static void
2144ospf_dump_lsa(struct top_hash_entry *he, struct proto *p)
2145{
e81b440f 2146
226cb2bc
OF
2147 struct ospf_lsa_rt *rt = NULL;
2148 struct ospf_lsa_rt_link *rr = NULL;
2149 struct ospf_lsa_net *ln = NULL;
2150 u32 *rts = NULL;
2151 u32 i, max;
2152
3aab39f5
OZ
2153 OSPF_TRACE(D_EVENTS, "- %1x %-1R %-1R %4u 0x%08x 0x%04x %-1R",
2154 he->lsa.type, he->lsa.id, he->lsa.rt, he->lsa.age, he->lsa.sn,
c3226991 2155 he->lsa.checksum, he->domain);
226cb2bc 2156
b49e6f5a 2157
226cb2bc
OF
2158 switch (he->lsa.type)
2159 {
2160 case LSA_T_RT:
2161 rt = he->lsa_body;
2162 rr = (struct ospf_lsa_rt_link *) (rt + 1);
2163
c3226991 2164 for (i = 0; i < lsa_rt_items(&he->lsa); i++)
742029eb 2165 OSPF_TRACE(D_EVENTS, " - %1x %-1R %-1R %5u",
3aab39f5 2166 rr[i].type, rr[i].id, rr[i].data, rr[i].metric);
226cb2bc
OF
2167 break;
2168
2169 case LSA_T_NET:
2170 ln = he->lsa_body;
2171 rts = (u32 *) (ln + 1);
226cb2bc 2172
c3226991 2173 for (i = 0; i < lsa_net_items(&he->lsa); i++)
742029eb 2174 OSPF_TRACE(D_EVENTS, " - %-1R", rts[i]);
226cb2bc
OF
2175 break;
2176
2177 default:
2178 break;
2179 }
2180}
2181
6ba36f06 2182void
992705f6 2183ospf_top_dump(struct top_graph *f, struct proto *p)
6ba36f06 2184{
a7a7372a 2185 uint i;
992705f6 2186 OSPF_TRACE(D_EVENTS, "Hash entries: %d", f->hash_entries);
6ba36f06 2187
b9ed99f7
OF
2188 for (i = 0; i < f->hash_size; i++)
2189 {
226cb2bc
OF
2190 struct top_hash_entry *e;
2191 for (e = f->hash_table[i]; e != NULL; e = e->next)
2192 ospf_dump_lsa(e, p);
b9ed99f7 2193 }
6ba36f06 2194}
e81b440f 2195*/