[Из песочницы] How to DPAA driver
Статья предназначена для узкого круга разработчиков, «подсевших» на процессоры QoriQ от Freescale и является кратким пересказом основных положений документации на сетевую архитектуру DPAA.DPAA (Data Path Acceleration Architecture) — специализированная фирменная архитектура ускорения маршрута данных, разработанная Freescale и встраиваемая в последние серии процессоров. Основное назначение DPAA — разгрузить процессор от рутинной работы по обработки сетевого трафика. Мы разработали драйвера данной архитектуры для серии процессоров p30xx/p4080 и готовы поделиться своим опытом.DPAA может работать в 2 режимах — нормальный режим и упрощенный, который обычно используется загрузчиками и драйверами, разработчики которых не успели/смогли освоить нормальный режим. На упрощенный режим накладываются ограничения в максимальной скорости обработки 100Мбит/с и отсутствии возможности использования средств аппаратного ускорения обработки данных. В нормальном режиме нам доступны 5 гигабитных портов datapath three-speed Ethernet controller (DTSEC), один 10 Gigabit Ethernet media access controller (10GEC) и суммарная пропускная способность в 12 Гбит/с. Структурная схема процессора p3040 представлена на рисунке, а DPAA в ней обведен красным контуром.
Как утверждают представители freescale — dpaa это просто. Настолько просто, что драйвер от freescale для Linux разрабатывается по сей день и его суммарный код вышел за пределы 2 мегабайт, правда это вместе с тест юнитами. Для нашей задачи использовать его не представлялось возможным, но время от времени мы в него подглядывали, потому-что стиль документации не смог ответить на все вопросы касательно порядка инициализации DPAA.
Информационный поток Итак, основная информационная единица сетевого драйвера — пакет. Данные пакета DPAA располагает в буферах(buffers). Буферы объединяются в кадры, которые имеют описатель (frame descriptor/FD), кадры объединяются в очереди кадров (Frame queue / FQ), очереди кадров объединяются в рабочие очереди (Work Queue/WQ), рабочие очереди объединяются в каналы (Channel), а каналы «утекают» в порталы (Portal). Это вам не e1000.Такая иерархия требуется для сохранения порядка пакетов, реализации приоритета получения и отправки пакетов, сортировки пакетов по протокольному признаку и прочих плюшек. Последнее, кстати, дает нам теоретическую возможность избавится от анализа пакета на процессоре.
Менеджеры буферов(Buffer Manager/BMan) и очередей(Queue Manager/QMan) Менеджеры буферов и очередей являются подсистемами DPAA, предоставляющими сервис организации буферного пула и очередей входящего/исходящего трафика. Они являются частью DPAA, но не обязательно могут работать с сетевыми интересами — их можно загрузить и другими задачами.Порталы Каждый такой менеджер имеет порталы — механизм разделения ресурса менеджера, предназначенный для работы с отдельными ядрами процессора. Для решения проблем синхронизации, на каждое ядро процессора выделяется не менее, чем по одному порталу. В менеджере очередей также существуют понятия direct и software порталов. Это внутреннее понятие менеджера очередей и для настройки DPAA надо понимать, что software порталы связаны с процессором, а direct порталы с Frame manager и его компонентами. Каждый портал настраивается набором регистров, разделенных на 2 части: кэшируемый и не кэшируемый, которые требуется отобразить с соответствующими атрибутами памяти на выровненный диапазон адресов.Общение с менеджерами состоит в выдачи команд и обработки ответов.
Команды управления Процесс формирования команд имеет схожую структуру для QMan и BMan. Для каждого типа команд существует кольцевой буфер очереди команд, размер которого фиксирован и кратен степени 2. Например, для команды «Дай буфер» — имеется очередь на 2 слота команд, а для команды «возьми буфер» — имеется 8 слотов команд. Для очереди буфера команд существуют понятия потребитель, который обрабатывает команды и производитель, который их выдает. Например, для команды «отправь пакет» драйвер будет производителем, а QMan — потребителем. Есть 3 способа контроля обработки очереди команд: по биту валидности, по указателям на начало/конец в кэшируемой и не кэшируемой области регистров менеджера. На мой вкус, использование бита валидности реализовать правильнее. Смысл следующий — сигналом обработки команды для потребителя очереди будет смена бита валидности в команде. Бит поменялся — команда обновилась.Команды и ответы на них расположены в кэшируемой области памяти и их размер кратен ширине локальной шины — 32 байта. Это удобно, не требуется копировать данные и их можно использовать как есть. Главное — не забывать обновлять кэш. Поэтому запись команды выглядит как последовательность действий: обнулить кэш, заполнить поля, барьер, установить бит валидности и сбросить кэш на шину. Перед чтением данных не забываем делать обновление кэша.
Менеджер буферов (Buffer Manager/BMan) В комиксах, любезно предоставленных freescale, менеджер буферов представлен в виде лотка бумаги для оргтехники. В эти лотки можно загружать бумагу одного размера, а устройство будет ее брать по мере необходимости. Весьма грубый пример, в действительности менеджер буферов заведует исключительно указателями на физические адреса области памяти одинакового размера. Если совсем по правде, то ему вообще все равно, что будут означать эти 32-х битные данные, которые он хранит, но для использования BMan в DPAA там должны быть физические адреса. Операционная система выделяет буферы для хранения сетевых пакетов из основной памяти и передает их физические адреса менеджеру буферов, указав номер кучки, которой они будут принадлежать. Максимальное количество таких кучек фиксировано — 0x3f и в каждой кучки лежат буферы одинакового размера. Количество буферов(указателей) в кучки зависит от размера памяти, которое мы для них выделим при инициализации BMan.Использование буферов регламентируется джентльменским соглашением между операционной системой и другими компонентами процессора, находящимися на внутренней шине. Для использования буфера его следует запросить у менеджера буферов, а по окончании использования — освободить. Процесс освобождения буфера не отличается от процесса инициализации буферов. Таким образом общение с менеджером буферов можно свести к двум командам освободить буфер и занять буфер. Структура команды позволяет управляться 8 буферами за одну команду.
Также Buffer manager можно попросить выдать прерывание, когда буферы будут заканчиваться, выставив в настройках порог и гистерезис.
Менеджер очередей (Queue Manager/QMan) Основной задачей менеджера очередей является распределение нагрузки на ядра процессора, настройка очередей и генерация прерываний событий очереди.Именно менеджер очередей является инициатором прерывания при получении пакетов от всех сетевых интерфейсов DPAA. Зачем это сделано? Если у нас имеется 5 разных сетевых карточек, на разных прерываниях, то сколько нам потребуется обработчиков прерываний? Пять. В случае с DPAA требуется только один обработчик, который может выполняться на всех ядрах процессора. DPAA поддерживает 5 сетевых портов, информационный поток которых может быть доступен для всех ядер процессора. Распределением нагрузки на ядра менеджер очередей реализует в соответствии с настроенным алгоритмом планирования.
Подсистемы обработки данных DPAA включает в себя различные подсистемы обработки данных(сетевого трафика). На данный момент драйвером они не поддерживаются, поэтому кратко об основных возможностях.Ускоритель шифрования SEС выполняет шифрование и дешифрование пакетов, знает протоколы ipsec, 802.1ae, ssl/tsl, алгоритмы шифрования rsa, des, aes; алгоритмы хэширования sha-*, md5, hmac, rc4/arc4, crc32 и многое другое.
Ускоритель распознавания образов PME обрабатывает регулярные выражения и применяет их к сетевому трафику со скоростью 9 Гбит/с. В PME могут одновременно распознаваться до 32K образцов длиной до 128 бит каждый. Результатом распознавания является «окраска» кадров, которая может быть использована другими подсистемами DPAA.
Эти компоненты могут являться частью конвейера обработки сетевого трафика и работают параллельно.
Менеджер кадров Менеджер кадров (Frame manager/ FMan) — центр управления DPAA, занимается взаимодействием с менеджером очередей, менеджером буферов, DTSECами и подсистемами обработки данных, распознает и сортирует пакеты по протоколам, определяет направление движения пакета в зависимости от настроек. На процессорах p4080 и старше Frame manager представлен в 2 экземплярах. Пример схемы движения пакета: Для полноценной реализации всех возможностей DPAA требуется ковырять сетевой стек. Исходников целевого сетевого стека у меня не было, тестирование драйвера было на подопытном BSD стеке, поэтому (и еще потому-что они не реализованы) использование всех этих подсистем мы сейчас не рассматриваем. Но для получения адекватных показателей на iperf BSD стек тоже пришлось чуть модифицировать.Порты Источником и пунктом назначения данных в Frame manager являются порты. Назначение портов фиксировано, существуют порты: приема 1/ 2.5Gb, отправки 1 / 2.5Gb, приема 10Gb, отправки 10Gb и внутренние. Внутренние порты предназначены для обработки данных не связанных с сетевыми интерфейсами DPAA.Инициализация DPAA В процессе инициализации BMan требуется выделить память для указателей на буферы. Адрес начала памяти и ее размер должен быть кратен 2^n. Физический адрес выделенного фрагмента памяти записывается в регистры BMan;При инициализации QMan требуется выделить память для указателей на дескрипторы и данные кадров, адрес начала памяти и ее размер также должен быть кратен 2^n;
При инициализации FMan задаются начальные настройки для QMan/BMan interface, DMA и прочих компонентов, настроить направления движения пакетов, задав соответствующий id назначения (Next invoked action/NIA);
Инициализация dtsec, MAC и PHY не содержит в себе каких-то трудностей и вполне стандартна для сетевых драйверов;
И еще надо инициализировать порталы, прерывания для всех менеджеров (MPIC мы уже настроили заранее), буферы в BMan и очереди в QMan;
Размер и количество буферов для сетевого трафика В теории можно создавать до 6 типов(размеров) буферов на 1 порт. Если мы хотим экономить память, то это будет полезно — зачем ICMP пакету занимать буфер в 2Кб? Давайте создадим кучку буферов по 128 байт! Зачем нам дробить jumbo frames? Создадим маленькую кучку буферов по 10Кб! И большую кучку по 1.6 Кб.На практике, буферы придется возвращать после обработки пакета, каждый в свою кучку. Для этого надо что-то вычислять, где-то хранить, я — ленивый, а память — дешевая, меньше код — меньше ошибок. Поэтому мы обошлись одной кучей по 2кб, общей для всех портов.
Количество очередей(FQ) на сетевой интерфейс В минимальной конфигурации нам потребуется для приема пакетов — одна очередь для входящих пакетов, одна очередь для ошибок, и одна или несколько внутренних очередей. Для отправки пакетов — одна очередь для приема ошибок, одна очередь для приема подтверждений и одна или несколько очередей для исходящих пакетов. Мы используем для отправки пакетов количество очередей равное буферу команд на отправку — 8.Интересно, что в драйвере от freescale распределением номеров очереди поручено BMan. В его буферный пул сохраняются номера от 0 до 0x1ff, которые являются номерами свободных очередей и запрашиваются при инициализации очереди.
Параметры очереди В параметрах очереди надо определять ее тип и к какому каналу и рабочей очереди она относится. Интересным параметром является поля contextB и contextA. В поле contextB мы можем положить любое число, например указатель на структуру с данными для обработки пакетов в этой очереди. Этот параметр будет доступен в обработчике прерываний. Поле contextА может содержать физический адрес, данные которого будут загружены в кэш до прихода прерывания. Прямо в L2. Размер данных кратен 32 байтам и указывается в параметрах.Процесс приема Пакет проходит PHY-MAC-DTSEC и попадает в порт Frame manager. В соответствии с размером пакета ему выбирается подходящий буфер и с помощью BMI интерфейса запрашивается у BMan. Дальнейшая судьба пакета зависит от настроек: пакет может быть подвергнут расшифровки, фильтрации, сортировки. В простейшем случае мы его просто отдаем в лапы QMan. Менеджер очередей ставит его в соответствующую очередь, канал и генерирует прерывание. Этот процесс наглядно показан в презентации от freescale: Все, что нужно сделать в обработчике прерываний — отпустить семафор потока обработки пакетов. Не заниматься же обработкой пакетов в контексте обработчика прерываний системы РВ ?! Да и в обычной системе нельзя так делать. Итак, обработчик прерываний запускает поток, который вычитывает очередь и обрабатывает буфер. Я использовал два типа буфера из четырех — целый (1 пакет — 1 буфер) и фрагметированный (S/G) и здесь ничего нового для сетевых драйверов нет. Хотя в драйвере от freescale S/G буфер был реализован только в январе этого года. По мере обработки пакетов сетевым стеком буферы возвращаются менеджеру буферов в кучу, откуда он был взят FMan.Процесс передачи Формируем из пакета S/G сисок по формату и ставим его в очередь QMan. Дальнейший процесс аналогичен приему и драйвер в нем уже не участвует.Заключение Безусловно, здесь описана только часть процесса инициализации DPAA, позволяющая его цинично использовать как простой 5 портовый ethernet адаптер. Надеюсь, что на этом разработка не закончится и нас ждет увлекательное путешествие в дебри аппаратных ускорений обработки сетевого трафика.