Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1518 → Rev 1519

/kernel/branches/net/network/tcp.inc
58,6 → 58,22
TCP_OPT_WINDOW equ 3 ; window scale
TCP_OPT_TIMESTAMP equ 8
 
; Fundamental timer values
TCP_time_MSL equ 47 ; max segment lifetime (30s)
TCP_time_re_min equ 2 ; min retransmission (1,28s)
TCP_time_re_max equ 100 ; max retransmission (64s)
TCP_time_pers_min equ 8 ; min persist (5,12s)
TCP_time_pers_max equ 94 ; max persist (60,16s)
TCP_time_keep_init equ 118 ; connectione stablishment (75,52s)
TCP_time_keep_idle equ 4608 ; idle time before 1st probe (2h)
TCP_time_keep_interval equ 118 ; between probes when no response (75,52s)
TCP_time_rtt_default equ 5 ; default Round Trip Time (3,2s)
 
; timer constants
TCP_max_rxtshift equ 12 ; max retransmissions waiting for ACK
TCP_max_keepcnt equ 8 ; max keepalive probes
 
 
struct TCP_segment
.SourcePort dw ?
.DestinationPort dw ?
118,24 → 134,16
ret
 
 
;-----------------------------------------------------------------
;----------------------
;
; decrease socket ttls
;
; IN: /
; OUT: /
;
; destroys: eax
;
;-----------------------------------------------------------------
;----------------------
align 4
TCP_timer_1000ms:
; scan through all the active TCP sockets, decrementing active timers
TCP_timer_160ms:
 
mov eax, net_sockets
.loop:
mov eax, [eax + SOCKET.NextPtr]
.check_only:
or eax, eax
jz .exit
 
142,62 → 150,80
cmp [eax + SOCKET.Type], IP_PROTO_TCP
jne .loop
 
cmp [eax + TCP_SOCKET.t_timer], 0
jne .decrement_tcb
;;;;;; cmp [eax + TCP_SOCKET.wndsizeTimer], 0
jne .decrement_wnd
jmp .loop
 
.decrement_tcb:
; decrement it, delete socket if TCB timer = 0 & socket in timewait state
dec [eax + TCP_SOCKET.t_timer]
dec [eax + TCP_SOCKET.timer_ack]
jnz .loop
 
cmp [eax + TCP_SOCKET.t_state], TCB_TIMED_WAIT
jne .loop
DEBUGF 1,"TCP ack for socket %x expired, time to piggyback!\n", eax
 
push [eax + SOCKET.NextPtr]
call SOCKET_free
push eax
call TCP_respond
pop eax
jmp .check_only
 
.decrement_wnd:
;;;;;; dec [eax + TCP_SOCKET.wndsizeTimer]
jmp .loop
 
.exit:
 
ret
 
 
 
;----------------------
;-----------------------------------------------------------------
;
; TCP_500ms
;
;----------------------
;-----------------------------------------------------------------
align 4
TCP_500ms:
TCP_timer_640ms:
 
; Update TCP sequence number
 
add [TCP_sequence_num], 64000
 
ret
; scan through all the active TCP sockets, decrementing ALL timers
; timers do not have the chance to wrap because of the keepalive timer will kill the socket when it expires
 
mov eax, net_sockets
.loop:
mov eax, [eax + SOCKET.NextPtr]
.check_only:
or eax, eax
jz .exit
 
cmp [eax + SOCKET.Type], IP_PROTO_TCP
jne .loop
 
;----------------------
;
; TCP_10ms
;
;----------------------
align 4
TCP_10ms:
dec [eax + TCP_SOCKET.timer_retransmission]
jnz .check_more2
 
; todo: decrease timers
DEBUGF 1,"socket %x: Retransmission timer expired\n", eax
 
ret
push eax
call TCP_output
pop eax
 
.check_more2:
dec [eax + TCP_SOCKET.timer_keepalive]
jnz .check_more3
 
DEBUGF 1,"socket %x: Keepalive expired\n", eax
 
;;; TODO: check socket state and handle accordingly
 
.check_more3:
dec [eax + TCP_SOCKET.timer_timed_wait]
jnz .check_more5
 
DEBUGF 1,"socket %x: 2MSL timer expired\n", eax
 
.check_more5:
dec [eax + TCP_SOCKET.timer_persist]
jnz .loop
 
DEBUGF 1,"socket %x: persist timer expired\n", eax
 
jmp .loop
.exit:
ret
 
 
;-----------------------------------------------------------------
;
; TCP_input:
374,8 → 400,9
;-------------------------------------
; Reset idle timer and keepalive timer
 
;;;; TODO: idle timer?
 
; TODO
mov [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval
 
;-----------------------------------------
; Process TCP options if not in LISTEN state
475,14 → 502,15
; Delete acknowledged bytes from send buffer
 
; Stop retransmit timer
mov [ebx + TCP_SOCKET.timer_ack], 0
 
; Awaken waiting processes
mov eax, ebx
call SOCKET_notify_owner
 
; Generate more output
call TCP_output
 
 
 
 
jmp .drop
 
 
518,9 → 546,10
add [ebx + TCP_SOCKET.RCV_NXT], ecx
 
; Add the data to the socket buffer
mov eax, ebx
;;; mov...
call SOCKET_input
 
; The receiving process is awakened (by sorwakeup).
 
; The delayed-ACK flag is set and the input processing is complete.
 
jmp .drop
679,9 → 708,9
jle @f
mov [ebx + TCP_SOCKET.SND_NXT], eax
 
mov [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval
mov [ebx + TCP_SOCKET.timer_retransmission], 0
 
; TODO: turn off retransmission timer
 
mov eax, [edx + TCP_segment.SequenceNumber]
mov [ebx + TCP_SOCKET.IRS], eax
 
937,18 → 966,6
jg .ack_dup
jl .ack_nodup
 
; dd .ack_nodup ;TCB_CLOSED
; dd .ack_nodup ;TCB_LISTEN
; dd .ack_nodup ;TCB_SYN_SENT
; dd .ack_syn_rcvd ;TCB_SYN_RECEIVED
; dd .ack_dup ;TCB_ESTABLISHED
; dd .ack_dup ;TCB_CLOSE_WAIT
; dd .ack_dup ;TCB_FIN_WAIT_1
; dd .ack_dup ;TCB_CLOSING
; dd .ack_dup ;TCB_LAST_ACK
; dd .ack_dup ;TCB_FIN_WAIT_2
; dd .ack_dup ;TCB_TIMED_WAIT
 
;;;;;
 
.ack_dup:
960,7 → 977,7
;;;; 887
 
;-------------------------------------------------
; If the congestion window was infalted to account
; If the congestion window was inflated to account
; for the other side's cached packets, retrace it
 
;;;; 888 - 902
971,7 → 988,15
 
;;;;; 903 - 926
 
mov [ebx + TCP_SOCKET.timer_retransmission], 0
 
mov eax, [ebx + TCP_SOCKET.SND_MAX]
cmp eax, [edx + TCP_segment.AckNumber]
je .all_outstanding
mov [ebx + TCP_SOCKET.timer_retransmission], 120 ;;;; TODO: correct this value
.all_outstanding:
 
 
;-------------------------------------------
; Open congestion window in response to ACKs
 
1614,7 → 1639,7
 
.enter_persist:
 
DEBUGF 1,"Entering pesist state\n"
DEBUGF 1,"Entering persist state\n"
 
 
 
1748,7 → 1773,7
;;;; jz .fail
 
push edx eax
call NET_send
call [ebx + NET_DEVICE.transmit]
ret
 
;----------------
1831,12 → 1856,9
 
 
DEBUGF 1,"Sending TCP Packet to device %x\n", ebx
mov esi, [ebx + ETH_DEVICE.transmit]
 
call [ebx + NET_DEVICE.transmit]
ret
 
 
 
;-------------------------
;
; TCP_outflags
1902,11 → 1924,14
 
;---------------------------------------
;
; TCP_respond
; TCP_ack
;
; The easy way to send a RST/ACK segment
; The easy way to send an ACK/RST/keepalive segment
;
; IN: eax = socket ptr
; -or-
; edx = packet ptr (eax must be 0)
; cl = flags
;
; OUT: /
;
1916,10 → 1941,117
 
DEBUGF 1,"TCP_respond\n"
 
;---------------------
; Create the IP packet
 
push cx eax edx
mov ebx, [eax + IP_SOCKET.LocalIP]
mov eax, [eax + IP_SOCKET.RemoteIP]
mov ecx, TCP_segment.Data
mov di , IP_PROTO_TCP
call IPv4_create_packet
test edi, edi
jz .error
 
;---------------------------
; Now fill in the TCP header
 
pop ecx
pop esi
 
test esi, esi
; jz
 
 
push edx eax
 
push dword .checksum
je .use_segment
jmp .use_socket
 
;---------------------
; Fill in the checksum
 
.checksum:
 
push [esi + IP_SOCKET.LocalIP]
push [esi + IP_SOCKET.RemoteIP]
lea esi, [edi - 20]
xor ecx, ecx
call TCP_checksum
 
;--------------------
; And send the segment
 
call [ebx + NET_DEVICE.transmit]
ret
 
.error:
DEBUGF 1,"TCP_ack failed\n"
add esp, 4
 
ret
 
;---------------------------------------------------
; Fill in the TCP header by using a received segment
 
.use_segment:
 
mov ax, [esi + TCP_segment.DestinationPort]
rol ax, 8
stosw
mov ax, [esi + TCP_segment.SourcePort]
rol ax, 8
stosw
mov eax, [esi + TCP_segment.AckNumber]
bswap eax
stosd
xor eax, eax
stosd
mov al, 0x50 ; Dataoffset: 20 bytes
stosb
mov al, cl
stosb
mov ax, 1280
rol ax, 8
stosw ; window
xor eax, eax
stosd ; checksum + urgentpointer
 
ret
 
 
;-----------------------------------------------
; Fill in the TCP header by using the socket ptr
 
.use_socket:
 
mov ax, [esi + TCP_SOCKET.LocalPort]
rol ax, 8
stosw
mov ax, [esi + TCP_SOCKET.RemotePort]
rol ax, 8
stosw
mov eax, [esi + TCP_SOCKET.SND_NXT]
bswap eax
stosd
mov eax, [esi + TCP_SOCKET.RCV_NXT]
bswap eax
stosd
mov al, 0x50 ; Dataoffset: 20 bytes
stosb
mov al, cl
stosb
mov ax, [esi + TCP_SOCKET.RCV_WND]
rol ax, 8
stosw ; window
xor eax, eax
stosd ; checksum + urgentpointer
 
ret
 
 
 
;-----------------------------------------------------------------
;
; TCP_checksum