]>
git.ipfire.org Git - thirdparty/bird.git/blob - proto/ospf/lsupd.c
72861bd533681256bb6c8a1cf919297a6705434e
4 * (c) 2000--2004 Ondrej Filip <feela@network.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
12 struct ospf_lsupd_packet
14 struct ospf_packet ospf_packet
;
15 u32 lsano
; /* Number of LSA's */
19 void ospf_dump_lsahdr(struct proto
*p
, struct ospf_lsa_header
*lsa_n
)
21 struct ospf_lsa_header lsa
;
22 ntohlsah(lsa_n
, &lsa
);
24 log(L_TRACE
"%s: LSA Id: %R, Rt: %R, Type: %u, Age: %u, Seqno: 0x%08x, Sum: %u",
25 p
->name
, lsa
.id
, lsa
.rt
, lsa
.type
, lsa
.age
, lsa
.sn
, lsa
.checksum
);
28 void ospf_dump_common(struct proto
*p
, struct ospf_packet
*op
)
30 log(L_TRACE
"%s: length %d", p
->name
, ntohs(op
->length
));
31 log(L_TRACE
"%s: router %R", p
->name
, ntohl(op
->routerid
));
34 static void ospf_dump_lsupd(struct proto
*p
, struct ospf_lsupd_packet
*pkt
)
36 struct ospf_packet
*op
= &pkt
->ospf_packet
;
38 ASSERT(op
->type
== LSUPD_P
);
39 ospf_dump_common(p
, op
);
42 int offset
= sizeof(struct ospf_lsupd_packet
);
43 int bound
= ntohs(op
->length
) - sizeof(struct ospf_lsa_header
);
46 j
= ntohl(pkt
->lsano
);
47 for (i
= 0; i
< j
; i
++)
51 log(L_TRACE
"%s: LSA invalid", p
->name
);
55 struct ospf_lsa_header
*lsa
= (void *) (pbuf
+ offset
);
56 ospf_dump_lsahdr(p
, lsa
);
57 offset
+= ntohs(lsa
->length
);
65 ospf_lsa_flooding_allowed(struct ospf_lsa_header
*lsa
, u32 domain
, struct ospf_iface
*ifa
)
67 if (lsa
->type
== LSA_T_EXT
)
69 if (ifa
->type
== OSPF_IT_VLINK
)
76 return ifa
->oa
->areaid
== domain
;
82 unknown_lsa_type(struct ospf_lsa_header
*lsa
)
101 ospf_lsa_flooding_allowed(struct ospf_lsa_header
*lsa
, u32 domain
, struct ospf_iface
*ifa
)
103 u32 scope
= LSA_SCOPE(lsa
);
106 if (unknown_lsa_type(lsa
) && !(lsa
->type
& LSA_UBIT
))
107 scope
= LSA_SCOPE_LINK
;
112 return ifa
->iface
->index
== domain
;
115 return ifa
->oa
->areaid
== domain
;
118 if (ifa
->type
== OSPF_IT_VLINK
)
125 log(L_ERR
"LSA with invalid scope");
133 * ospf_lsupd_flood - send received or generated lsa to the neighbors
135 * @n: neighbor than sent this lsa (or NULL if generated)
136 * @hn: LSA header followed by lsa body in network endianity (may be NULL)
137 * @hh: LSA header in host endianity (must be filled)
138 * @domain: domain of LSA (must be filled)
139 * @rtl: add this LSA into retransmission list
142 * return value - was the LSA flooded back?
146 ospf_lsupd_flood(struct proto_ospf
*po
,
147 struct ospf_neighbor
*n
, struct ospf_lsa_header
*hn
,
148 struct ospf_lsa_header
*hh
, u32 domain
, int rtl
)
150 struct ospf_iface
*ifa
;
151 struct ospf_neighbor
*nn
;
152 struct top_hash_entry
*en
;
153 struct proto
*p
= &po
->proto
;
157 WALK_LIST(ifa
, po
->iface_list
)
162 if (! ospf_lsa_flooding_allowed(hh
, domain
, ifa
))
165 DBG("Wanted to flood LSA: Type: %u, ID: %R, RT: %R, SN: 0x%x, Age %u\n",
166 hh
->type
, hh
->id
, hh
->rt
, hh
->sn
, hh
->age
);
169 WALK_LIST(nn
, ifa
->neigh_list
)
172 if (nn
->state
< NEIGHBOR_EXCHANGE
)
176 if (nn
->state
< NEIGHBOR_FULL
)
178 if ((en
= ospf_hash_find_header(nn
->lsrqh
, domain
, hh
)) != NULL
)
180 DBG("That LSA found in lsreq list for neigh %R\n", nn
->rid
);
182 switch (lsa_comp(hh
, &en
->lsa
))
188 s_rem_node(SNODE en
);
189 if (en
->lsa_body
!= NULL
)
190 mb_free(en
->lsa_body
);
192 DBG("Removing from lsreq list for neigh %R\n", nn
->rid
);
193 ospf_hash_delete(nn
->lsrqh
, en
);
194 if (EMPTY_SLIST(nn
->lsrql
))
195 ospf_neigh_sm(nn
, INM_LOADDONE
);
199 s_rem_node(SNODE en
);
200 if (en
->lsa_body
!= NULL
)
201 mb_free(en
->lsa_body
);
203 DBG("Removing from lsreq list for neigh %R\n", nn
->rid
);
204 ospf_hash_delete(nn
->lsrqh
, en
);
205 if (EMPTY_SLIST(nn
->lsrql
))
206 ospf_neigh_sm(nn
, INM_LOADDONE
);
209 bug("Bug in lsa_comp?");
221 /* In OSPFv3, there should be check whether receiving router understand
222 that type of LSA (for LSA types with U-bit == 0). But as we does not support
223 any optional LSA types, this is not needed yet */
225 if ((en
= ospf_hash_find_header(nn
->lsrth
, domain
, hh
)) == NULL
)
227 en
= ospf_hash_get_header(nn
->lsrth
, domain
, hh
);
231 s_rem_node(SNODE en
);
233 s_add_tail(&nn
->lsrtl
, SNODE en
);
234 memcpy(&en
->lsa
, hh
, sizeof(struct ospf_lsa_header
));
235 DBG("Adding that LSA for flood to %I\n", nn
->ip
);
239 if ((en
= ospf_hash_find_header(nn
->lsrth
, domain
, hh
)) != NULL
)
241 s_rem_node(SNODE en
);
242 if (en
->lsa_body
!= NULL
)
243 mb_free(en
->lsa_body
);
245 ospf_hash_delete(nn
->lsrth
, en
);
253 continue; /* pg 150 (2) */
255 if (n
&& (n
->ifa
== ifa
))
257 if ((n
->rid
== ifa
->drid
) || n
->rid
== ifa
->bdrid
)
258 continue; /* pg 150 (3) */
259 if (ifa
->state
== OSPF_IS_BACKUP
)
260 continue; /* pg 150 (4) */
267 struct ospf_lsupd_packet
*pk
;
268 struct ospf_packet
*op
;
269 struct ospf_lsa_header
*lh
;
271 if ((ifa
->type
== OSPF_IT_NBMA
) || (ifa
->type
== OSPF_IT_VLINK
))
276 pk
= (struct ospf_lsupd_packet
*) sk
->tbuf
;
277 op
= (struct ospf_packet
*) sk
->tbuf
;
279 ospf_pkt_fill_hdr(ifa
, pk
, LSUPD_P
);
280 pk
->lsano
= htonl(1);
282 lh
= (struct ospf_lsa_header
*) (pk
+ 1);
284 /* Copy LSA into the packet */
287 memcpy(lh
, hn
, ntohs(hn
->length
));
292 struct top_hash_entry
*en
;
295 help
= (u8
*) (lh
+ 1);
296 en
= ospf_hash_find_header(po
->gr
, domain
, hh
);
297 htonlsab(en
->lsa_body
, help
, hh
->type
, hh
->length
298 - sizeof(struct ospf_lsa_header
));
301 len
= sizeof(struct ospf_lsupd_packet
) + ntohs(lh
->length
);
303 age
= ntohs(lh
->age
);
304 age
+= ifa
->inftransdelay
;
305 if (age
> LSA_MAXAGE
)
307 lh
->age
= htons(age
);
309 op
->length
= htons(len
);
311 OSPF_PACKET(ospf_dump_lsupd
, (struct ospf_lsupd_packet
*) sk
->tbuf
,
312 "LSUPD packet flooded via %s", ifa
->iface
->name
);
317 if ((ifa
->state
== OSPF_IS_BACKUP
) || (ifa
->state
== OSPF_IS_DR
))
318 ospf_send_to_agt(sk
, ifa
, NEIGHBOR_EXCHANGE
);
320 ospf_send_to_bdr(sk
, ifa
);
324 ospf_send_to(sk
, ifa
->vip
, ifa
);
328 if ((ifa
->state
== OSPF_IS_BACKUP
) || (ifa
->state
== OSPF_IS_DR
) ||
329 (ifa
->type
== OSPF_IT_PTP
))
330 ospf_send_to(sk
, AllSPFRouters
, ifa
);
332 ospf_send_to(sk
, AllDRouters
, ifa
);
339 void /* I send all I received in LSREQ */
340 ospf_lsupd_send_list(struct ospf_neighbor
*n
, list
* l
)
342 struct l_lsr_head
*llsh
;
345 struct top_hash_entry
*en
;
346 struct ospf_lsupd_packet
*pk
;
347 struct ospf_packet
*op
;
348 struct ospf_area
*oa
= n
->ifa
->oa
;
349 struct proto_ospf
*po
= oa
->po
;
350 struct proto
*p
= &po
->proto
;
356 pk
= (struct ospf_lsupd_packet
*) n
->ifa
->ip_sk
->tbuf
;
357 op
= (struct ospf_packet
*) n
->ifa
->ip_sk
->tbuf
;
359 DBG("LSupd: 1st packet\n");
361 ospf_pkt_fill_hdr(n
->ifa
, pk
, LSUPD_P
);
362 len
= sizeof(struct ospf_lsupd_packet
);
368 u32 domain
= ospf_lsa_domain(llsh
->lsh
.type
, n
->ifa
);
369 if ((en
= ospf_hash_find(po
->gr
, domain
, llsh
->lsh
.id
,
370 llsh
->lsh
.rt
, llsh
->lsh
.type
)) == NULL
)
371 continue; /* Probably flushed LSA */
372 /* FIXME This is a bug! I cannot flush LSA that is in lsrt */
374 DBG("Sending LSA: Type=%u, ID=%R, RT=%R, SN: 0x%x, Age: %u\n",
375 llsh
->lsh
.type
, llsh
->lsh
.id
, llsh
->lsh
.rt
, en
->lsa
.sn
, en
->lsa
.age
);
376 if (((u32
) (len
+ en
->lsa
.length
)) > ospf_pkt_maxsize(n
->ifa
))
378 pk
->lsano
= htonl(lsano
);
379 op
->length
= htons(len
);
381 OSPF_PACKET(ospf_dump_lsupd
, (struct ospf_lsupd_packet
*) n
->ifa
->ip_sk
->tbuf
,
382 "LSUPD packet sent to %I via %s", n
->ip
, n
->ifa
->iface
->name
);
383 ospf_send_to(n
->ifa
->ip_sk
, n
->ip
, n
->ifa
);
385 DBG("LSupd: next packet\n");
386 ospf_pkt_fill_hdr(n
->ifa
, pk
, LSUPD_P
);
387 len
= sizeof(struct ospf_lsupd_packet
);
391 htonlsah(&(en
->lsa
), pktpos
);
392 pktpos
= pktpos
+ sizeof(struct ospf_lsa_header
);
393 htonlsab(en
->lsa_body
, pktpos
, en
->lsa
.type
, en
->lsa
.length
394 - sizeof(struct ospf_lsa_header
));
395 pktpos
= pktpos
+ en
->lsa
.length
- sizeof(struct ospf_lsa_header
);
396 len
+= en
->lsa
.length
;
401 pk
->lsano
= htonl(lsano
);
402 op
->length
= htons(len
);
404 OSPF_PACKET(ospf_dump_lsupd
, (struct ospf_lsupd_packet
*) n
->ifa
->ip_sk
->tbuf
,
405 "LSUPD packet sent to %I via %s", n
->ip
, n
->ifa
->iface
->name
);
406 ospf_send_to(n
->ifa
->ip_sk
, n
->ip
, n
->ifa
);
411 ospf_lsupd_receive(struct ospf_packet
*ps_i
, struct ospf_iface
*ifa
,
412 struct ospf_neighbor
*n
)
414 struct ospf_lsupd_packet
*ps
= (void *) ps_i
;
415 struct ospf_neighbor
*ntmp
;
416 struct ospf_lsa_header
*lsa
;
417 struct proto_ospf
*po
= ifa
->oa
->po
;
418 struct proto
*p
= &po
->proto
;
419 unsigned int i
, sendreq
= 1, size
= ntohs(ps
->ospf_packet
.length
);
421 OSPF_PACKET(ospf_dump_lsupd
, ps
, "LSUPD packet received from %I via %s", n
->ip
, ifa
->iface
->name
);
423 if (n
->state
< NEIGHBOR_EXCHANGE
)
425 OSPF_TRACE(D_PACKETS
, "Received lsupd in lesser state than EXCHANGE from (%I)", n
->ip
);
430 (sizeof(struct ospf_lsupd_packet
) + sizeof(struct ospf_lsa_header
)))
432 log(L_WARN
"Received lsupd from %I is too short!", n
->ip
);
436 ospf_neigh_sm(n
, INM_HELLOREC
); /* Questionable */
438 lsa
= (struct ospf_lsa_header
*) (ps
+ 1);
440 for (i
= 0; i
< ntohl(ps
->lsano
); i
++,
441 lsa
= (struct ospf_lsa_header
*) (((u8
*) lsa
) + ntohs(lsa
->length
)))
443 struct ospf_lsa_header lsatmp
;
444 struct top_hash_entry
*lsadb
;
445 unsigned diff
= ((u8
*) lsa
) - ((u8
*) ps
), lenn
= ntohs(lsa
->length
);
448 if (((diff
+ sizeof(struct ospf_lsa_header
)) >= size
)
449 || ((lenn
+ diff
) > size
))
451 log(L_WARN
"Received lsupd from %I is too short!", n
->ip
);
452 ospf_neigh_sm(n
, INM_BADLSREQ
);
456 if ((lenn
<= sizeof(struct ospf_lsa_header
))
457 || (lenn
!= (4 * (lenn
/ 4))))
459 log(L_WARN
"Received LSA from %I with bad length", n
->ip
);
460 ospf_neigh_sm(n
, INM_BADLSREQ
);
465 chsum
= lsa
->checksum
;
466 log(L_WARN
"Checking rcv %R %R %d (len %d)", ntohl(lsa
->id
), ntohl(lsa
->rt
), ntoht(lsa
->type
), ntohs(lsa
->length
));
467 buf_dump("RCV", lsa
, ntohs(lsa
->length
));
468 if (chsum
!= lsasum_check(lsa
, NULL
))
470 log(L_WARN
"Received bad lsa checksum from %I: %x %x", n
->ip
, chsum
, lsa
->checksum
);
477 if ((lsa
->type
< LSA_T_RT
) || (lsa
->type
> LSA_T_EXT
))
479 log(L_WARN
"Unknown LSA type from %I", n
->ip
);
484 if ((lsa
->type
== LSA_T_EXT
) && ifa
->oa
->stub
)
486 log(L_WARN
"Received External LSA in stub area from %I", n
->ip
);
491 if ((LSA_SCOPE(lsa
) == LSA_SCOPE_AS
) && ifa
->oa
->stub
)
493 log(L_WARN
"Received LSA with AS scope in stub area from %I", n
->ip
);
498 if ((LSA_SCOPE(lsa
) == LSA_SCOPE_RES
))
500 log(L_WARN
"Received LSA with invalid scope from %I", n
->ip
);
505 ntohlsah(lsa
, &lsatmp
);
507 DBG("Update Type: %u ID: %R RT: %R, Sn: 0x%08x Age: %u, Sum: %u\n",
508 lsatmp
.type
, lsatmp
.id
, lsatmp
.rt
, lsatmp
.sn
, lsatmp
.age
, lsatmp
.checksum
);
510 u32 domain
= ospf_lsa_domain(lsatmp
.type
, ifa
);
511 lsadb
= ospf_hash_find_header(po
->gr
, domain
, &lsatmp
);
515 DBG("I have Type: %u ID: %R RT: %R, Sn: 0x%08x Age: %u, Sum: %u\n",
516 lsadb
->lsa
.type
, lsadb
->lsa
.id
, lsadb
->lsa
.rt
,
517 lsadb
->lsa
.sn
, lsadb
->lsa
.age
, lsadb
->lsa
.checksum
);
521 if ((lsatmp
.age
== LSA_MAXAGE
) && (lsadb
== NULL
) && can_flush_lsa(po
))
523 ospf_lsack_enqueue(n
, lsa
, ACKL_DIRECT
);
528 if ((lsadb
== NULL
) || (lsa_comp(&lsatmp
, &lsadb
->lsa
) == CMP_NEWER
))
530 struct ospf_iface
*ift
= NULL
;
532 int self
= (lsatmp
.rt
== p
->cf
->global
->router_id
);
534 DBG("PG143(5): Received LSA is newer\n");
537 /* 13.4 - check self-originated LSAs of NET type */
538 if ((!self
) && (lsatmp
.type
== LSA_T_NET
))
540 struct ospf_iface
*nifa
;
541 WALK_LIST(nifa
, po
->iface_list
)
545 if (ipa_equal(nifa
->iface
->addr
->ip
, ipa_from_u32(lsatmp
.id
)))
554 /* pg 145 (5f) - premature aging of self originated lsa */
557 struct top_hash_entry
*en
;
559 if ((lsatmp
.age
== LSA_MAXAGE
) && (lsatmp
.sn
== LSA_MAXSEQNO
))
561 ospf_lsack_enqueue(n
, lsa
, ACKL_DIRECT
);
565 lsatmp
.age
= LSA_MAXAGE
;
566 lsatmp
.sn
= LSA_MAXSEQNO
;
567 lsa
->age
= htons(LSA_MAXAGE
);
568 lsa
->sn
= htonl(LSA_MAXSEQNO
);
569 OSPF_TRACE(D_EVENTS
, "Premature aging self originated lsa.");
570 OSPF_TRACE(D_EVENTS
, "Type: %d, Id: %R, Rt: %R",
571 lsatmp
.type
, lsatmp
.id
, lsatmp
.rt
);
572 lsasum_check(lsa
, (lsa
+ 1)); /* It also calculates chsum! */
573 lsatmp
.checksum
= ntohs(lsa
->checksum
);
574 ospf_lsupd_flood(po
, NULL
, lsa
, &lsatmp
, domain
, 0);
575 if (en
= ospf_hash_find_header(po
->gr
, domain
, &lsatmp
))
576 { /* FIXME verify hacks */
577 ospf_lsupd_flood(po
, NULL
, NULL
, &en
->lsa
, domain
, 1);
583 if (lsadb
&& ((now
- lsadb
->inst_t
) <= MINLSARRIVAL
)) /* FIXME: test for flooding? */
585 DBG("I got it in less that MINLSARRIVAL\n");
590 if (ospf_lsupd_flood(po
, n
, lsa
, &lsatmp
, domain
, 1) == 0)
592 DBG("Wasn't flooded back\n"); /* ps 144(5e), pg 153 */
593 if (ifa
->state
== OSPF_IS_BACKUP
)
595 if (ifa
->drid
== n
->rid
)
596 ospf_lsack_enqueue(n
, lsa
, ACKL_DELAY
);
599 ospf_lsack_enqueue(n
, lsa
, ACKL_DELAY
);
602 /* Remove old from all ret lists */
605 WALK_LIST(ift
, po
->iface_list
)
606 WALK_LIST(ntmp
, ift
->neigh_list
)
608 struct top_hash_entry
*en
;
609 if (ntmp
->state
> NEIGHBOR_EXSTART
)
610 if ((en
= ospf_hash_find_header(ntmp
->lsrth
, domain
, &lsadb
->lsa
)) != NULL
)
612 s_rem_node(SNODE en
);
613 if (en
->lsa_body
!= NULL
)
614 mb_free(en
->lsa_body
);
616 ospf_hash_delete(ntmp
->lsrth
, en
);
620 if ((lsatmp
.age
== LSA_MAXAGE
) && (lsatmp
.sn
== LSA_MAXSEQNO
)
621 && lsadb
&& can_flush_lsa(po
))
623 flush_lsa(lsadb
, po
);
630 mb_alloc(p
->pool
, lsatmp
.length
- sizeof(struct ospf_lsa_header
));
631 ntohlsab(lsa
+ 1, body
, lsatmp
.type
,
632 lsatmp
.length
- sizeof(struct ospf_lsa_header
));
633 lsadb
= lsa_install_new(po
, &lsatmp
, domain
, body
);
634 DBG("New LSA installed in DB\n");
639 /* FIXME pg145 (6) */
642 if (lsa_comp(&lsatmp
, &lsadb
->lsa
) == CMP_SAME
)
644 struct top_hash_entry
*en
;
645 DBG("PG145(7) Got the same LSA\n");
646 if ((en
= ospf_hash_find_header(n
->lsrth
, lsadb
->domain
, &lsadb
->lsa
)) != NULL
)
649 s_rem_node(SNODE en
);
650 if (en
->lsa_body
!= NULL
)
651 mb_free(en
->lsa_body
);
653 ospf_hash_delete(n
->lsrth
, en
);
654 if (ifa
->state
== OSPF_IS_BACKUP
)
656 if (n
->rid
== ifa
->drid
)
657 ospf_lsack_enqueue(n
, lsa
, ACKL_DELAY
);
663 ospf_lsack_enqueue(n
, lsa
, ACKL_DIRECT
);
670 if ((lsadb
->lsa
.age
== LSA_MAXAGE
) && (lsadb
->lsa
.sn
== LSA_MAXSEQNO
))
677 struct l_lsr_head ll
;
679 ll
.lsh
.id
= lsadb
->lsa
.id
;
680 ll
.lsh
.rt
= lsadb
->lsa
.rt
;
681 ll
.lsh
.type
= lsadb
->lsa
.type
;
682 add_tail(&l
, NODE
& ll
);
683 ospf_lsupd_send_list(n
, &l
);
687 /* Send direct LSAs */
688 ospf_lsack_send(n
, ACKL_DIRECT
);
690 if (sendreq
&& (n
->state
== NEIGHBOR_LOADING
))
692 ospf_lsreq_send(n
); /* Ask for another part of neighbor's database */
697 ospf_lsupd_flush_nlsa(struct proto_ospf
*po
, struct top_hash_entry
*en
)
699 struct ospf_lsa_header
*lsa
= &en
->lsa
;
700 struct proto
*p
= &po
->proto
;
702 lsa
->age
= LSA_MAXAGE
;
703 lsa
->sn
= LSA_MAXSEQNO
;
704 lsasum_calculate(lsa
, en
->lsa_body
);
705 OSPF_TRACE(D_EVENTS
, "Premature aging self originated lsa!");
706 OSPF_TRACE(D_EVENTS
, "Type: %d, Id: %R, Rt: %R", lsa
->type
, lsa
->id
, lsa
->rt
);
707 ospf_lsupd_flood(po
, NULL
, NULL
, lsa
, en
->domain
, 0);