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