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 ; Re-calculate checksum
push edx ebx push edx ebx
mov esi, edx mov esi, edx
call checksum_ip_header call IPv4_checksum
pop ebx edx pop ebx edx
; now see if it was correct ; now see if it was correct
@ -611,7 +611,7 @@ IPv4_create_packet:
push eax edx esi push eax edx esi
mov esi, edi mov esi, edi
call checksum_ip_header call IPv4_checksum
pop esi edx eax ecx pop esi edx eax ecx
add edi, IPv4_Packet.DataOrOptional 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 ; 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 ; IN: edx = start offset for semi-checksum
; esi = pointer to data ; esi = pointer to data
@ -289,151 +289,6 @@ checksum_1:
.end: .end:
ret 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 ; checksum_2
@ -451,9 +306,10 @@ checksum_2:
shr ecx, 16 shr ecx, 16
and edx, 0xffff and edx, 0xffff
add edx, ecx add edx, ecx
mov eax, edx
shr eax, 16 mov ecx, edx
add edx, eax shr ecx, 16
add edx, ecx
not dx not dx
jnz .not_zero jnz .not_zero

View File

@ -67,43 +67,32 @@ UDP_init:
; size of buffer in [esp+4] ; size of buffer in [esp+4]
; pointer to device struct in ebx ; pointer to device struct in ebx
; UDP Packet size in ecx ; UDP Packet size in ecx
; pointer to UDP Packet data in edx ; pointer to UDP Packet in edx
; OUT: / ; OUT: /
; ;
;----------------------------------------------------------------- ;-----------------------------------------------------------------
align 4 align 4
UDP_handler: UDP_handler:
DEBUGF 1,"UDP_Handler\n" DEBUGF 1,"UDP_Handler, checksum:%x\n", [edx+UDP_Packet.Checksum]:4
; First validate, checksum:
cmp [edx + UDP_Packet.Checksum], 0 cmp [edx + UDP_Packet.Checksum], 0
jz .no_checksum jz .no_checksum
; First validate, checksum:
pusha push ecx edx
push cx
rol word [esp], 8
push word IP_PROTO_UDP shl 8
push edi
push esi push esi
push edi
mov di, [edx + UDP_Packet.Checksum]
mov [edx + UDP_Packet.Checksum], 0
mov esi, edx mov esi, edx
xor edx, edx call UDP_checksum
call checksum_1
call checksum_pseudoheader
call checksum_2
cmp di, dx pop edx ecx
popa
jne .checksum_mismatch ;dump
cmp [edx + UDP_Packet.Checksum], 0
jnz .checksum_mismatch
.no_checksum: .no_checksum:
DEBUGF 1,"UDP Checksum is correct\n" DEBUGF 1,"UDP Checksum is correct\n"
; Look for a socket where ; Look for a socket where
@ -190,12 +179,11 @@ UDP_handler:
DEBUGF 2,"UDP_Handler - checksum mismatch\n" DEBUGF 2,"UDP_Handler - checksum mismatch\n"
mov esi, [esp] ; mov esi, edx
mov ecx, [esp + 4] ; @@: ;
@@: ; ; lodsb ;
lodsb ; ; DEBUGF 2,"%x ", eax:2 ;
DEBUGF 2,"%x ", eax:2 ; ; loop @r ;
loop @r ;
.dump: .dump:
call kernel_free call kernel_free
@ -230,9 +218,7 @@ UDP_socket_send:
DEBUGF 1,"Create UDP Packet (size=%u)\n",ecx DEBUGF 1,"Create UDP Packet (size=%u)\n",ecx
mov di , IP_PROTO_UDP mov di , IP_PROTO_UDP
sub esp, 8 ; reserve some place in stack for later sub esp, 8 ; Data ptr and data size will be placed here
; Create a part of the pseudoheader in stack,
push dword IP_PROTO_UDP shl 8
add ecx, UDP_Packet.Data add ecx, UDP_Packet.Data
; TODO: fill in: dx = fragment id ; TODO: fill in: dx = fragment id
@ -242,12 +228,11 @@ UDP_socket_send:
cmp edi, -1 cmp edi, -1
je .fail je .fail
mov [esp + 8 + 4], eax ; pointer to buffer start mov [esp + 8], eax ; pointer to buffer start
mov [esp + 8 + 4 + 4], edx ; buffer size mov [esp + 8 + 4], edx ; buffer size
rol cx, 8 rol cx, 8
mov [edi + UDP_Packet.Length], cx mov [edi + UDP_Packet.Length], cx
mov [esp + 8 + 2], cx
ror cx, 8 ror cx, 8
pop esi pop esi
@ -264,22 +249,16 @@ UDP_socket_send:
pop dword [edi + UDP_Packet.SourcePort] ; fill in both portnumbers pop dword [edi + UDP_Packet.SourcePort] ; fill in both portnumbers
mov [edi + UDP_Packet.Checksum], 0 ; set it to zero, to calculate checksum mov [edi + UDP_Packet.Checksum], 0 ; set it to zero, to calculate checksum
; Checksum for UDP header + data ; Checksum
xor edx, edx
mov esi, edi mov esi, edi
call checksum_1
; Checksum for pseudoheader
pushd [edi-4] ; destination address ; TODO: fix this, IPv4 packet could have options.. pushd [edi-4] ; destination address ; TODO: fix this, IPv4 packet could have options..
pushd [edi-8] ; source address pushd [edi-8] ; source address
call checksum_pseudoheader call UDP_checksum
; Now create the final checksum and store it in UDP header
call checksum_2
mov [edi + UDP_Packet.Checksum], dx
inc [UDP_PACKETS_TX] inc [UDP_PACKETS_TX]
DEBUGF 1,"Sending UDP Packet to device %x\n", ebx ; DEBUGF 1,"Sending UDP Packet to device %x\n", ebx
jmp ETH_sender ; jmp ETH_sender
.fail: .fail:
; todo: queue the packet ; 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 ; UDP_API