Mon 16 Apr 2012 01:10:55 PM UTC, comment #8:
I finally realized what going on.
It's lwip bug(. checksum of delayed tcp_seg not correctly summed with new sended data. Here is example with my comments:
//my test values for reproduce
#define TCP_SND_BUF (24)
#define TCP_MSS (10) //yes, I know that TCP_MSS must be more then 536, but it's for easily debug only
#define LWIP_CHECKSUM_ON_COPY 1
#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK 1
with this options sending 27 bytes of any data will fail
log:
TCP connection request 4163 -> 80. //new client connected
tcp_enqueue_flags: queueing 6510:6511 (0x12)
tcp_output_segment: 6510:6510
TCP connection established 4163 -> 80.
tcp_output: nothing to send (0x0) //here we send 24 bytes of data
tcp_write(pcb=0x200019a8, data=0x80273a0, len=24, apiflags=2) //24 writes because of TCP_SND_BUF limit
tcp_write: queueing 6511:6521 //full segment1 len = 10
tcp_write: queueing 6521:6531 //full segment2 len = 10
tcp_write: queueing 6531:6535 //NOT full segment3 len = 4 (will wait for TCP_MORE_DATA)
tcp_output_segment: 6511:6521 //segment1 out
tcp_output_segment: 6521:6531 //segment2 out
tcp_write(pcb=0x200019a8, data=0x80273b8, len=3, apiflags=0) //after ACK received we write remaining data (3 bytes)
tcp_output_segment: 6531:6538 //it's segment with old 4 bytes + new 3 bytes
tcp_output_segment: calculated checksum is a64a instead of ae6 //checksum of this segment incorrect!!
now deep into the code:
tcp_write function declare next variables if LWIP_CHECKSUM_ON_COPY=1
u16_t concat_chksum = 0; //checksum of new added data
u8_t concat_chksum_swapped = 0; //is checksum swapped or not
u16_t concat_chksummed = 0; //len of new data witch added to delayed segment
//in 2 phase we set this variables to right values
after all we concat_p to last_unsent->p and sum checksums
#if TCP_CHECKSUM_ON_COPY
if (concat_chksummed) {
/ERROR if concat_chksum swapped!! we must swap it back /
tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum,
&last_unsent->chksum_swapped);
last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED;
}
#endif /* TCP_CHECKSUM_ON_COPY */
I add this before call tcp_seg_add_chksum (also patch in attach)
/if concat checksumm swapped - swap it back /
if (concat_chksum_swapped){
concat_chksum = SWAP_BYTES_IN_WORD(concat_chksum);
}
This solve the problem.
After viewing the code, I think, that concat_chksum_swapped not necessary,
because we don't accumulate checksum in concat_chksum. (why tcp_seg_add_chksum called for compute new data checksum in phase 2??)
I need someone to fix the code properly, I'm afraid to break the code.
(file #25657)
|