Subversion Repositories Kolibri OS

Compare Revisions

Ignore whitespace Rev 1762 → Rev 1763

/kernel/branches/net/network/tcp_input.inc
1,3 → 1,21
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Part of the tcp/ip network stack for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; Based on the code of 4.4BSD ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
;-----------------------------------------------------------------
;
; TCP_input:
339,8 → 357,9
 
; Update RTT estimators
 
;;; TODO
 
; Delete acknowledged bytes from send buffer
 
pusha
mov ecx, eax
lea eax, [ebx + STREAM_SOCKET.snd]
349,23 → 368,21
 
; update window pointers
mov eax, [edx + TCP_segment.AckNumber]
dec eax
mov [ebx + TCP_SOCKET.SND_WL1], eax
mov [ebx + TCP_SOCKET.SND_UNA], eax
 
; Stop retransmit timer
mov [ebx + TCP_SOCKET.timer_ack], 0
 
; Awaken waiting processes
mov [ebx + SOCKET.lock], 0
mov eax, ebx
call SOCKET_notify_owner
 
;; Generate more output FIXME
;; mov eax, ebx
;; call TCP_output
;;
;; jmp .drop
jmp .ack_processed
; Generate more output
call TCP_output
 
jmp .drop_not_locked
 
;-------------------------------------------------
; maybe we are the receiver in the uni-xfer then..
 
387,7 → 404,8
 
DEBUGF 1,"header prediction: we are receiver\nreceiving %u bytes of data\n", ecx
 
pusha
add [ebx + TCP_SOCKET.RCV_NXT], ecx ; Update sequence number with number of bytes we have copied
 
add esi, edx
lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_write ; Add the data to the socket buffer
394,9 → 412,7
 
mov eax, ebx
call SOCKET_notify_owner
popa
 
add [ebx + TCP_SOCKET.RCV_NXT], ecx ; Update sequence number with number of bytes we have copied
or [ebx + TCP_SOCKET.t_flags], TF_DELACK ; Set delayed ack flag
 
jmp .drop
415,7 → 431,7
 
; Calculate receive window size
 
;;;;
;;;; TODO: 444
 
cmp [ebx + TCP_SOCKET.t_state], TCB_LISTEN
je .LISTEN
540,7 → 556,7
 
TCP_rcvseqinit ebx
 
mov [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
 
mov eax, [ebx + TCP_SOCKET.SND_UNA]
cmp eax, [ebx + TCP_SOCKET.ISS]
608,7 → 624,7
 
; First, check if timestamp is present
 
;;;; TODO
;;;; TODO 602
 
; Then, check if at least some bytes of data are within window
 
628,10 → 644,12
 
mov eax, [ebx + TCP_SOCKET.RCV_NXT]
sub eax, [edx + TCP_segment.SequenceNumber]
jz .no_duplicate
jle .no_duplicate
 
DEBUGF 1,"Uh oh.. %x bytes of duplicate data!\n", eax
 
test [edx + TCP_segment.Flags], TH_SYN
jz .no_drop
jz .no_dup_syn
 
; remove duplicate syn
 
643,13 → 661,13
 
dec [edx + TCP_segment.UrgentPointer]
 
jmp .no_drop
jmp .no_dup_syn
@@:
 
and [edx + TCP_segment.Flags], not (TH_URG)
dec eax
jz .no_duplicate
.no_drop:
.no_dup_syn:
 
DEBUGF 1,"Going to drop %u out of %u bytes\n", eax, ecx
 
828,7 → 846,6
 
jmp .drop
 
.rst_skip:
 
 
 
835,7 → 852,9
 
 
 
.rst_skip:
 
 
;--------------------------------------
; handle SYN-full and ACK-less segments
 
857,7 → 876,6
 
 
 
 
;---------------
; ACK processing
 
876,49 → 894,135
cmp eax, [ebx + TCP_SOCKET.SND_UNA]
jg .not_dup_ack
 
DEBUGF 1,"Duplicate ACK\n"
 
test ecx, ecx
jnz .ack_processed
jnz .reset_dupacks
 
mov eax, dword [edx + TCP_segment.Window]
cmp eax, [ebx + TCP_SOCKET.SND_WND]
jne .ack_processed
jne .reset_dupacks
 
; Process the duplicate ACK
DEBUGF 1,"Processing a duplicate ACK..\n"
 
;;;;; 833 - 878
cmp [ebx + TCP_SOCKET.timer_retransmission], 10000 ;;;;
jg @f
 
;;; call TCP_output
mov eax, [edx + TCP_segment.AckNumber]
cmp eax, [ebx + TCP_SOCKET.SND_UNA]
je .dup_ack
 
@@:
mov [ebx + TCP_SOCKET.t_dupacks], 0
jmp .not_dup_ack
 
.dup_ack:
inc [ebx + TCP_SOCKET.t_dupacks]
cmp [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
jne .no_re_xmit
 
push [ebx + TCP_SOCKET.SND_NXT] ; >>>>
 
mov eax, [ebx + TCP_SOCKET.SND_WND]
cmp eax, [ebx + TCP_SOCKET.SND_CWND]
cmovg eax, [ebx + TCP_SOCKET.SND_CWND]
shr eax, 1
push edx
xor edx, edx
div [ebx + TCP_SOCKET.t_maxseg]
cmp eax, 2
jge @f
mov ax, 2
@@:
mul [ebx + TCP_SOCKET.t_maxseg]
pop edx
mov [ebx + TCP_SOCKET.SND_SSTHRESH], eax
 
mov [ebx + TCP_SOCKET.timer_retransmission], 0 ; turn off retransmission timer
mov [ebx + TCP_SOCKET.t_rtt], 0
mov eax, [edx + TCP_segment.AckNumber]
mov [ebx + TCP_SOCKET.SND_NXT], eax
mov eax, [ebx + TCP_SOCKET.t_maxseg]
mov [ebx + TCP_SOCKET.SND_CWND], eax
 
mov eax, ebx
call TCP_output ; retransmit missing segment
 
push edx
xor edx, edx
mov eax, [ebx + TCP_SOCKET.t_maxseg]
mul [ebx + TCP_SOCKET.t_dupacks]
pop edx
add eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
mov [ebx + TCP_SOCKET.SND_CWND], eax
 
pop eax ; <<<<
cmp eax, [ebx + TCP_SOCKET.SND_NXT]
jl @f
mov [ebx + TCP_SOCKET.SND_NXT], eax
@@:
 
jmp .drop
 
.not_dup_ack:
 
DEBUGF 1,"new ACK\n"
.no_re_xmit:
jle .not_dup_ack
 
DEBUGF 1,"Increasing congestion window\n"
 
mov eax, [ebx + TCP_SOCKET.t_maxseg]
add [ebx + TCP_SOCKET.SND_CWND], eax
 
mov eax, ebx
call TCP_output
 
jmp .drop
 
 
 
 
 
 
.not_dup_ack:
 
;-------------------------------------------------
; If the congestion window was inflated to account
; for the other side's cached packets, retract it
 
;;;; 888 - 902
mov eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
cmp eax, [ebx + TCP_SOCKET.SND_CWND]
jg @f
cmp [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
jle @f
mov [ebx + TCP_SOCKET.SND_CWND], eax
@@:
 
mov [ebx + TCP_SOCKET.t_dupacks], 0
 
mov eax, [edx + TCP_segment.AckNumber]
cmp eax, [ebx + TCP_SOCKET.SND_MAX]
jle @f
 
;;; TODO: update stats
jmp .drop_after_ack
 
@@:
 
mov edi, [edx + TCP_segment.AckNumber]
sub edi, [ebx + TCP_SOCKET.SND_UNA] ; now we got the number of acked bytes in esi
 
;;; TODO: update stats
 
 
DEBUGF 1,"We have an acceptable ACK of %x bytes\n", esi
 
 
 
 
 
 
;------------------------------------------
; RTT measurements and retransmission timer
 
;;;;; 903 - 926
;;;;; 912 - 926
 
mov [ebx + TCP_SOCKET.timer_retransmission], 0
 
937,25 → 1041,49
;-------------------------------------------
; Open congestion window in response to ACKs
 
;;;;
mov esi, [ebx + TCP_SOCKET.SND_CWND]
mov eax, [ebx + TCP_SOCKET.t_maxseg]
 
cmp esi, [ebx + TCP_SOCKET.SND_SSTHRESH]
jle @f
push edx
push eax
mul eax
div esi
pop edx
shr edx, 3
add eax, edx
pop edx
@@:
 
add esi, eax
 
push ecx
mov cl, [ebx + TCP_SOCKET.SND_SCALE]
mov eax, TCP_max_win
shl eax, cl
pop ecx
 
cmp esi, eax
cmovg esi, eax
mov [ebx + TCP_SOCKET.SND_CWND], esi
 
 
 
 
 
 
 
;------------------------------------------
; Remove acknowledged data from send buffer
 
pusha
mov ecx, [edx + TCP_segment.AckNumber]
sub ecx, [ebx + TCP_SOCKET.SND_UNA] ; ecx now holds number of bytes acked
 
push ecx edx ebx
mov ecx, edi
lea eax, [ebx + STREAM_SOCKET.snd]
call SOCKET_ring_free
popa
pop ebx
sub [ebx + TCP_SOCKET.SND_WND], ecx
pop edx ecx
 
; Wake up process waiting on send buffer
 
977,6 → 1105,7
 
 
 
 
; General ACK handling complete
; Now do the state-specific ones
 
1016,8 → 1145,9
 
 
 
.reset_dupacks: ; We got a new ACK, reset duplicate ACK counter
 
align 4
mov [ebx + TCP_SOCKET.t_dupacks], 0
 
.ack_processed: ; (step 6)