Персональные инструменты
Вы здесь: Главная Блог Анализ гигабита на commodity hardware: что есть уже сейчас

Анализ гигабита на commodity hardware: что есть уже сейчас

Автор: Денис Гамаюнов at 2009-01-21 01:31 |

Галопом по доступным сегодня средствам сбора и (или) анализа трафика на типовом оборудовании на гигабитных скоростях, в основном, для ОС Linux. Рассматриваются: mmap-pcap + NAPI и PF_RING, а также Gulp как пример того, чего можно достичь в юзерспейсе, слегка изменив настройки планировщика.

Как было показано в предыдущей заметке, опережающее развитие технологий передачи данных по Гилдеру приводит к тому, что на типовом "железе" становится всё труднее обрабатывать типовой канал передачи данных при полной его утилизации. Этот тренд накладывается на несовершенство некоторых аспектов реализации современных ОС общего назначения, что ведёт к большим накладным расходам. Результат можно наблюдать на примере поведения библиотеки libpcap в ОС Linux при использовании настроек по-умолчанию.

Справедливости ради нужно отметить, что во многом такое положение дел с libpcap продиктовано требованиями универсальности и независимости интерфейса библиотеки от используемой аппаратной платформы и операционной системы. В разных ОС libpcap использует различные нативные механизмы ОС. Например, во FreeBSD она работает через BPF, а в Linux - через raw sockets.

В ОС Linux существует несколько способов повышения производительности libpcap. Первый способ - использование mmap() для передачи пакетов с уровня ядра в юзерспейс. Он реализован Филом Вудом (Phil Wood) в модифицированной версии библиотеки. Для установки надо взять исходники, собрать библиотеку, и пересобрать весь использующий её софт. Второй способ - использование активного поллинга, который реализован в Linux NAPI и поддерживается большинством драйверов сетевых карт. Поллинг работает примерно так: при получении прерывания от устройства ядро маскирует все последующие прерывания и начинает периодически опрашивать устройство для его обслуживания. Как только устройство обслужено, ядро снова демаскирует прерывания от него. Вместе два этих способа дают приличный прирост производительности libpcap в Linux, но не решают проблему для гигабитных скоростей.

Один из авторов ntop.org, Люка Дери (Luca Deri), ещё в 2004 году опубликовал результаты экспериментов с libpcap на различных платформах и различном оборудовании. В тестах использовались ядра Linux версий 2.4 и 2.6, FreeBSD 4.8, Windows 2000. За 4 года результаты, конечно, значительно устарели, но судя по отдельным более современным исследованиям, с 2004 года ситуация с libpcap мало изменилась. Худшие результаты были продемонстрированы при использовании libpcap на Linux 2.4 на 100-мегабитном канале (80Kpps) и на довольно слабенькой машине - VIA C3 533Mhz CPU и остальное в том же духе - потери составили 99,8% пакетов. При этом версия с mmap улучшила результат в 5 раз - потери снизились до 99%. На том же оборудовании libpcap на FreeBSD потеряла "всего" 66% пакетов, а результат WinPCAP составил 32% потерь.

В следующем эксперимента он использовал поллинг в ОС Linux (2.6.1, NAPI) и FreeBSD. В качестве аппаратной платформы использовался Pentium III 550Mhz с гигабитной сетевой картой Intel. Тест проводился с разным размером кадров - 64 байта, 512 байт и 1500 байт. Результаты приведены в таблице 1 (указаны потери):

Размер кадра
Linux 2.6.1, NAPI
обычная libpcap
Linux 2.6.1, NAPI
libpcap-mmap
FreeBSD с включённым
поллингом
64 97,5% 85,1% 2,7%
512 98,9% 88,3% 52,7%
 1500 65,7% 6,5% 43,9%
Таблица 1. Доля потерь с включённым поллингом сетевых устройств

 Видно, что с мелкими кадрами ситуация совсем плохая. Хотя на больших кадрах линуксовая версия libcap-mmap показывает себя вполне неплохо. В статье есть ещё несколько тестов на более быстрых процессорах, в том числе с использованием авторского патча на ядро. В целом же можно сделать вывод, что использование версии libpcap с mmap() и поллинг сетевой карты существенно улучшают производительность при выводе трафика в юзерспейс, но недостаточно, чтобы можно было говорить о wire speed.

Отсюда плавно переходим к PF_RING - это патч на ядро Linux, автором которого является тот же Люка Дери. PF_RING предоставляет приложениям в юзерспейсе сокеты специального вида, где с каждым сокетом ассоциирован кольцевой буфер, который отображается в юзерспейс с помощью того же mmap(). Кадр из буфера сетевой карты через DMA попадает сразу в кольцевой буфер, и становится доступен приложению (см. рисунок 1). Цикл работы PF_RING выглядит следующим образом:

  • создаётся сокет типа PF_RING;
  • ядро выделяет память под кольцевой буфер, а когда приложение закрывает сокет - освобождает;
  • когда драйвер получает кадр с сетевой карты (через DMA) и копирует его в кольцевой буфер. Если буфер полон, кадр сбрасывается;
  • на тех интерфейсах, для которых есть сокеты PF_RING, кадр по-умолчанию не передаётся стеку операционной системы, что ускоряет обработку кадров; при желании, эту опцию можно включить;
  • кольцевой буфер экспортируется в юзерспейс с помощью mmap();
  • для доступа приложения к буферу оно должно открыть сокет и вызвать mmap(), получив таким образом указатель чтения на позицию в кольцевом буфере;
  • ядро при записи в буфер продвигает указатель записи, а указатель чтения сдвигается по мере получения пакетов приложением;
  • новые кадры перезаписывают уже считанные приложением;
  • для управления потоком кадров используется "текущее ведро" (leaky bucket).

 pf_ring

 Рисунок 1. Схема работы PF_RING.

 Приложения могут использовать как родной интерфейс библиотеки, так и модифицированную автором PF_RING версию libpcap. Но ядро так или иначе придётся патчить - PF_RING всё ещё не вошёл в основную ветку kernel.org, несмотря на то, что успешно развивается и поддерживается уже пятый или шестой год. По тестам из той же статьи 2004 года libpcap + PF_RING + NAPI на 1500-байтных кадрах показывает такую же производительность, как libpcap-mmap + NAPI, а на средних и мелких кадрах намного превосходит. Более свежие тесты (2008 год) с использованием двухъядерного Xeon 3.2ГГц и генератора трафика IXIA 400 демонстрируют какие-то потери кадров лишь после 1.8 Mpps (на двух гигабитных сетевых интерфейсах).

Размер пакета
Скорость в Kpps Скорость в Mbps Доля свободного времени CPU
250 259.23 518 >90%
250 462.9 925.9  88%
128 355.1 363.6  86%
128 844.6 864.8 82%

Таблица 2. Производительность PF_RING на одноядерном Celeron 3.2ГГц

На сегодняшний день кроме быстрого вывода трафика в юзерспейс PF_RING умеет следующее:

  • Bloom filtering на уровне драйвера - эффективный по памяти способ организации фильтров
  • несколько фильтров на каждый сокет
  • архитектурная независимость - работает для x86, MIPS и т.д., есть реализация для OpenWRT
  • фильтры уровня PF_RING с поддержкой string matching (реализация Aho-Corasick)
  • готовая реализация NetFlow, плюс можно добавлять свои плагины ядерного уровня
Как можно понять из вот этой презентации, автор смотрит в сторону перехвата VoIP и прочих задач lawful interception на канальной скорости.


В последнем для данной заметки примере решается конкретная прикладная задача - перехват и запись на файловую систему гигабитного трафика с канальной скоростью. Для решения данной задачи Corey Satten из университета Вашингтона разработал и реализовал простое многопоточное средство Gulp, которое примечательно тем, что использует всё тот же кольцевой буфер без блокировок в качестве интерфейса передачи трафика между двумя потоками. Первый поток получает пакеты из libpcap, а второй пишет их на диск. Простой привязкой этих двух потоков к разным ядрам процессора и повышением приоритета читающего потока автору удалось обеспечить запись гигабитного трафика на диск без потерь. К сожалению, в описанном тесте средняя скорость составляла всего 96 kpps, то есть в канале преимущественно были кадры большого размера. На мелких кадрах, надо полагать, ситуация была бы не столь радужна. Примечательна фраза наверху домашней странички автора Gulp: "Due to lack of funds, the Security Solutions Team at the University of Washington was abruptly eliminated on May 20, 2008 and I was laid off (along with 65 others throughout "UW Technology")." Удачи тебе, Corey!

В заключение отмечу, что сегодня уже доступны системы с 64 и 256 логическими ядрами на сановском UltraSPARC T2 (Niagara 2), и скоро выйдет Rock. Вот-вот обещают 16-ядерные процессоры интеловской архитектуры. А так как задачи анализа сетевого трафика, как правило, хорошо параллелятся, то у нас есть надежда и на успешный разбор 10Гбитного трафика одним-двумя юнитами и четырьмя сотнями ватт потребления, без потерь и всё такое на wire speed. Надо только сделать что-нибудь подобное PF_RING с конвейерами из процессорных ядер в кернелспейсе.

 

Действия с Документом

^_^

Автор: http://gq.net.ru/author/gq/ Дата: 2009-01-21 18:10
А вы сами-то с PF_RING экспериментировали?

Нет ещё

Автор: Денис Гамаюнов Дата: 2009-01-21 19:19
Мы ж в ядерном режиме на FreeBSD cидим, поэтому экспериментировали с BPF и netgraph. Тесты BPF из юзерспейса сходятся с результатами Luca Deri.