Мультикаст в мире RDMA занимает нишу скромную, но важную: раздача рыночных данных на десятки подписчиков, оповещения кластерных служб, дублирование потоков на зеркала. В классическом Ethernet всё это решается привычно, а вот в RDMA мультикаст живёт по собственным правилам протокола: подписка идёт через менеджер подсети, доставкой занимается ненадёжный датаграммный режим, и есть тонкость, которая регулярно удивляет новичков, отправитель, состоящий в группе, получает собственные кадры обратно. Именно эта петля приёма собственных кадров, плюс возможность собрать программную петлю на одном узле без фабрики, и определяют практику работы с механизмом.

Разберём механику групп, код подписки и отправки, поведение петли, особенности RoCEv2 и программную петлю для тестов. Материал собран с прицелом на практику: половина сюрпризов мультикаста в RDMA лежит не в коде, а в поведении фабрики и петли, и лучше встретить их заранее описанными.

Мультикаст в RDMA с группами MLID и очередями UD

Мультикаст в InfiniBand работает только через очереди ненадёжного датаграммного режима, UD. Членство оформляется не на узле, а в менеджере подсети: приложение просит присоединить порт к группе по её глобальному идентификатору MGID, менеджер выделяет локальный идентификатор группы MLID и заносит запись о членстве в таблицу, а коммутаторы фабрики разносят кадры группы по портам участников. Доставка невыгодна по определению: UD не подтверждает кадры, ретрансляций нет, и механизм мультикаста наследует эту честность без гарантий, что и объясняет его применение там, где редкая потеря приемлема, а массовая рассылка нужнее каждой отдельной гарантии.

Отправка строится через адресный дескриптор: кадр адресуется на DLID, равный MLID группы, глобальный маршрут несёт MGID, а в дескрипторе датаграммного режима передаётся ключ очереди QKey, общий для отправителей группы. Диапазон локальных идентификаторов групп ограничен верхним сегментом адресного пространства, и менеджер подсети выдаёт их из этого пула, поэтому число активных групп и участников имеет административные потолки, описываемые в документации фабрики. Запись членства в менеджере несёт и атрибуты качества, уровень сервиса и скорость группы, и несогласованные значения между записью фабрики и настройками приёмников дают кадры, которые кто-то видит, а кто-то нет. Подписка на приём и отправка с неверным ключом расходятся по разным кодам ошибок, и оба случая диагностируются по статусам завершений, которые легко спутать с сетевыми проблемами, если не держать в голове эту пару проверок.

Код подписки и отправки

Каноническая последовательность в libibverbs выглядит компактно:

union ibv_gid mc_gid;
inet_pton(AF_INET6, "ff0e::1234", &mc_gid.raw);

struct ibv_multicast *mc = ibv_join_multicast(qp, &mc_gid, 0);

struct ibv_ah_attr ah_attr = {0};
ah_attr.dlid = mc->mlid;
ah_attr.grh.dgid = mc_gid;
ah_attr.grh.hop_limit = 1;
struct ibv_ah *ah = ibv_create_ah(pd, &ah_attr);

struct ibv_send_wr wr = {0};
wr.wr.ud.ah = ah;
wr.wr.ud.remote_qkey = my_qkey;
wr.opcode = IBV_WR_SEND;
ibv_post_send(qp, &wr, &bad);

Вызов подписки возвращает структуру с подтверждённым идентификатором группы, из которой берётся DLID для адресного дескриптора, а выход из группы делается парной функцией ibv_detach_multicast. Нюанс подготовки очереди: UD-очередь должна знать свой QKey ещё на этапе модификации атрибутов, и рассинхрон ключей между отправителем и приёмниками диагностируется уже по месту, где кадр пропал. Адресные дескрипторы кешируются в драйвере, поэтому в горячем пути их создают один раз на группу, а не на каждый пакет. Подготовка очереди UD включает собственный ключ и начальный номер пакетов, а полезным дополнением служит немедленные данные в отправке: тридцать два бита сразу в завершении приёмника экономят отдельный механизм синхронизации, и порядковые номера рассылки удобно гонять именно через них.

Петля приёма собственных кадров

Поведение петли в InfiniBand строгое и предсказуемое: кадр мультикаста доставляется всем портам, числящимся в группе, включая порт отправителя, если тот подписан. Отсюда два практических следствия. Первое, приложение-издатель, подписанное на собственную группу для отладки, обязано фильтровать собственные кадры, и делают это по исходному номеру очереди в дескрипторе завершения приёма:

if (wc.src_qp == my_qp_num)
  continue;

либо по глобальному идентификатору источника из заголовка маршрута. Второе, издателю, не желающему слышать себя, достаточно просто не подписывать свою очередь, и петля не возникнет вовсе, потому что членство, а не передача, определяет приём. Отладка дубликатов при этом не требует мистики: в логах приёма с выводом исходных номеров очередей собственные кадры мгновенно выстраиваются в отдельный класс. Второе, издателю, не желающему слышать себя, достаточно просто не подписывать свою очередь, и петля не возникнет вовсе, потому что членство, а не передача, определяет приём.

С Ethernet контраст прямой: сетевой контроллер не возвращает переданное обратно, а коммутатор с подписками не заведёт мультикаст на порт источника, и приложения привыкли к отсутствию собственных эхо. На фабриках Ethernet без подписок группы размазываются на все порты домена, и в этой среде собственное эхо возможно, но выглядит как неожиданность настройки, тогда как в InfiniBand оно регулярное поведение, прописанное в правилах групп. Переносчики логики с Ethernet на RDMA попадают на этот нюанс с типичным симптомом, двойная обработка каждого сообщения, и лечится он либо фильтром по QPN, либо разрывом собственного членства. Отдельно стоит помнить, что членство управляется на уровне порта, и второй порт того же узла в группе не получит кадры первого, пока не подпишется сам.

Особенности RoCEv2 и Ethernet-основы

В RoCEv2 мультикаст живёт поверх Ethernet-мультикаста, и это меняет часть правил. Группы записываются в формате отображения IPv4-мультикаста, доставка идёт по правилам коммутации второго уровня, членство контролируется механизмами подписки Ethernet, и через границу маршрутизатора обычный мультикаст RDMA не идёт, что делает его средством внутри одного домена коммутации. Практическое следствие для архитектора: рассылка между стойками, разделёнными маршрутизацией, потребует либо растяжения домена, либо замены механизма на надёжные очереди или коллективы, и лучше выбрать это на этапе проектирования, чем в разборке инцидента. Пропускная способность репликации ложится на коммутаторы, и на фабриках с дублированием через несколько линий мелкий мультикастный трафик размазывается по линиям иначе, чем привычный потоковый, что иногда проявляется в балансировке.

Отдельная тема, взаимодействие с приоритезацией и управлением потоком: кадры UD без подтверждений, и механизмы управления потоком второго уровня к ним применяются осторожно, поэтому плотность мультикаста на фабрике планируют отдельно, не полагаясь на то, что управление потоком спасёт от переполнения приёмников. Для сервисов, которым нужна надёжная рассылка в масштабах фабрики, индустрия давно ушла в аппаратные коллективы с выгрузкой в коммутаторы, и мультикаст UD остаётся средством простых оповещений и потоков данных, где потеря единичных кадров лечится на приёме.

Программная петля для тестов через Soft-RoCE

Отлаживать мультикаст-логику без фабрики помогает программная реализация RoCE, модуль ядра rdma_rxe, навешенный на интерфейс обратной петли:

modprobe rdma_rxe
rdma link add rxe0 type rxe netdev lo
ibv_devinfo -d rxe0
ibv_rc_pingpong -d rxe0

После такой настройки узел обзаводится полноценным RDMA-устройством без единого сетевого контроллера, и два процесса на одном хосте обмениваются через него как через настоящий адаптер. Поддержка групп в программной реализации есть, включая таблицы членства, что позволяет гонять мультикаст-логику без фабрики целиком. Параллельно существует и второй программный стек, Soft-iWARP, но для задач этого класса именно RoCE-реализация ближе по поведению к аппаратным портам. Для проверки кода групп это идеальный стенд: подписки, ключи очередей, фильтрация собственных кадров и адресация через глобальные заголовки отрабатываются целиком, и только после этого перенос на аппаратный порт остаётся делом производительности. Ограничения стенда предсказуемы: всё считается процессором, полоса ограничена и зависит от ядра, метки времени аппаратных часов отсутствуют, и размер передаваемых единиц упирается в интерфейс обратной петли, но для корректности логики этого более чем достаточно.

Зеркальный подход работает и на реальном железе без фабрики: пара узлов, соединённых кабелем напрямую, даёт честный аппаратный путь для базовой проверки, а групповые тесты уже требуют коммутатора с поддержкой репликации групп, что стоит предусмотреть в стенде заранее, если мультикаст в проекте не просто флаг компиляции.

Ограничения мультикаста и вопросы надёжности

Ограничения мультикаста в RDMA стоит проговаривать открыто. Доставка без подтверждений означает потерю кадров при переполнении приёмников, и компенсировать её приходится на уровне приложения, порядковыми номерами, повторными запросами пропущенного либо периодическими сводками состояния. Отсутствие управления потоком для групп означает, что медленный подписчик не притормозит издателя, и издатель обязан калибровать темп под самого тихого участника либо мириться с потерями у него. Размер кадров ограничен согласованным MTU, максимум для базового транспорта составляет четыре килобайта, и большие сообщения режутся приложением на части с собственной сборкой. Число групп и участников ограничено таблицами менеджера подсети и коммутаторов, и на больших фабриках этот потолок стоит проверять, а не угадывать. Взвешивая альтернативы, стоит помнить о выгруженных коллективных операциях, где коммутаторы сами собирают и раздают результаты, экономя и полосу, и процессоры участников, и о банальной посылке по списку адресов через надёжные очереди, которая на десятках получателей нередко оказывается дешевле мультикаста с его оговорками.

Взвешивая альтернативы, стоит помнить о деревьях репликации на прикладном уровне, о выгруженных коллективных операциях с аппаратной поддержкой и о банальной посылке по списку адресов через надёжные очереди, которая на десятках получателей может оказаться дешевле мультикаста с его оговорками. Мультикаст выигрывает там, где получателей много, а кадр один, и проигрывает там, где к потоку предъявляются гарантии доставки. Немедленные данные в завершениях приёма позволяют совместить рассылку с лёгкой сигнализацией, и на практичных схемах пара данных с немедленным кодом покрывает большинство нужд оповещений без единого дополнительного механизма.

Практический порядок проверки на стендах

Проверку механизма на проекте удобно вести по шагам:

  1. собрать стенд из Soft-RoCE на интерфейсе обратной петли и прогнать базовую пару процессов;
  2. проверить подписку и отправку в группу на стенде, включая фильтрацию собственных кадров по QPN;
  3. повторить на аппаратной паре напрямую, без фабрики, и сверить статусы завершений;
  4. вынести тест на коммутатор с группами, проверив видимость участников и репликацию;
  5. заложить обработку потерь, порядковые номера и повторные запросы, и проверить поведение при нагрузке выше полосы группы;
  6. зафиксировать параметры групп, ключей и темпов в конфигурации сервиса и в документации фабрики.

Последовательность выглядит длинной, но каждый шаг занимает минуты, и именно она отличает рабочий мультикаст от демонстрационного: без обработки потерь и фиксации темпов механизм живёт до первого пика нагрузки, после которого начинается расследование по горячим следам.

Итог у мультикаста в RDMA сбалансированный: простой механизм групповой доставки без гарантий, с честной петлёй собственных кадров и с полной отладкой на программной петле. Настройка аккуратных приложений с фильтрацией и калибровкой темпа делает его надёжным инструментом для рассылок в пределах домена коммутации, а программная петля снимает входной барьер, позволяя довести логику до ума задолго до того, как в стойке появится фабрика.