Что происходит после захвата пакета? - PullRequest
10 голосов
/ 30 марта 2010

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

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

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

Спасибо.

С уважением, Rayne

Ответы [ 2 ]

14 голосов
/ 27 апреля 2010

То, как этот процесс завершается, в основном зависит от автора драйвера и аппаратного обеспечения, но для драйверов, которые я просмотрел или написал, и от аппаратного обеспечения, с которым я работал, обычно так оно и работает:

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

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

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

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

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

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

0 голосов
/ 27 апреля 2010

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

...