Net-branch:

Fixed Bugs in checksum, introduced in #1473
Checksum for IP/UDP/TCP is now very fast.


git-svn-id: svn://kolibrios.org@1482 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
hidnplayr 2010-06-07 09:37:13 +00:00
parent 049d796e81
commit 34c194bda4
3 changed files with 149 additions and 195 deletions

View File

@ -140,7 +140,7 @@ IPv4_handler: ; TODO: implement handler for IP options
; Re-calculate checksum
push edx ebx
mov esi, edx
call checksum_ip_header
call IPv4_checksum
pop ebx edx
; now see if it was correct
@ -611,7 +611,7 @@ IPv4_create_packet:
push eax edx esi
mov esi, edi
call checksum_ip_header
call IPv4_checksum
pop esi edx eax ecx
add edi, IPv4_Packet.DataOrOptional
@ -632,6 +632,58 @@ IPv4_create_packet:
align 4
IPv4_checksum:
; This is the fast procedure to create or check a IP header without options
;
; To create a new checksum, the checksum field must be set to 0 before computation
;
; To check an existing checksum, leave the checksum as is, and it will be 0 after this procedure, if it was correct
xor edx, edx
add dl, [esi+1]
adc dh, [esi+0]
adc dl, [esi+3]
adc dh, [esi+2]
adc dl, [esi+5]
adc dh, [esi+4]
adc dl, [esi+7]
adc dh, [esi+6]
adc dl, [esi+9]
adc dh, [esi+8]
; we skip 11th and 12th byte, they are the checksum bytes and should be 0 for re-calculation
adc dl, [esi+13]
adc dh, [esi+12]
adc dl, [esi+15]
adc dh, [esi+14]
adc dl, [esi+17]
adc dh, [esi+16]
adc dl, [esi+19]
adc dh, [esi+18]
adc edx, 0
call checksum_2
neg word [esi+10] ; zero will stay zero so we just get the checksum
add word [esi+10], dx ; , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
ret
;---------------------------------------------------------------------------
;

View File

@ -208,7 +208,7 @@ end if
;
; checksum_1
;
; This is the first of two functions needed to calculate the TCP checksum.
; This is the first of two functions needed to calculate a checksum.
;
; IN: edx = start offset for semi-checksum
; esi = pointer to data
@ -289,151 +289,6 @@ checksum_1:
.end:
ret
;IN: 12 bytes of pseudoheader pushed onto the stack
; edx = start offset
;
; OUT: pseudochecksum in edx
align 4
checksum_pseudoheader:
add dl, [esp+5]
adc dh, [esp+4]
adc dl, [esp+7]
adc dh, [esp+6]
adc dl, [esp+9]
adc dh, [esp+8]
adc dl, [esp+11]
adc dh, [esp+10]
adc dl, [esp+13]
adc dh, [esp+12]
adc dl, [esp+15]
adc dh, [esp+14]
adc edx,0
ret 12
align 4
checksum_ip_header:
; This is the fast procedure to create or check a IP header without options
;
; To create a new checksum, the checksum field must be set to 0 before computation
;
; To check an existing checksum, leave the checksum as is, and it will be 0 after this procedure, if it was correct
xor edx, edx
add dl, [esi+1]
adc dh, [esi+0]
adc dl, [esi+3]
adc dh, [esi+2]
adc dl, [esi+5]
adc dh, [esi+4]
adc dl, [esi+7]
adc dh, [esi+6]
adc dl, [esi+9]
adc dh, [esi+8]
; we skip 11th and 12th byte, they are the checksum bytes and should be 0 for re-calculation
adc dl, [esi+13]
adc dh, [esi+12]
adc dl, [esi+15]
adc dh, [esi+14]
adc dl, [esi+17]
adc dh, [esi+16]
adc dl, [esi+19]
adc dh, [esi+18]
adc edx, 0
call checksum_2
neg word [esi+10] ; zero will stay zero so we jsut get the checksum
add word [esi+10], dx ; , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
ret
align 4
checksum_udp:
; This is the fast procedure to create or check a IP header without options
;
; To create a new checksum, the checksum field must be set to 0 before computation
;
; To check an existing checksum, leave the checksum as is, and it will be 0 after this procedure, if it was correct
xor edx, edx
add dl, [esi+1]
adc dh, [esi+0]
adc dl, [esi+3]
adc dh, [esi+2]
adc dl, [esi+5]
adc dh, [esi+4]
adc dl, [esi+7]
adc dh, [esi+6]
adc dl, [esi+9]
adc dh, [esi+8]
; we skip 11th and 12th byte, they are the checksum bytes and should be 0 for re-calculation
adc dl, [esi+13]
adc dh, [esi+12]
adc dl, [esi+15]
adc dh, [esi+14]
adc dl, [esi+17]
adc dh, [esi+16]
adc dl, [esi+19]
adc dh, [esi+18]
adc edx, 0
call checksum_2
neg word [esi+10] ; zero will stay zero so we jsut get the checksum
add word [esi+10], dx ; , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
ret
;-----------------------------------------------------------------
;
; checksum_2
@ -451,9 +306,10 @@ checksum_2:
shr ecx, 16
and edx, 0xffff
add edx, ecx
mov eax, edx
shr eax, 16
add edx, eax
mov ecx, edx
shr ecx, 16
add edx, ecx
not dx
jnz .not_zero

View File

@ -67,43 +67,32 @@ UDP_init:
; size of buffer in [esp+4]
; pointer to device struct in ebx
; UDP Packet size in ecx
; pointer to UDP Packet data in edx
; pointer to UDP Packet in edx
; OUT: /
;
;-----------------------------------------------------------------
align 4
UDP_handler:
DEBUGF 1,"UDP_Handler\n"
DEBUGF 1,"UDP_Handler, checksum:%x\n", [edx+UDP_Packet.Checksum]:4
cmp [edx + UDP_Packet.Checksum], 0
jz .no_checksum
; First validate, checksum:
; First validate, checksum:
cmp [edx + UDP_Packet.Checksum], 0
jz .no_checksum
pusha
push ecx edx
push cx
rol word [esp], 8
push word IP_PROTO_UDP shl 8
push edi
push esi
mov di, [edx + UDP_Packet.Checksum]
mov [edx + UDP_Packet.Checksum], 0
push edi
mov esi, edx
xor edx, edx
call checksum_1
call checksum_pseudoheader
call checksum_2
call UDP_checksum
cmp di, dx
popa
jne .checksum_mismatch ;dump
pop edx ecx
cmp [edx + UDP_Packet.Checksum], 0
jnz .checksum_mismatch
.no_checksum:
DEBUGF 1,"UDP Checksum is correct\n"
; Look for a socket where
@ -190,12 +179,11 @@ UDP_handler:
DEBUGF 2,"UDP_Handler - checksum mismatch\n"
mov esi, [esp]
mov ecx, [esp + 4]
@@: ;
lodsb ;
DEBUGF 2,"%x ", eax:2 ;
loop @r ;
; mov esi, edx
; @@: ;
; lodsb ;
; DEBUGF 2,"%x ", eax:2 ;
; loop @r ;
.dump:
call kernel_free
@ -230,9 +218,7 @@ UDP_socket_send:
DEBUGF 1,"Create UDP Packet (size=%u)\n",ecx
mov di , IP_PROTO_UDP
sub esp, 8 ; reserve some place in stack for later
; Create a part of the pseudoheader in stack,
push dword IP_PROTO_UDP shl 8
sub esp, 8 ; Data ptr and data size will be placed here
add ecx, UDP_Packet.Data
; TODO: fill in: dx = fragment id
@ -242,12 +228,11 @@ UDP_socket_send:
cmp edi, -1
je .fail
mov [esp + 8 + 4], eax ; pointer to buffer start
mov [esp + 8 + 4 + 4], edx ; buffer size
mov [esp + 8], eax ; pointer to buffer start
mov [esp + 8 + 4], edx ; buffer size
rol cx, 8
mov [edi + UDP_Packet.Length], cx
mov [esp + 8 + 2], cx
ror cx, 8
pop esi
@ -264,22 +249,16 @@ UDP_socket_send:
pop dword [edi + UDP_Packet.SourcePort] ; fill in both portnumbers
mov [edi + UDP_Packet.Checksum], 0 ; set it to zero, to calculate checksum
; Checksum for UDP header + data
xor edx, edx
; Checksum
mov esi, edi
call checksum_1
; Checksum for pseudoheader
pushd [edi-4] ; destination address ; TODO: fix this, IPv4 packet could have options..
pushd [edi-8] ; source address
call checksum_pseudoheader
; Now create the final checksum and store it in UDP header
call checksum_2
mov [edi + UDP_Packet.Checksum], dx
call UDP_checksum
inc [UDP_PACKETS_TX]
DEBUGF 1,"Sending UDP Packet to device %x\n", ebx ;
jmp ETH_sender ;
DEBUGF 1,"Sending UDP Packet to device %x\n", ebx
jmp ETH_sender
.fail:
; todo: queue the packet
@ -289,6 +268,73 @@ UDP_socket_send:
;-----------------------------------------------------------------
;
; checksum_udp
;
; This is the fast procedure to create or check a UDP header
; - To create a new checksum, the checksum field must be set to 0 before computation
; - To check an existing checksum, leave the checksum as is,
; and it will be 0 after this procedure, if it was correct
;
; IN: push source ip
; push dest ip
; esi = packet ptr
;
; OUT: checksum is filled in in packet! (but also in dx)
;
;-----------------------------------------------------------------
align 4
UDP_checksum:
; Pseudoheader
mov edx, IP_PROTO_UDP ; NO shl 8 here ! (it took me ages to figure this one out)
add dl, [esp+1+4]
adc dh, [esp+0+4]
adc dl, [esp+3+4]
adc dh, [esp+2+4]
adc dl, [esp+1+8]
adc dh, [esp+0+8]
adc dl, [esp+3+8]
adc dh, [esp+2+8]
adc dl, byte[esi+UDP_Packet.Length+1]
adc dh, byte[esi+UDP_Packet.Length+0]
; Done with pseudoheader, now do real header
adc dl, byte[esi+UDP_Packet.SourcePort+1]
adc dh, byte[esi+UDP_Packet.SourcePort+0]
adc dl, byte[esi+UDP_Packet.DestinationPort+1]
adc dh, byte[esi+UDP_Packet.DestinationPort+0]
adc dl, byte[esi+UDP_Packet.Length+1]
adc dh, byte[esi+UDP_Packet.Length+0]
adc edx, 0
; Done with header, now do data
push esi
movzx ecx, [esi+UDP_Packet.Length]
rol cx , 8
sub cx , UDP_Packet.Data
add esi, UDP_Packet.Data
call checksum_1
call checksum_2
pop esi
neg [esi+UDP_Packet.Checksum] ; zero will stay zero so we just get the checksum
add [esi+UDP_Packet.Checksum], dx ; , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
ret 8
;---------------------------------------------------------------------------
;
; UDP_API