redes protocolo glucose caracteristicas bioquimica udp checksum

glucose - udp protocolo



Cálculo de suma de comprobación UDP (3)

La estructura de encabezado UDP definida en /usr/include/netinet/udp.h es la siguiente

struct udphdr { u_int16_t source; u_int16_t dest; u_int16_t len; u_int16_t check; };

¿Qué valor se almacena en el campo de verificación del encabezado? ¿Cómo verificar si la suma de comprobación es correcta? Me refiero a qué datos se calcula la suma de comprobación? (¿Es solo el encabezado udp o el encabezado udp más la carga útil que lo sigue?)

Gracias.



La suma de comprobación UDP se realiza en toda la carga útil, los otros campos en el encabezado y algunos campos del encabezado IP. Se construye un pseudo encabezado a partir del encabezado IP para realizar el cálculo (que se realiza sobre este pseudo encabezado, el encabezado UDP y la carga útil). La razón por la que se incluye el pseudo-encabezado es para capturar paquetes que se han enrutado a la dirección IP incorrecta.

Básicamente, en el extremo receptor, todas las palabras de 16 bits de los encabezados más el área de datos se suman (se ajustan a 16 bits) y el resultado se verifica contra 0xffff .

En el lado de envío, es un poco más complejo. La suma del complemento de uno se realiza en todos los valores de 16 bits, luego se toma el complemento de uno (es decir, se invierten todos los bits) de ese valor para completar el campo de suma de comprobación (con la condición adicional de que una suma de comprobación calculada de cero se cambiará a todos de un bit).

La suma del complemento de uno no es solo la suma de todos los valores del complemento de uno. Es un poco más complejo.

Básicamente, tienes un acumulador de 16 bits en ejecución que comienza en cero y le agregas cada valor de 16 bits. Cada vez que una de esas adiciones se traduce en un acarreo, el valor se envuelve y usted agrega uno nuevamente al valor. Esto toma efectivamente el bit de acarreo de la adición de 16 bits y lo agrega al valor.

Como nota aparte, y esto es pura conjetura de mi parte, pero esto probablemente podría hacerse de manera eficiente mediante el uso de la instrucción ADC (agregar con acarreo) en lugar de ADD (sorprendentemente, agregar), o cualquier otra instrucción equivalente disponible en su CPU en el tiempo.

Si no hubiera acarreo, ADC solo agregaría el bit cero del acarreo. En los días en que se hizo esto (y sí, desafortunadamente, yo soy tan viejo), la memoria era mucho más una restricción que la velocidad, no tanto en el caso de hoy en día, por lo que ahorrar algunos bytes en su código podría elevarlo a el nivel de demi-dios-emperador-del-universo :-)

Tenga en cuenta que nunca tuvo que preocuparse por llevar la segunda vez (o un acarreo de dos con el próximo ADC si está usando el método mencionado en el párrafo anterior), ya que los dos valores más grandes de 16 bits, cuando se suman, producen ( truncado desde 0x1fffe ) 0xfffe : agregar uno a eso nunca causará otro acarreo.

Una vez que se calcula la suma de complemento calculada, se invierten los bits y se insertan en el paquete, lo que hará que el cálculo en el extremo receptor produzca 0xffff , suponiendo que no haya errores en la transmisión, por supuesto.

Vale la pena señalar que la carga útil siempre se rellena para garantizar que haya un número integral de palabras de 16 bits. Si estaba rellenado, el campo de longitud le indica la longitud real.

RFC768 es la especificación que detalla esto.


Un ejemplo agradable y fácil de entender del cálculo de la suma de comprobación UDP lo realiza Gerd Hoffmann.

Puede buscar en Google "net-checksum.c Gerd Hoffmann" o consultar el archivo aquí:

https://gist.github.com/fxlv/81209bbd150abfeaceb1f85ff076c9f3

Puede usar la función net_checksum_tcpudp , alimentarla con la longitud de carga útil UDP, las direcciones IP proto, src y dst y luego la carga útil UDP en sí misma y hará lo correcto.

Al final tienes que llamar a htons() en la suma de comprobación y estás bien.