linux linux-kernel udp epoll

linux - Caída de paquetes UDP-INErrors Vs.RcvbufErrors



linux-kernel epoll (3)

Escribí un sencillo programa de Servidor UDP para comprender más sobre posibles cuellos de botella en la red.

Servidor UDP: crea un socket UDP, lo enlaza a un puerto y un addr especificados, y agrega el descriptor del archivo socket a la lista de interés de epoll. Entonces su epoll espera el paquete entrante. Al recibir el paquete entrante (EPOLLIN), lee el paquete y simplemente imprime la longitud del paquete recibido. Bastante simple, cierto :)

Cliente UDP: usé hping como se muestra a continuación:

hping3 192.168.1.2 --udp -p 9996 --flood -d 100

Cuando envío paquetes udp a 100 paquetes por segundo, no encuentro ninguna pérdida de paquetes UDP. Pero cuando inundo los paquetes udp (como se muestra en el comando anterior), veo una pérdida significativa de paquetes.

Prueba 1: cuando 26356 paquetes se inundan desde el cliente UDP, mi programa de ejemplo recibe SOLO 12127 paquetes y los restantes 14230 paquetes se descargan con el kernel como se muestra en la salida / proc / net / snmp.

cat / proc / net / snmp | grep Udp:
Udp: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors
Udp: 12372 0 14230 218 14230 0

Para Test1, el porcentaje de pérdida de paquetes es ~ 53%.

Verifiqué que NO hay mucha pérdida a nivel de hardware con el comando "ethtool -S ethX" tanto en el lado del cliente como en el del servidor, mientras que en el nivel de aplicación veo una pérdida del 53% como se dijo anteriormente.

Por lo tanto, para reducir la pérdida de paquetes probé estos:
- Aumenté la prioridad de mi programa de muestra usando renice comando renice .
- Aumento del tamaño del búfer de recepción (tanto a nivel de sistema como a nivel de proceso)

Sube la prioridad a -20:

renice -20 2022
2022 (ID de proceso) antigua prioridad 0, nueva prioridad -20

Suba el tamaño del bufete de recepción a 16MB:

En el nivel de proceso:
int sockbufsize = 16777216;
setsockopt (sockfd, SOL_SOCKET, SO_RCVBUF, (char *) & sockbufsize, (int) sizeof (sockbufsize))
A nivel de Kernel:
cat / proc / sys / net / core / rmem_default
16777216
cat / proc / sys / net / core / rmem_max
16777216

Después de estos cambios, realizó Test2.

Prueba2: cuando los paquetes 1985076 se inundan desde el cliente UDP, mi programa de ejemplo recibe 1848791 paquetes y el paquete elimina los paquetes 136286 restantes como se muestra en la salida / proc / net / snmp.

cat / proc / net / snmp | grep Udp:
Udp: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors
Udp: 1849064 0 136286 236 0 0

Para Test2 el porcentaje de pérdida de paquetes es del 6%.

La pérdida de paquetes se reduce significativamente. Pero tengo las siguientes preguntas:

  1. ¿Se puede reducir aún más la pérdida de paquetes? Sé que soy codicioso aquí :) Pero solo estoy tratando de averiguar si es posible reducir aún más la pérdida de paquetes.
  2. A diferencia de Test1, en Test2 InErrors no coincide con RcvbufErrors y RcvbufErrors siempre es cero. ¿Alguien puede explicar la razón detrás de esto, por favor? ¿Cuál es exactamente la diferencia entre InErrors y RcvbufErrors? Entiendo RcvbufErrors pero NOT InErrors.

¡¡¡Gracias por su ayuda y tiempo!!!


Ajustar la pila de red del kernel de Linux para reducir las caídas de paquetes es un poco complicado ya que hay muchas opciones de optimización desde el controlador hasta la pila de red.

Escribí una larga publicación en el blog en la que se explicaban todos los parámetros de ajuste de arriba a abajo y se explicaba qué significaba cada uno de los campos en /proc/net/snmp para que puedas descubrir por qué ocurren esos errores. Eche un vistazo, creo que debería ayudarlo a que su red se reduzca a 0.


InErrors se compone de:

  • Paquetes corruptos (encabezados incorrectos o suma de comprobación)
  • tamaño de búfer RCV completo

Entonces, supongo que ha solucionado el problema de desbordamiento del búfer (RcvbufErrors es 0) y lo que queda son paquetes con sumas de comprobación incorrectas.


Si no hay caídas en el nivel de hardware, entonces debería tratarse principalmente de una cuestión de memoria, debería poder ajustar los parámetros de configuración del kernel para alcanzar 0 caídas (obviamente, necesita un hardware equilibrado razonable para el tráfico de red que está recibiendo). ).

Creo que te estás perdiendo netdev_max_backlog que es importante para los paquetes entrantes:

Número máximo de paquetes, en cola en el lado de ENTRADA, cuando la interfaz recibe paquetes más rápido de lo que el kernel puede procesarlos.