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


Ejercicio: De acuerdo con el RFC768, User Datagram Protocol, ¿cúal sería el checksum para el siguiente mensaje UDP? (La información mostrada está dentro de un frame Ethernet V2 y no se muestra el checksum del header UDP,  ni el CRC ni el preámbulo para Ethernet)

            Offset: Hexadecimal                                ASCII
      ------- -----------                                -----
           0: 0260 8ce8 5533 0800 2073 5ec6 0800 4500    .`..U3.. s^...E.
          16: 0047 adaa 4000 ff11 784f a8b0 0319 a8b0    .G..@...xO......
          32: 0132 e573 0035 0033 ____ 39f9 0100 0001    .2.s.5.3.|9ù....
          48: 0000 0000 0000 0235 3001 3103 3137 3603    .......50.1.176.
          64: 3136 3807 696e 2d61 6464 7204 6172 7061    168.in-addr.arpa
          80: 0000 0c00 01                               .....

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

[...]Checksum is the 16-bit one's complement of the one's complement sum of a
pseudo header of information from the IP header, the UDP header, and the
data,  padded  with zero octets  at the end (if  necessary)  to  make  a
multiple of two octets.
 
The pseudo  header  conceptually prefixed to the UDP header contains the
source  address,  the destination  address,  the protocol,  and the  UDP
length.   This information gives protection against misrouted datagrams.
This checksum procedure is the same as is used in TCP.
 
                  0      7 8     15 16    23 24    31 
                 +--------+--------+--------+--------+
                 |          source address           |
                 +--------+--------+--------+--------+
                 |        destination address        |
                 +--------+--------+--------+--------+
                 |  zero  |protocol|   UDP length    |
                 +--------+--------+--------+--------+
 
If the computed  checksum  is zero,  it is transmitted  as all ones (the
equivalent  in one's complement  arithmetic).   An all zero  transmitted
checksum  value means that the transmitter  generated  no checksum  (for
debugging or for higher level protocols that don't care).[...]
Es decir que el checksum para UDP se calcula sobre los octetos que componen un seudo-header, el header de UDP 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 UDP:

  • Formato del frame Ethernet (el tamaño de los campos está en bytes)
  • Formato del header de IPv4
  • Formato del header UDP
  • Ahora debemos separar nuestro frame en su componentes: header Ethernet, Header IPv4, Header UDP y Datos:
            0260 8ce8 5533 0800 2073 5ec6 0800 ===> Header del frame Ethernet
    
            4500 0047  \
            adaa 4000  |
            ff11 784f   > Header IPv4
            a8b0 0319  |
            a8b0 0132  /
    
            e573 0035    Header
            0033 ____     UDP
    
            39f9 0100  \
            0001 0000  |
            0000 0000  |
            0235 3001  |
            3103 3137  |
            3603 3136   > Datos...
            3807 696e  |
            2d61 6464  |
            7204 6172  |
            7061 0000  |
            0c00 01    /
    De acuerdo con el RFC768 el seudo-header de este mensaje sería:

    a8b0 0319   ===> Dirección IP origen
    a8b0 0132   ===> Dirección IP destino
    0011 0033   ===> cero + número de protocolo (17 decimal) + longitud UDP (51 decimal, incluye header y datos)

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

    Suma con aritmética complemento a uno del seudoheader

       [Hex]    Binario
       [a8b0]   1010100010110000
       [0319]   0000001100011001
       [a8b0]   1010100010110000
       [0132]   0000000100110010
       [0011]   0000000000010001
       [0033]   0000000000110011
      [155EF]  10101010111101111

    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

        [55EF]   0101010111101111
                                1
        [55F0]   0101010111110000

    Suma con aritmética complemento a uno del header UDP

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

       [Hex]    Binario
       [e573]   1110010101110011
       [0035]   0000000000110101
       [0033]   0000000000110011
       [0000]   0000000000000000
       [E5DB]   1110010111011011

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

    (Se hace con sumas parciales para facilitar el manejo del los acarreos que ocurran)

       [Hex]    Binario
       [39f9]   0011100111111001
       [0100]   0000000100000000
       [0001]   0000000000000001
       [0000]   0000000000000000
       [0000]   0000000000000000
       [0000]   0000000000000000
       [0235]   0000001000110101
       [3001]   0011000000000001
       [3103]   0011000100000011
       [3137]   0011000100110111
       [3603]   0011011000000011
      [1056D]  10000010101101101  --> 0000010101101101 + 1 = 0000010101101110 [56E]

       [3136]   0011000100110110
       [3807]   0011100000000111
       [696e]   0110100101101110
       [2d61]   0010110101100001
      [1000C]  10000000000001100  --> 0000000000001100 + 1 = 0000000000001101 [D]

       [6464]   0110010001100100
       [7204]   0111001000000100
       [6172]   0110000101110010
      [137DA]  10011011111011010  --> 0011011111011010 + 1 = 0011011111011011 [37DB]

       [7061]   0111000001100001
       [0000]   0000000000000000
       [0c00]   0000110000000000
       [0100]   0000000100000000
       [7D61]   0111110101100001

    Ahora sumamos los subtotales
        [Hex]  Binario
        [56E]  0000010101101110
          [D]  0000000000001101
       [37DB]  0011011111011011
       [7D61]  0111110101100001
       [BAB7]  1011101010110111

    Y por fin, el checksum...

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

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

       [55F0] 0101010111110000
       [E5DB]  1110010111011011
       [BAB7] 1011101010110111
      [1F682] 11111011010000010  --> 1111011010000010 + 1 = 1111011010000011 [F683]

    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 de 1111011010000011 es 0000100101111100. Que vendría a ser el checksum: el hexadecimal 097C.

    Así que el frame completo sería:

          Offset: Hexadecimal                                ASCII
          ------- -----------                                -----
               0: 0260 8ce8 5533 0800 2073 5ec6 0800 4500    .`..U3.. s^...E.
              16: 0047 adaa 4000 ff11 784f a8b0 0319 a8b0    .G..@...xO......
              32: 0132 e573 0035 0033 097c 39f9 0100 0001    .2.s.5.3.|9ù....
              48: 0000 0000 0000 0235 3001 3103 3137 3603    .......31.44.66.
              64: 3136 3807 696e 2d61 6464 7204 6172 7061    88.in-addr.arpa.
              80: 0000 0c00 01                               .....
    [Algoritmo de checksum de Internet]
    [Checksum en IP]
    [Checksum en UDP]
    [Checksum en TCP]

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