Что происходит после захвата пакета?

Я читал о том, что происходит после захвата пакетов сетевыми картами, и чем больше я читаю, тем больше я запутался.

Во-первых, я читал, что традиционно после захвата пакета сетевой картой он копируется в блок памяти в пространстве ядра, а затем в пространство пользователя для любого приложения, которое затем работает с данными пакета. Потом прочитал про DMA, где сетевая карта напрямую копирует пакет в память, минуя ЦП. Так что NIC -> память ядра -> поток памяти пользовательского пространства все еще действителен? Кроме того, большинство сетевых адаптеров (например, Myricom) используют DMA для повышения скорости захвата пакетов?

Во-вторых, одинаково ли работает RSS (масштабирование на стороне приема) в системах Windows и Linux? Я могу найти подробные объяснения того, как работает RSS, только в статьях MSDN, где говорится о том, как RSS (и MSI-X) работает в Windows Server 2008. Но та же концепция RSS и MSI-X должна по-прежнему применяться к системам Linux, верно? ?

Спасибо.

С уважением, Рейн


person Rayne    schedule 30.03.2010    source источник
comment
Google для сети с нулевым копированием ... очень немногие высокоскоростные устройства в наши дни могут выдерживать двойное копирование в ядро, а затем пользователя. IANANG (я не сетевой гуру), но я считаю, что DMA используется агрессивно   -  person Sam Post    schedule 30.03.2010
comment
Итак, в настоящее время, когда сетевая карта захватывает пакет, он будет напрямую скопирован в (пользовательскую) память?   -  person Rayne    schedule 30.03.2010
comment
@ Рейн да; NIC будет использовать DMA для передачи данных непосредственно в физическую память, сопоставленную с адресным пространством вашего процесса (пользовательского пространства).   -  person vladr    schedule 30.03.2010
comment
Почему ты спрашиваешь? Чего вы хотите достичь?   -  person Denes Tarjan    schedule 13.04.2010
comment
+1 за упоминание нулевой копии. Его широко используется в наши дни.   -  person Jack    schedule 25.04.2010
comment
@Vlad: Когда приходит пакет, пользовательское приложение, возможно, еще не запросило данные, поэтому невозможно скопировать их в буфер пользовательского пространства. Он хранится в ядре до тех пор, пока не будет запрошен.   -  person Steve Madsen    schedule 27.04.2010
comment
@vladr Как вы уже упоминали, NIC напрямую копирует пакет в память процесса пользовательского пространства с помощью DMA и использует только одну копию ... Но я думаю, что DMA используется только для передачи данных в память ядра без вмешательства ЦП. поэтому копирование данных не происходит с помощью ЦП, и ЦП может работать во время передачи DMA.   -  person akp    schedule 20.06.2013


Ответы (2)


Как происходит этот процесс, в основном зависит от автора драйвера и оборудования, но для драйверов, которые я просматривал или писал, и оборудования, с которым я работал, обычно это работает следующим образом:

  1. При инициализации драйвера он выделяет некоторое количество буферов и передает их сетевой карте.
  2. Когда сетевой адаптер получает пакет, он извлекает следующий адрес из своего списка буферов, записывает данные прямо в него и уведомляет драйвер через прерывание.
  3. Драйвер получает прерывание и может либо передать буфер ядру, либо выделить новый буфер ядра и скопировать данные. «Сеть с нулевым копированием» относится к первому варианту и, очевидно, требует поддержки со стороны операционной системы. (подробнее об этом ниже)
  4. Драйвер должен либо выделить новый буфер (в случае нулевого копирования), либо повторно использовать буфер. В любом случае буфер возвращается сетевой карте для будущих пакетов.

Сеть с нулевым копированием внутри ядра не так уж и плоха. Полное отсутствие копирования вплоть до пользовательского пространства намного сложнее. Userland получает данные, но сетевые пакеты состоят как из заголовка, так и из данных. По крайней мере, истинное нулевое копирование на всем пути к пользовательскому пространству требует поддержки со стороны вашей сетевой карты, чтобы она могла размещать пакеты DMA в отдельных буферах заголовков/данных. Заголовки перерабатываются после того, как ядро ​​направит пакет к месту назначения и проверит контрольную сумму (для TCP, либо аппаратно, если сетевая карта поддерживает это, либо программно, если нет; обратите внимание, что если ядру необходимо вычислить контрольную сумму самому, оно также может копировать данные: просмотр данных приводит к промахам кеша, а копирование их в другое место может быть бесплатным с настроенным кодом).

Даже если предположить, что все звезды сошлись, данные на самом деле не находятся в вашем пользовательском буфере, когда они получены системой. Пока приложение не запросит данные, ядро ​​не знает, где они окажутся. Рассмотрим случай многопроцессорного демона, такого как Apache. Есть много дочерних процессов, и все они прослушивают один и тот же сокет. Вы также можете установить соединение, fork(), и оба процесса смогут recv() получать входящие данные.

TCP-пакеты в Интернете обычно содержат 1460 байт полезной нагрузки (MTU 1500 = 20-байтовый IP-заголовок + 20-байтовый TCP-заголовок + 1460 байт данных). 1460 не является степенью двойки и не будет соответствовать размеру страницы ни в одной системе, которую вы найдете. Это создает проблемы для повторной сборки потока данных. Помните, что TCP ориентирован на поток. Нет различий между операциями записи отправителя, и две операции записи по 1000 байт, ожидающие получения, будут полностью израсходованы при чтении 2000 байт.

Продолжая это, рассмотрим пользовательские буферы. Они выделяются приложением. Чтобы его можно было использовать для нулевого копирования на всем протяжении, буфер должен быть выровнен по страницам и не должен делиться этой страницей памяти с чем-либо еще. Во время recv() ядро ​​теоретически может переназначить старую страницу на страницу, содержащую данные, и "перевернуть" ее на место, но это осложняется описанной выше проблемой повторной сборки, поскольку последующие пакеты будут находиться на отдельных страницах. Ядро может ограничить данные, которые оно возвращает, полезной нагрузкой каждого пакета, но это будет означать множество дополнительных системных вызовов, переназначение страниц и, вероятно, снижение пропускной способности в целом.

Я действительно только царапаю поверхность по этой теме. В начале 2000-х я работал в нескольких компаниях, пытаясь распространить концепцию нулевого копирования на пользовательскую среду. Мы даже реализовали стек TCP в пользовательской среде и полностью обошли ядро ​​для приложений, использующих стек, но это принесло свой собственный набор проблем и никогда не было качеством производства. Это очень сложная проблема.

person Steve Madsen    schedule 27.04.2010

взгляните на этот документ, http://www.ece.virginia.edu/cheetah/documents/papers/TCPlinux.pdf это может помочь решить некоторые вопросы об управлении памятью.

person Stb    schedule 26.04.2010