From c10e7c783c248400893ed2b13e20f67f4d57750b Mon Sep 17 00:00:00 2001 From: hidnplayr Date: Tue, 28 Aug 2012 19:56:28 +0000 Subject: [PATCH] rewrote TCP option parser, added SACK, moved connection accepter to run before option parser. git-svn-id: svn://kolibrios.org@2954 a494cfbc-eb01-0410-851d-a64ba20cac60 --- kernel/branches/net/network/tcp_input.inc | 173 ++++++++++++---------- 1 file changed, 93 insertions(+), 80 deletions(-) diff --git a/kernel/branches/net/network/tcp_input.inc b/kernel/branches/net/network/tcp_input.inc index bcda6fe9ab..0a37da541d 100644 --- a/kernel/branches/net/network/tcp_input.inc +++ b/kernel/branches/net/network/tcp_input.inc @@ -159,7 +159,35 @@ TCP_input: ; Are we accepting incoming connections? test [ebx + SOCKET.options], SO_ACCEPTCON - jnz .accept_connection + jz .no_accept + + DEBUGF 1,"TCP_input: Accepting new connection\n" + + pusha + lea ecx, [ebx + SOCKET.mutex] + call mutex_unlock + popa + + push ecx edx esi edi ;;; + call SOCKET_fork + pop edi esi edx ecx + + test eax, eax + jz .drop_no_socket + + mov ebx, eax + + mov [ebx + TCP_SOCKET.temp_bits], TCP_BIT_DROPSOCKET ;;; FIXME: should we take over bits from previous socket? + + push dword [edi + 4] ; Ipv4 destination addres + pop [ebx + IP_SOCKET.LocalIP] + + push [edx + TCP_header.DestinationPort] + pop [ebx + TCP_SOCKET.LocalPort] + + mov [ebx + TCP_SOCKET.t_state], TCPS_LISTEN + .no_accept: + ;------------------------------------- ; Reset idle timer and keepalive timer @@ -170,85 +198,108 @@ TCP_input: ;-------------------- ; Process TCP options - movzx eax, [edx + TCP_header.DataOffset] - cmp eax, sizeof.TCP_header ; Does header contain any options? + push ecx + + movzx ecx, [edx + TCP_header.DataOffset] + cmp ecx, sizeof.TCP_header ; Does header contain any options? je .no_options DEBUGF 1,"TCP_input: Segment has options\n" - cmp [ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state - jz .not_uni_xfer ; also no header prediction +;;; 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 eax, edx + add ecx, edx lea esi, [edx + sizeof.TCP_header] .opt_loop: - cmp esi, eax ; are we scanning outside of header? + cmp esi, ecx ; are we scanning outside of header? jae .no_options - - cmp byte [esi], TCP_OPT_EOL ; end of option list? - jz .no_options - - cmp byte [esi], TCP_OPT_NOP ; nop ? - jz .opt_nop - - cmp byte [esi], TCP_OPT_MAXSEG + lodsb + cmp al, TCP_OPT_EOL ; end of option list? + je .no_options + cmp al, TCP_OPT_NOP + je .opt_loop + cmp al, TCP_OPT_MAXSEG je .opt_maxseg - - cmp byte [esi], TCP_OPT_WINDOW + cmp al, TCP_OPT_WINDOW je .opt_window - - cmp byte [esi], TCP_OPT_TIMESTAMP + cmp al, TCP_OPT_SACK_PERMIT + je .opt_sack_permit +; cmp al, TCP_OPT_SACK +; je .opt_sack + cmp al, TCP_OPT_TIMESTAMP je .opt_timestamp - + DEBUGF 1,"TCP_input: unknown option:%u\n", al jmp .no_options ; If we reach here, some unknown options were received, skip them all! - .opt_nop: - inc esi - jmp .opt_loop - .opt_maxseg: - cmp byte [esi+1], 4 + lodsb + cmp al, 4 jne .no_options ; error occured, ignore all options! test [edx + TCP_header.Flags], TH_SYN jz @f - movzx eax, word[esi+2] + lodsw rol ax, 8 DEBUGF 1,"TCP_input: Maxseg=%u\n", ax mov [ebx + TCP_SOCKET.t_maxseg], eax - @@: - add esi, 4 jmp .opt_loop .opt_window: - cmp byte [esi+1], 3 + lodsb + cmp al, 3 jne .no_options test [edx + TCP_header.Flags], TH_SYN jz @f - DEBUGF 1,"TCP_input: Got window option\n" + DEBUGF 1,"TCP_input: Got window scale option\n" + or [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE + + lodsb + mov [ebx + TCP_SOCKET.SND_SCALE], al + ;;;;; TODO + + @@: + jmp .opt_loop + + + .opt_sack_permit: + lodsb + cmp al, 2 + jne .no_options + + test [edx + TCP_header.Flags], TH_SYN + jz @f + + DEBUGF 1,"TCP_input: Selective Acknowledgement permitted\n" + or [ebx + TCP_SOCKET.t_flags], TF_SACK_PERMIT - ;;;;; @@: - add esi, 3 jmp .opt_loop .opt_timestamp: - cmp byte [esi+1], 10 ; length must be 10 + lodsb + cmp al, 10 ; length must be 10 jne .no_options DEBUGF 1,"TCP_input: Got timestamp option\n" - push dword [esi + 2] ; timestamp - pop [ebx + TCP_SOCKET.ts_val] - push dword [esi + 6] ; timestamp echo reply - pop [ebx + TCP_SOCKET.ts_ecr] + test [edx + TCP_header.Flags], TH_SYN + jz @f + or [ebx + TCP_SOCKET.t_flags], TF_RCVD_TSTMP + @@: + + lodsd + mov [ebx + TCP_SOCKET.ts_val], eax + lodsd ; timestamp echo reply + mov [ebx + TCP_SOCKET.ts_ecr], eax or [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP ; Since we have a timestamp, lets do the paws test right away! @@ -264,19 +315,19 @@ TCP_input: DEBUGF 1,"TCP_input: PAWS: detected an old segment\n" - mov eax, [esp+4+4] ; tcp_now + mov eax, [esp+4+4+4] ; tcp_now sub eax, [ebx + TCP_SOCKET.ts_recent_age] cmp eax, TCP_PAWS_IDLE jle .drop_after_ack ; TODO: update stats mov [ebx + TCP_SOCKET.ts_recent], 0 ; timestamp was invalid, fix it. .no_paws: - - add esi, 10 jmp .opt_loop .no_options: + pop ecx + ;----------------------------------------------------------------------- ; Time to do some header prediction (Original Principle by Van Jacobson) @@ -1038,37 +1089,8 @@ TCP_input: -;------------- -; Passive Open -align 4 - .accept_connection: - - DEBUGF 1,"TCP_input: Accepting new connection\n" - - pusha - lea ecx, [ebx + SOCKET.mutex] - call mutex_unlock - popa - - push ecx edx esi edi ;;; - call SOCKET_fork - pop edi esi edx ecx - - test eax, eax - jz .drop - - mov [eax + TCP_SOCKET.temp_bits], TCP_BIT_DROPSOCKET ;;; FIXME: should we take over bits from previous socket? - - push dword [edi + 4] ; Ipv4 destination addres - pop [eax + IP_SOCKET.LocalIP] - - push [edx + TCP_header.DestinationPort] - pop [eax + TCP_SOCKET.LocalPort] - - mov [eax + TCP_SOCKET.t_state], TCPS_LISTEN - mov ebx, eax .LISTEN: @@ -1262,17 +1284,13 @@ align 4 ja .no_window_update @@: - mov eax, [ebx + TCP_SOCKET.SND_WL2] - cmp eax, [edx + TCP_header.AckNumber] - jne .no_window_update - mov eax, dword [edx + TCP_header.Window] cmp eax, [ebx + TCP_SOCKET.SND_WND] jbe .no_window_update .update_window: -;;; TODO: Keep track of pure window updates +;;; TODO: update stats (Keep track of pure window updates) mov eax, dword [edx + TCP_header.Window] cmp eax, [ebx + TCP_SOCKET.max_sndwnd] @@ -1293,12 +1311,6 @@ align 4 .no_window_update: - - - - - - ;----------------- ; process URG flag @@ -1464,6 +1476,7 @@ align 4 DEBUGF 1,"TCP_input: ACK now!\n" .need_output: + DEBUGF 1,"TCP_input: need output\n" call TCP_output .dumpit: