Cálculo del campo de checksum en el header de TCP

Ejercicio: De acuerdo con el RFC793, Transmission Control Protocol, ¿cúal sería el checksum para el siguiente segmento TCP? (La información mostrada está dentro de un frame Ethernet V2 y no se muestra el checksum del header TCP,  ni el CRC ni el preámbulo para Ethernet). Este segmento no lleva datos, es el primer segmento del three-way handshake de TCP.

            Offset: Hexadecimal                                ASCII
      ------- -----------                                -----
           0: 0800 2073 5ec6 00e0 1ede 72d6 0800 4500    .. s^.....r...E.
          16: 0030 6e1e 4000 7f06 35c4 a8b0 036c a8b0    .0n.@...5....l..
          32: 0319 0593 0015 008a ca9b 0000 0000 7002    ..............p.
          48: 2000 ____ 0000 0204 0218 0101 0402          .>...........

Solución: Recordemos que el texto del RFC793 dice lo siguiente acerca del cálculo del campo del checksum para TCP:

[...]
Checksum:  16 bits

    The checksum field is the 16 bit one's complement of the one's
    complement sum of all 16 bit words in the header and text.  If a
    segment contains an odd number of header and text octets to be
    checksummed, the last octet is padded on the right with zeros to
    form a 16 bit word for checksum purposes.  The pad is not
    transmitted as part of the segment.  While computing the checksum,
    the checksum field itself is replaced with zeros.

    The checksum also covers a 96 bit pseudo header conceptually
    prefixed to the TCP header.  This pseudo header contains the Source
    Address, the Destination Address, the Protocol, and TCP length.
    This gives the TCP protection against misrouted segments.  This
    information is carried in the Internet Protocol and is transferred
    across the TCP/Network interface in the arguments or results of
    calls by the TCP on the IP.

                     +--------+--------+--------+--------+
                     |           Source Address          |
                     +--------+--------+--------+--------+
                     |         Destination Address       |
                     +--------+--------+--------+--------+
                     |  zero  |  PTCL  |    TCP Length   |
                     +--------+--------+--------+--------+

      The TCP Length is the TCP header length plus the data length in
      octets (this is not an explicitly transmitted quantity, but is
      computed), and it does not count the 12 octets of the pseudo
      header.
[...]
Es decir que el checksum para TCP se calcula sobre los octetos que componen un seudo-header, el header de TCP y los datos (que se deben completar con ceros al final si es necesario).

También debemos recordar los formatos del frame Ethernet, el header IPv4 y el header de TCP:

  • Formato del frame Ethernet (el tamaño de los campos está en bytes)
  • Formato del header de IPv4
  • Formato del header TCP
  • Ahora debemos separar nuestro frame en su componentes: header Ethernet, Header IPv4, Header UDP y Datos:
            0800 2073 5ec6 00e0 1ede 72d6 0800 ===> Header del frame Ethernet
    
            4500 0030  \
            6e1e 4000  |
            7f06 35c4   > Header IPv4
            a8b0 036c  |
            a8b0 0319  /
            0593 0015    Header TCP
            008a ca9b
            0000 0000
            7002 2000
            ____ 0000
            0204 0218
            0101 0402

            y no hay datos...

    De acuerdo con el RFC793  el seudo-header de este mensaje sería:

    a8b0 036c   ===> Dirección IP origen
    a8b0 0319   ===> Dirección IP destino
    0006 ????   ===> cero + número de protocolo (6 decimal) + longitud segmento TCP (que debemos calcular sumando el header TCP y los datos transportados por TCP)

    Para calcular la longitud del segmento TCP, en este ejercicio, simplemente miramos que el header de TCP lleva 28 bytes y no transporta datos (en hexadecimal se expresaría como 1C). El seudo-header completo será:

    a8b0 036c   ===> Dirección IP origen
    a8b0 0319   ===> Dirección IP destino
    0006 001c   ===> cero + número de protocolo (6 decimal) + longitud segmento TCP (header TCP + los datos transportados)

    Ahora debemos sumar, con aritmetica complemento a uno, el seudo-header + el header TCP + los datos TCP, como palabras de 16 bits

    Suma con aritmética complemento a uno del seudoheader

       [Hex]    Binario
       [a8b0]   1010100010110000
       [036c]   0000001101101100
       [a8b0]   1010100010110000
       [0319]   0000001100011001
       [0006]   0000000000000110
       [001c]   0000000000011100
      [15807]  10101100000000111

    En la aritmética complemento a uno, cuando una operación genera un acarreo (carry) en el bit más significativo, se debe incrementar el resultado

        [5807]   0101100000000111
                                1
        [5808]   0101100000001000

    Suma con aritmética complemento a uno del header TCP

    Nota: En este momento el campo de checksum está en 0000000000000000

       [Hex]    Binario
       [0593]   0000010110010011
       [0015]   0000000000010101
       [008a]   0000000010001010
       [ca9b]   1100101010011011
       [0000]   0000000000000000
       [0000]   0000000000000000
       [7002]   0111000000000010
       [2000]   0010000000000000
       [0000]   0000000000000000
       [0000]   0000000000000000
       [0204]   0000001000000100
       [0218]   0000001000011000
       [0101]   0000000100000001
       [0402]   0000010000000010
      [169EE]  10110100111101110   --> 0110100111101110 + 1 = 0110100111101111 [69EF]

    Suma con aritmética complemento a uno de los datos transportados por TCP

    En el segmento que estamos utilizando no se llevan datos (es el primer segmento del three-way handshake de TCP).  Para recordar que los datos trabsportados también se suman para calcular el checksum, aquí lo incluiremos con un valor de cero.

       [0000]   0000000000000000

    Y por fin, el checksum...

    Para calcular el checksum debemos hacer dos cosas ahora, sumar los resultados obtenidos con el seudo-header, el header TCP y los datos y, finalmente, calcular el complemento a uno.

    1. Suma de los resultados obtenidos con el  seudo-header, el header TCP y los datos

       [5808]   0101100000001000
       [69EF]   0110100111101111
       [0000]  0000000000000000
       [C1F7]   1100000111110111

    El complemento a uno se obtiene convirtiendo todos los ceros en unos y todos los unos en cero. De esta forma, el complemento a uno de1100000111110111 es 11111000001000. Que vendría a ser el checksum: el hexadecimal 3E08.

    Así que el frame completo sería:


               Offset: Hexadecimal                                ASCII
          ------- -----------                                -----
               0: 0800 2073 5ec6 00e0 1ede 72d6 0800 4500    .. s^.....r...E.
              16: 0030 6e1e 4000 7f06 35c4 a8b0 036c a8b0    .0n.@...5....l..
              32: 0319 0593 0015 008a ca9b 0000 0000 7002    ..............p.
              48: 2000 3e08 0000 0204 0218 0101 0402          .>...........

    [Algoritmo de checksum de Internet]
    [Checksum en IP]
    [Checksum en UDP]
    [Checksum en TCP]



    ©Oscar Agudelo.  2000-2003. Todos los derechos reservados.