TCP: advertise correct window, small updates and bugfixes

git-svn-id: svn://kolibrios.org@4347 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
hidnplayr 2013-12-13 12:20:53 +00:00
parent df6a761ad4
commit bf755d6cbd
4 changed files with 93 additions and 67 deletions

View File

@ -141,10 +141,6 @@ struct TCP_SOCKET IP_SOCKET
seg_next dd ? ; re-assembly queue seg_next dd ? ; re-assembly queue
temp_bits db ?
rb 3 ; align
ends ends
struct UDP_SOCKET IP_SOCKET struct UDP_SOCKET IP_SOCKET

View File

@ -110,7 +110,7 @@ SS_MORETOCOME = 0x4000
SS_BLOCKED = 0x8000 SS_BLOCKED = 0x8000
SOCKET_MAXDATA = 4096*32 ; must be 4096*(power of 2) where 'power of 2' is at least 8 SOCKET_MAXDATA = 4096*8 ; must be 4096*(power of 2) where 'power of 2' is at least 8
MAX_backlog = 20 ; maximum backlog for stream sockets MAX_backlog = 20 ; maximum backlog for stream sockets
; Error Codes ; Error Codes

View File

@ -83,6 +83,7 @@ proc TCP_process_input
locals locals
dataoffset dd ? dataoffset dd ?
timestamp dd ? timestamp dd ?
temp_bits db ?
endl endl
xor esi, esi xor esi, esi
@ -218,7 +219,7 @@ endl
;--------------------------- ;---------------------------
; disable all temporary bits ; disable all temporary bits
mov [ebx + TCP_SOCKET.temp_bits], 0 mov [temp_bits], 0
;--------------------------------------- ;---------------------------------------
; unscale the window into a 32 bit value ; unscale the window into a 32 bit value
@ -252,7 +253,7 @@ endl
mov ebx, eax mov ebx, eax
mov [ebx + TCP_SOCKET.temp_bits], TCP_BIT_DROPSOCKET ;;; FIXME: should we take over bits from previous socket? mov [temp_bits], TCP_BIT_DROPSOCKET
push dword [edi + 4] ; Ipv4 destination addres push dword [edi + 4] ; Ipv4 destination addres
pop [ebx + IP_SOCKET.LocalIP] pop [ebx + IP_SOCKET.LocalIP]
@ -378,7 +379,7 @@ endl
mov [ebx + TCP_SOCKET.ts_val], eax mov [ebx + TCP_SOCKET.ts_val], eax
lodsd ; timestamp echo reply lodsd ; timestamp echo reply
mov [ebx + TCP_SOCKET.ts_ecr], eax mov [ebx + TCP_SOCKET.ts_ecr], eax
or [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP or [temp_bits], TCP_BIT_TIMESTAMP
; Since we have a timestamp, lets do the paws test right away! ; Since we have a timestamp, lets do the paws test right away!
@ -483,7 +484,7 @@ endl
; Update RTT estimators ; Update RTT estimators
test [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP test [temp_bits], TCP_BIT_TIMESTAMP
jz .no_timestamp_rtt jz .no_timestamp_rtt
mov eax, [timestamp] mov eax, [timestamp]
sub eax, [ebx + TCP_SOCKET.ts_ecr] sub eax, [ebx + TCP_SOCKET.ts_ecr]
@ -713,16 +714,16 @@ endl
;;; TODO: update stats ;;; TODO: update stats
.dont_drop_all: .dont_drop_all:
;;; TODO: update stats ;;; TODO: update stats
DEBUGF 1, "Trimming %u bytes from the right of the window\n" DEBUGF DEBUG_NETWORK_VERBOSE, "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 ; remove data from the right side of window (decrease data length)
and [ebx + TCP_SOCKET.t_flags], not (TH_PUSH or TH_FIN) and [edx + TCP_header.Flags], not (TH_PUSH or TH_FIN)
.no_excess_data: .no_excess_data:
;----------------- ;-----------------
; Record timestamp ; 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 [temp_bits], TCP_BIT_TIMESTAMP
jz .no_timestamp jz .no_timestamp
mov eax, [ebx + TCP_SOCKET.last_ack_sent] mov eax, [ebx + TCP_SOCKET.last_ack_sent]
sub eax, [edx + TCP_header.SequenceNumber] sub eax, [edx + TCP_header.SequenceNumber]
@ -1004,11 +1005,11 @@ endl
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: acceptable ACK for %u bytes\n", edi DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: acceptable ACK for %u bytes\n", edi
;------------------------------------------ ;------------------------------------------
; RTT measurements and retransmission timer (912-926) ; RTT measurements and retransmission timer
; If we have a timestamp, update smoothed RTT ; If we have a timestamp, update smoothed RTT
test [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP test [temp_bits], TCP_BIT_TIMESTAMP
jz .timestamp_not_present jz .timestamp_not_present
mov eax, [timestamp] mov eax, [timestamp]
sub eax, [ebx + TCP_SOCKET.ts_ecr] sub eax, [ebx + TCP_SOCKET.ts_ecr]
@ -1039,7 +1040,7 @@ endl
cmp eax, [edx + TCP_header.AckNumber] cmp eax, [edx + TCP_header.AckNumber]
jne .more_data jne .more_data
and [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission and [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission
or [ebx + TCP_SOCKET.temp_bits], TCP_BIT_NEEDOUTPUT or [temp_bits], TCP_BIT_NEEDOUTPUT
jmp .no_restart jmp .no_restart
.more_data: .more_data:
test [ebx + TCP_SOCKET.timer_flags], timer_flag_persist test [ebx + TCP_SOCKET.timer_flags], timer_flag_persist
@ -1241,7 +1242,7 @@ align 4
TCP_rcvseqinit ebx TCP_rcvseqinit ebx
mov [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED mov [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
mov [ebx + TCP_SOCKET.t_flags], TF_ACKNOW or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
mov [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval ;;;; macro mov [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval ;;;; macro
or [ebx + TCP_SOCKET.timer_flags], timer_flag_keepalive or [ebx + TCP_SOCKET.timer_flags], timer_flag_keepalive
@ -1251,7 +1252,7 @@ align 4
lea eax, [ebx + STREAM_SOCKET.rcv] lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_create call SOCKET_ring_create
and [ebx + TCP_SOCKET.temp_bits], not TCP_BIT_DROPSOCKET and [temp_bits], not TCP_BIT_DROPSOCKET
pusha pusha
mov eax, ebx mov eax, ebx
@ -1431,7 +1432,7 @@ align 4
push [edx + TCP_header.AckNumber] push [edx + TCP_header.AckNumber]
pop [ebx + TCP_SOCKET.SND_WL2] pop [ebx + TCP_SOCKET.SND_WL2]
or [ebx + TCP_SOCKET.temp_bits], TCP_BIT_NEEDOUTPUT or [temp_bits], TCP_BIT_NEEDOUTPUT
.no_window_update: .no_window_update:
@ -1521,7 +1522,6 @@ align 4
; Generate ACK immediately, to let the other end know that a segment was received out of order, ; 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. ; 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:
;--------------- ;---------------
@ -1540,7 +1540,7 @@ align 4
mov eax, ebx mov eax, ebx
call SOCKET_cant_recv_more call SOCKET_cant_recv_more
mov [ebx + TCP_SOCKET.t_flags], TF_ACKNOW or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
inc [ebx + TCP_SOCKET.RCV_NXT] inc [ebx + TCP_SOCKET.RCV_NXT]
.not_first_fin: .not_first_fin:
@ -1562,29 +1562,54 @@ align 4
dd .fin_timed ; TCPS_TIMED_WAIT dd .fin_timed ; TCPS_TIMED_WAIT
.fin_syn_est: .fin_syn_est:
mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
jmp .final_processing jmp .final_processing
.fin_wait1: .fin_wait1:
mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSING mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSING
jmp .final_processing jmp .final_processing
.fin_wait2: .fin_wait2:
mov [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT mov [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
mov eax, ebx mov eax, ebx
call TCP_cancel_timers call TCP_cancel_timers
mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
or [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
call SOCKET_is_disconnected call SOCKET_is_disconnected
jmp .final_processing
.fin_timed: .fin_timed:
mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
or [ebx + TCP_SOCKET.timer_flags], timer_flag_wait or [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
jmp .final_processing
;-----------------
; Final processing
.final_processing:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Final processing\n"
push ebx
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
pop eax
test [temp_bits], TCP_BIT_NEEDOUTPUT
jnz .need_output
test [eax + TCP_SOCKET.t_flags], TF_ACKNOW
jz .dumpit
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: ACK now!\n"
.need_output:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: need output\n"
call TCP_output
.dumpit:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: dumping\n"
call NET_packet_free
jmp .loop
;-----------------
; Drop the segment
.drop_after_ack: .drop_after_ack:
@ -1621,34 +1646,6 @@ align 4
jnz .respond_syn jnz .respond_syn
jmp .dumpit jmp .dumpit
;-----------------
; Final processing
.final_processing:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Final processing\n"
push ebx
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
pop eax
test [eax + TCP_SOCKET.temp_bits], TCP_BIT_NEEDOUTPUT
jnz .need_output
test [eax + TCP_SOCKET.t_flags], TF_ACKNOW
jz .dumpit
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: ACK now!\n"
.need_output:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: need output\n"
call TCP_output
.dumpit:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: dumping\n"
call NET_packet_free
jmp .loop
;--------- ;---------
; Respond ; Respond
@ -1709,7 +1706,7 @@ align 4
popa popa
.destroy_new_socket: .destroy_new_socket:
test [ebx + TCP_SOCKET.temp_bits], TCP_BIT_DROPSOCKET test [temp_bits], TCP_BIT_DROPSOCKET
jz .drop_no_socket jz .drop_no_socket
mov eax, ebx mov eax, ebx

View File

@ -26,7 +26,11 @@ $Revision: 3289 $
; ;
;----------------------------------------------------------------- ;-----------------------------------------------------------------
align 4 align 4
TCP_output: proc TCP_output
locals
temp_bits db ?
endl
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: socket=%x\n", eax DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: socket=%x\n", eax
@ -57,7 +61,7 @@ TCP_output:
.not_idle: .not_idle:
.again: .again:
mov [eax + TCP_SOCKET.temp_bits], 0 mov [temp_bits], 0
mov ebx, [eax + TCP_SOCKET.SND_NXT] ; calculate offset (71) mov ebx, [eax + TCP_SOCKET.SND_NXT] ; calculate offset (71)
sub ebx, [eax + TCP_SOCKET.SND_UNA] ; sub ebx, [eax + TCP_SOCKET.SND_UNA] ;
@ -145,7 +149,7 @@ TCP_output:
jbe @f jbe @f
mov esi, [eax + TCP_SOCKET.t_maxseg] mov esi, [eax + TCP_SOCKET.t_maxseg]
or [eax + TCP_SOCKET.temp_bits], TCP_BIT_SENDALOT or [temp_bits], TCP_BIT_SENDALOT
@@: @@:
;-------------------------------------------- ;--------------------------------------------
@ -406,16 +410,48 @@ TCP_send:
jbe .no_overflow jbe .no_overflow
mov esi, [eax + TCP_SOCKET.t_maxseg] mov esi, [eax + TCP_SOCKET.t_maxseg]
or [eax + TCP_SOCKET.temp_bits], TCP_BIT_SENDALOT or [temp_bits], TCP_BIT_SENDALOT
.no_overflow: .no_overflow:
;----------------------------------------------------
; Calculate the receive window.
; Dont shrink window, but avoid silly window syndrome
mov ebx, SOCKET_MAXDATA
sub ebx, [eax + STREAM_SOCKET.rcv.size]
cmp ebx, SOCKET_MAXDATA/4
jae @f
cmp ebx, [eax + TCP_SOCKET.t_maxseg]
jae @f
xor ebx, ebx
@@:
cmp ebx, TCP_max_win
jbe @f
mov ebx, TCP_max_win
@@:
mov ecx, [eax + TCP_SOCKET.RCV_ADV]
sub ecx, [eax + TCP_SOCKET.RCV_NXT]
cmp ebx, ecx
ja @f
mov ebx, ecx
@@:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: window = %u\n", ebx
mov cl, [eax + TCP_SOCKET.RCV_SCALE]
shr ebx, cl
xchg bl, bh
;----------------------------------------------------------------- ;-----------------------------------------------------------------
; Start by pushing all TCP header values in reverse order on stack ; Start by pushing all TCP header values in reverse order on stack
; (essentially, creating the tcp header on the stack!) ; (essentially, creating the tcp header on the stack!)
pushw 0 ; .UrgentPointer dw ? pushw 0 ; .UrgentPointer dw ?
pushw 0 ; .Checksum dw ? pushw 0 ; .Checksum dw ?
pushw 0x00a0 ; .Window dw ? ;;;;;;; FIXME (370) pushw bx ; .Window dw ?
shl edi, 2 ; .DataOffset db ? only 4 left-most bits shl edi, 2 ; .DataOffset db ? only 4 left-most bits
shl dx, 8 shl dx, 8
or dx, di ; .Flags db ? or dx, di ; .Flags db ?
@ -566,7 +602,7 @@ TCP_send:
push [eax + TCP_SOCKET.RCV_NXT] push [eax + TCP_SOCKET.RCV_NXT]
pop [eax + TCP_SOCKET.last_ack_sent] pop [eax + TCP_SOCKET.last_ack_sent]
; and flags ; clear the ACK flags
and [eax + TCP_SOCKET.t_flags], not (TF_ACKNOW + TF_DELACK) and [eax + TCP_SOCKET.t_flags], not (TF_ACKNOW + TF_DELACK)
;-------------- ;--------------
@ -582,7 +618,7 @@ TCP_send:
;----------------------------- ;-----------------------------
; Check if we need more output ; Check if we need more output
test [eax + TCP_SOCKET.temp_bits], TCP_BIT_SENDALOT test [temp_bits], TCP_BIT_SENDALOT
jnz TCP_output.again jnz TCP_output.again
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: success!\n" DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: success!\n"
@ -622,7 +658,4 @@ TCP_send:
ret ret
endp