forked from KolibriOS/kolibrios
Bugfixes in TCP.
git-svn-id: svn://kolibrios.org@4339 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
d15d08a79a
commit
d148603f7d
@ -92,8 +92,8 @@ struct TCP_SOCKET IP_SOCKET
|
|||||||
SND_MAX dd ?
|
SND_MAX dd ?
|
||||||
|
|
||||||
; congestion control
|
; congestion control
|
||||||
SND_CWND dd ?
|
SND_CWND dd ? ; congestion window
|
||||||
SND_SSTHRESH dd ?
|
SND_SSTHRESH dd ? ; slow start threshold
|
||||||
|
|
||||||
;----------------------
|
;----------------------
|
||||||
; Transmit timing stuff
|
; Transmit timing stuff
|
||||||
@ -2085,7 +2085,6 @@ SOCKET_num_to_ptr:
|
|||||||
mov eax, [eax + SOCKET.NextPtr]
|
mov eax, [eax + SOCKET.NextPtr]
|
||||||
or eax, eax
|
or eax, eax
|
||||||
jz .error
|
jz .error
|
||||||
diff16 "tetten", 0, $
|
|
||||||
cmp [eax + SOCKET.Number], ecx
|
cmp [eax + SOCKET.Number], ecx
|
||||||
jne .next_socket
|
jne .next_socket
|
||||||
|
|
||||||
|
@ -78,7 +78,11 @@ TCP_input:
|
|||||||
|
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
TCP_process_input:
|
proc TCP_process_input
|
||||||
|
|
||||||
|
locals
|
||||||
|
dataoffset dd ?
|
||||||
|
endl
|
||||||
|
|
||||||
xor esi, esi
|
xor esi, esi
|
||||||
mov ecx, MANUAL_DESTROY
|
mov ecx, MANUAL_DESTROY
|
||||||
@ -123,12 +127,13 @@ TCP_process_input:
|
|||||||
.checksum_ok:
|
.checksum_ok:
|
||||||
|
|
||||||
; Verify the data offset
|
; Verify the data offset
|
||||||
and [edx + TCP_header.DataOffset], 0xf0 ; Calculate TCP segment header size (throwing away unused reserved bits in TCP header)
|
|
||||||
shr [edx + TCP_header.DataOffset], 2
|
|
||||||
cmp [edx + TCP_header.DataOffset], sizeof.TCP_header ; Now see if it's at least the size of a standard TCP header
|
|
||||||
jb .drop_no_socket ; If not, drop the packet
|
|
||||||
|
|
||||||
movzx eax, [edx + TCP_header.DataOffset]
|
movzx eax, [edx + TCP_header.DataOffset]
|
||||||
|
and al, 0xf0 ; Calculate TCP segment header size (throwing away unused reserved bits in TCP header)
|
||||||
|
shr al, 2
|
||||||
|
cmp al, sizeof.TCP_header ; Now see if it's at least the size of a standard TCP header
|
||||||
|
jb .drop_no_socket ; If not, drop the packet
|
||||||
|
mov [dataoffset], eax
|
||||||
|
|
||||||
sub ecx, eax ; substract TCP header size from total segment size
|
sub ecx, eax ; substract TCP header size from total segment size
|
||||||
jb .drop_no_socket ; If total segment size is less then the advertised header size, drop packet
|
jb .drop_no_socket ; If total segment size is less then the advertised header size, drop packet
|
||||||
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes of data\n", ecx
|
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes of data\n", ecx
|
||||||
@ -267,18 +272,18 @@ TCP_process_input:
|
|||||||
;--------------------
|
;--------------------
|
||||||
; Process TCP options
|
; Process TCP options
|
||||||
|
|
||||||
|
;;; FIXME: for LISTEN, options should be called after we determined route, we need it for MSS
|
||||||
|
;;; cmp [ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state
|
||||||
|
;;; jz .not_uni_xfer ; also no header prediction
|
||||||
|
|
||||||
push ecx
|
push ecx
|
||||||
|
|
||||||
movzx ecx, [edx + TCP_header.DataOffset]
|
mov ecx, [dataoffset]
|
||||||
cmp ecx, sizeof.TCP_header ; Does header contain any options?
|
cmp ecx, sizeof.TCP_header ; Does header contain any options?
|
||||||
je .no_options
|
je .no_options
|
||||||
|
|
||||||
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Segment has options\n"
|
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Segment has options\n"
|
||||||
|
|
||||||
;;; FIXME: for LISTEN, options should be called after we determined route, we need it for MSS
|
|
||||||
;;; cmp [ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state
|
|
||||||
;;; jz .not_uni_xfer ; also no header prediction
|
|
||||||
|
|
||||||
add ecx, edx
|
add ecx, edx
|
||||||
lea esi, [edx + sizeof.TCP_header]
|
lea esi, [edx + sizeof.TCP_header]
|
||||||
|
|
||||||
@ -311,9 +316,10 @@ TCP_process_input:
|
|||||||
test [edx + TCP_header.Flags], TH_SYN
|
test [edx + TCP_header.Flags], TH_SYN
|
||||||
jz @f
|
jz @f
|
||||||
|
|
||||||
|
xor eax, eax
|
||||||
lodsw
|
lodsw
|
||||||
rol ax, 8
|
rol ax, 8
|
||||||
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Maxseg=%u\n", ax
|
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Maxseg=%u\n", eax
|
||||||
call TCP_mss
|
call TCP_mss
|
||||||
@@:
|
@@:
|
||||||
jmp .opt_loop
|
jmp .opt_loop
|
||||||
@ -538,7 +544,7 @@ TCP_process_input:
|
|||||||
|
|
||||||
add [ebx + TCP_SOCKET.RCV_NXT], ecx ; Update sequence number with number of bytes we have copied
|
add [ebx + TCP_SOCKET.RCV_NXT], ecx ; Update sequence number with number of bytes we have copied
|
||||||
|
|
||||||
movzx esi, [edx + TCP_header.DataOffset]
|
mov esi, [dataoffset]
|
||||||
add esi, edx
|
add esi, edx
|
||||||
lea eax, [ebx + STREAM_SOCKET.rcv]
|
lea eax, [ebx + STREAM_SOCKET.rcv]
|
||||||
call SOCKET_ring_write ; Add the data to the socket buffer
|
call SOCKET_ring_write ; Add the data to the socket buffer
|
||||||
@ -583,8 +589,9 @@ TCP_process_input:
|
|||||||
;----------------------------
|
;----------------------------
|
||||||
; trim any data not in window
|
; trim any data not in window
|
||||||
|
|
||||||
; check for duplicate data at beginning of segment (635)
|
; 1. Check for duplicate data at beginning of segment
|
||||||
|
|
||||||
|
; Calculate number of bytes we need to drop
|
||||||
mov eax, [ebx + TCP_SOCKET.RCV_NXT]
|
mov eax, [ebx + TCP_SOCKET.RCV_NXT]
|
||||||
sub eax, [edx + TCP_header.SequenceNumber]
|
sub eax, [edx + TCP_header.SequenceNumber]
|
||||||
jle .no_duplicate
|
jle .no_duplicate
|
||||||
@ -609,7 +616,7 @@ TCP_process_input:
|
|||||||
dec eax
|
dec eax
|
||||||
.no_dup_syn:
|
.no_dup_syn:
|
||||||
|
|
||||||
; Check for entire duplicate segment (646)
|
; 2. Check for entire duplicate segment
|
||||||
cmp eax, ecx ; eax holds number of bytes to drop, ecx is data size
|
cmp eax, ecx ; eax holds number of bytes to drop, ecx is data size
|
||||||
jb .duplicate
|
jb .duplicate
|
||||||
jnz @f
|
jnz @f
|
||||||
@ -623,16 +630,19 @@ TCP_process_input:
|
|||||||
|
|
||||||
; send an ACK and resynchronize and drop any data.
|
; send an ACK and resynchronize and drop any data.
|
||||||
; But keep on processing for RST or ACK
|
; But keep on processing for RST or ACK
|
||||||
DEBUGF DEBUG_NETWORK_VERBOSE, "616\n"
|
|
||||||
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
|
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
|
||||||
mov eax, ecx
|
mov eax, ecx
|
||||||
;TODO: update stats
|
|
||||||
|
;;; TODO: update stats
|
||||||
|
|
||||||
;-----------------------------------------------
|
;-----------------------------------------------
|
||||||
; Remove duplicate data and update urgent offset
|
; Remove duplicate data and update urgent offset
|
||||||
|
|
||||||
.duplicate:
|
.duplicate:
|
||||||
;;; TODO: 677
|
DEBUGF 1, "TCP_input: trimming duplicate data\n"
|
||||||
|
|
||||||
|
; Trim data from left side of window
|
||||||
|
add [dataoffset], eax
|
||||||
add [edx + TCP_header.SequenceNumber], eax
|
add [edx + TCP_header.SequenceNumber], eax
|
||||||
sub ecx, eax
|
sub ecx, eax
|
||||||
|
|
||||||
@ -643,10 +653,10 @@ TCP_process_input:
|
|||||||
@@:
|
@@:
|
||||||
|
|
||||||
;--------------------------------------------------
|
;--------------------------------------------------
|
||||||
; Handle data that arrives after process terminates (687)
|
; Handle data that arrives after process terminates
|
||||||
|
|
||||||
.no_duplicate:
|
.no_duplicate:
|
||||||
cmp [ebx + SOCKET.PID], 0
|
cmp [ebx + SOCKET.PID], 0 ;;; TODO: use socket flags instead??
|
||||||
jne .not_terminated
|
jne .not_terminated
|
||||||
cmp [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
|
cmp [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
|
||||||
jbe .not_terminated
|
jbe .not_terminated
|
||||||
@ -659,7 +669,7 @@ TCP_process_input:
|
|||||||
jmp .respond_seg_reset
|
jmp .respond_seg_reset
|
||||||
|
|
||||||
;----------------------------------------
|
;----------------------------------------
|
||||||
; Remove data beyond right edge of window (700-736)
|
; Remove data beyond right edge of window
|
||||||
|
|
||||||
.not_terminated:
|
.not_terminated:
|
||||||
mov eax, [edx + TCP_header.SequenceNumber]
|
mov eax, [edx + TCP_header.SequenceNumber]
|
||||||
@ -688,29 +698,26 @@ TCP_process_input:
|
|||||||
jmp .findpcb ; FIXME: skip code for unscaling window, ...
|
jmp .findpcb ; FIXME: skip code for unscaling window, ...
|
||||||
.no_new_request:
|
.no_new_request:
|
||||||
|
|
||||||
; If window is closed can only take segments at window edge, and have to drop data and PUSH from
|
; If window is closed, we can only take segments at window edge, and have to drop data and PUSH from
|
||||||
; incoming segments. Continue processing, but remember to ACK. Otherwise drop segment and ACK
|
; incoming segments. Continue processing, but remember to ACK. Otherwise drop segment and ACK
|
||||||
|
|
||||||
cmp [ebx + TCP_SOCKET.RCV_WND], 0
|
cmp [ebx + TCP_SOCKET.RCV_WND], 0
|
||||||
jne .drop_after_ack
|
jne .drop_after_ack
|
||||||
mov eax, [edx + TCP_header.SequenceNumber]
|
mov esi, [edx + TCP_header.SequenceNumber]
|
||||||
cmp eax, [ebx + TCP_SOCKET.RCV_NXT]
|
cmp esi, [ebx + TCP_SOCKET.RCV_NXT]
|
||||||
jne .drop_after_ack
|
jne .drop_after_ack
|
||||||
|
|
||||||
DEBUGF DEBUG_NETWORK_VERBOSE, "690\n"
|
|
||||||
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
|
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
|
||||||
;;; TODO: update stats
|
;;; TODO: update stats
|
||||||
jmp .no_excess_data
|
|
||||||
.dont_drop_all:
|
.dont_drop_all:
|
||||||
;;; TODO: update stats
|
;;; TODO: update stats
|
||||||
;;; TODO: 733
|
DEBUGF 1, "Trimming %u bytes from the right of the window\n"
|
||||||
|
sub ecx, eax ; remove data from the right side of window (decrease data length)
|
||||||
sub ecx, eax
|
|
||||||
and [ebx + TCP_SOCKET.t_flags], not (TH_PUSH or TH_FIN)
|
and [ebx + TCP_SOCKET.t_flags], not (TH_PUSH or TH_FIN)
|
||||||
.no_excess_data:
|
.no_excess_data:
|
||||||
|
|
||||||
;-----------------
|
;-----------------
|
||||||
; Record timestamp (737-746)
|
; Record timestamp
|
||||||
|
|
||||||
; If last ACK falls within this segments sequence numbers, record its timestamp
|
; If last ACK falls within this segments sequence numbers, record its timestamp
|
||||||
test [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
|
test [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
|
||||||
@ -1359,7 +1366,16 @@ align 4
|
|||||||
|
|
||||||
inc [edx + TCP_header.SequenceNumber]
|
inc [edx + TCP_header.SequenceNumber]
|
||||||
|
|
||||||
;;; TODO: Drop any received data that follows receive window (590)
|
; Drop any received data that doesnt fit in the receive window.
|
||||||
|
cmp ecx, [ebx + TCP_SOCKET.RCV_WND]
|
||||||
|
jbe .dont_trim
|
||||||
|
|
||||||
|
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: received data does not fit in window, trimming %u bytes\n", eax
|
||||||
|
mov ecx, [ebx + TCP_SOCKET.RCV_WND]
|
||||||
|
and [edx + TCP_header.Flags], not (TH_FIN)
|
||||||
|
;;; TODO: update stats
|
||||||
|
|
||||||
|
.dont_trim:
|
||||||
|
|
||||||
mov eax, [edx + TCP_header.SequenceNumber]
|
mov eax, [edx + TCP_header.SequenceNumber]
|
||||||
mov [ebx + TCP_SOCKET.RCV_UP], eax
|
mov [ebx + TCP_SOCKET.RCV_UP], eax
|
||||||
@ -1479,7 +1495,7 @@ align 4
|
|||||||
or [ebx + TCP_SOCKET.t_flags], TF_DELACK
|
or [ebx + TCP_SOCKET.t_flags], TF_DELACK
|
||||||
|
|
||||||
pusha
|
pusha
|
||||||
movzx esi, [edx + TCP_header.DataOffset]
|
mov esi, [dataoffset]
|
||||||
add esi, edx
|
add esi, edx
|
||||||
lea eax, [ebx + STREAM_SOCKET.rcv]
|
lea eax, [ebx + STREAM_SOCKET.rcv]
|
||||||
call SOCKET_ring_write ; Add the data to the socket buffer
|
call SOCKET_ring_write ; Add the data to the socket buffer
|
||||||
@ -1493,14 +1509,15 @@ align 4
|
|||||||
jmp .data_done
|
jmp .data_done
|
||||||
|
|
||||||
.out_of_order:
|
.out_of_order:
|
||||||
|
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP data is out of order!\nSequencenumber is %u, we expected %u.\n", \
|
||||||
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP data is out of order\n"
|
[edx + TCP_header.SequenceNumber], [ebx + TCP_SOCKET.RCV_NXT]
|
||||||
|
|
||||||
; Uh-oh, some data is out of order, lets call TCP reassemble for help
|
; Uh-oh, some data is out of order, lets call TCP reassemble for help
|
||||||
|
|
||||||
call TCP_reassemble
|
call TCP_reassemble
|
||||||
|
|
||||||
DEBUGF DEBUG_NETWORK_VERBOSE, "1470\n"
|
; Generate ACK immediately, to let the other end know that a segment was received out of order,
|
||||||
|
; and to tell it what sequence number is expected. This aids the fast-retransmit algorithm.
|
||||||
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
|
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
|
||||||
|
|
||||||
.data_done:
|
.data_done:
|
||||||
@ -1703,3 +1720,5 @@ align 4
|
|||||||
call NET_packet_free
|
call NET_packet_free
|
||||||
add esp, 4
|
add esp, 4
|
||||||
jmp .loop
|
jmp .loop
|
||||||
|
|
||||||
|
endp
|
||||||
|
Loading…
Reference in New Issue
Block a user