2010-03-30 13 views
10

He estado leyendo sobre lo que sucede después de que los NIC capturan paquetes, y cuanto más leo, más me confundo.¿Qué sucede después de capturar un paquete?

En primer lugar, he leído que tradicionalmente, después de que un paquete es capturado por la NIC, se copia a un bloque de memoria en el espacio del núcleo, luego al espacio de usuario para la aplicación que luego trabaja en los datos del paquete . Luego leo sobre DMA, donde el NIC copia directamente el paquete en la memoria, sin pasar por la CPU. Entonces, ¿la NIC -> kernel memory -> User space memory flow sigue siendo válida? Además, ¿la mayoría de las NIC (por ejemplo, Myricom) usan DMA para mejorar las tasas de captura de paquetes?

En segundo lugar, ¿el RSS (Receive Side Scaling) funciona de manera similar en los sistemas Windows y Linux? Solo puedo encontrar explicaciones detalladas sobre cómo funciona el RSS en los artículos de MSDN, donde hablan sobre cómo funciona RSS (y MSI-X) en Windows Server 2008. Pero el mismo concepto de RSS y MSI-X aún debe aplicarse a los sistemas de Linux, a la derecha ?

Gracias.

Saludos, Rayne

+1

Google para redes de copia cero ... muy pocos dispositivos de alta velocidad pueden tolerar copias dobles para kernel y usuarios en estos días. IANANG (No soy un gurú de la red) pero creo que DMA se usa agresivamente –

+0

Entonces, ¿una vez que una NIC captura un paquete, se copiará directamente en la memoria (del usuario)? – Rayne

+3

@Rayne sí; el NIC usará DMA para transferir datos directamente a la memoria física mapeada en el espacio de direcciones de su proceso (espacio de usuario). – vladr

Respuesta

12

Cómo juega a cabo este proceso es en su mayoría hasta el autor del controlador y el hardware , pero para los conductores que he mirado o por escrito y el hardware que he trabajado, esto es por lo general la forma en que funciona:

  1. en la inicialización del controlador, se asignará un número de buffers y dar a éstos a el NIC.
  2. Cuando la NIC recibe un paquete, saca la siguiente dirección de su lista de almacenamientos intermedios, DMA los datos directamente en ella y notifica al controlador mediante una interrupción.
  3. El controlador recibe la interrupción y puede pasar el búfer al kernel o asignará un nuevo búfer de kernel y copiará los datos. La "red de copia cero" es la primera y obviamente requiere soporte del sistema operativo. (más abajo en esto)
  4. El controlador necesita asignar un nuevo búfer (en el caso de copia cero) o reutilizará el búfer. En cualquier caso, el buffer se devuelve a la NIC para paquetes futuros.

La red de cero copias dentro del kernel no es tan mala. La copia cero hasta el usuario es mucho más difícil. Userland obtiene datos, pero los paquetes de red están formados por encabezado y datos. Como mínimo, la copia cero real hasta el sitio del usuario requiere soporte de su NIC para que pueda convertir los paquetes DMA en búferes de encabezado/datos separados. Los encabezados se reciclan una vez que el kernel enruta el paquete a su destino y verifica la suma de comprobación (para TCP, ya sea en hardware si la NIC lo admite o en el software si no; tenga en cuenta que si el kernel debe calcular la suma de comprobación misma, también puede copiar los datos: ver los datos incurre en errores de caché y copiarlos en otro lugar puede ser gratis con un código sintonizado).

Incluso asumiendo que todas las estrellas se alineen, los datos no están realmente en su búfer de usuario cuando el sistema los recibe. Hasta que una aplicación solicite los datos, el kernel no sabe dónde terminará. Considere el caso de un daemon multiproceso como Apache. Hay muchos procesos secundarios, todos escuchando en el mismo socket. También puede establecer una conexión, fork(), y ambos procesos pueden recv() datos entrantes.

Los paquetes TCP en Internet suelen tener 1460 bytes de carga (MTU de 1500 = 20 bytes de encabezado IP + 20 bytes de encabezado TCP + 1460 bytes de datos). 1460 no tiene una potencia de 2 y no coincidirá con un tamaño de página en cualquier sistema que encuentre. Esto presenta problemas para el reensamblaje de la secuencia de datos. Recuerde que TCP está orientado a flujos. No hay distinción entre las escrituras del remitente, y dos escrituras de 1000 bytes que esperan en el recibido se consumirán por completo en una lectura de 2000 bytes.

Teniendo esto en cuenta, considere los almacenamientos intermedios de usuario. Estos son asignados por la aplicación. Para que se pueda utilizar como copia cero hasta el final, el almacenamiento intermedio debe estar alineado con la página y no compartir esa página de memoria con nada más. En recv() vez, el kernel podría reasignar teóricamente la página anterior con la que contiene los datos y "voltearla" en su lugar, pero esto se complica por el problema de reensamblado anterior ya que los paquetes sucesivos estarán en páginas separadas. El kernel podría limitar los datos que devuelve a la carga útil de cada paquete, pero esto significará muchas llamadas adicionales al sistema, reasignación de páginas y, en general, un rendimiento inferior.

Estoy realmente solo arañando la superficie sobre este tema. Trabajé en un par de empresas a principios de la década de 2000 tratando de extender los conceptos de copia cero al dominio del usuario. Incluso implementamos una pila TCP en el territorio del usuario y eludimos por completo el kernel para las aplicaciones que usan la pila, pero eso trajo su propio conjunto de problemas y nunca fue de calidad de producción. Es un problema muy difícil de resolver.

Cuestiones relacionadas