Получение пакетов сокетов RAW с точностью до микросекунд

Я пишу код, который получает необработанные пакеты ethernet (без TCP/UDP) каждые 1 мс с сервера. Для каждого полученного пакета мое приложение должно ответить 14 необработанными пакетами. Если сервер не получает 14 пакетов до того, как он отправит пакет, запланированный на каждые 1 мс, тогда сервер вызывает тревогу, и приложение должно выйти из строя. Связь между сервером и клиентом - это одна к одной ссылке.

Сервер - это аппаратное обеспечение (FPGA), которое генерирует пакеты с точным интервалом 1 мс. Клиентское приложение работает на Linux (RHEL/Centos 7) с 10G SolarFlare NIC.

Моя первая версия кода похожа на эту

while(1)
{
  while(1)
  {
     numbytes = recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL);
     if(numbytes > 0)
     {
        //Some more lines here, to read packet number
        break;
     }
  }
  for (i=0;i<14;i++)
  {
     if (sendto(sockfd,(void *)(sym) , sizeof(sym), 0, NULL, NULL) < 0)
            perror("Send failed\n");
  }
}

Я измеряю время приема, беря отметки времени (используя clock_gettime) перед вызовом recvfrom и один за ним, я печатаю разницу во времени этих временных меток и печатаю их каждый раз, когда разница во времени превышает допустимый диапазон 900-1100 нас.

Проблема, с которой я сталкиваюсь, заключается в том, что время приема пакета колеблется. Что-то вроде этого (отпечатки находятся в микросекундах)

Decode Time : 1234
Decode Time : 762
Decode Time : 1593
Decode Time : 406
Decode Time : 1703
Decode Time : 257
Decode Time : 1493
Decode Time : 514
and so on..

И иногда время декодирования превышает 2000us, и приложение будет ломаться.

В этой ситуации приложение будет прерываться от 2 секунд до нескольких минут.

Параметры, которые я использовал до сих пор.

  • Настройка близости к изолированному ядру.
  • Настройка приоритетов планирования с максимальным значением с помощью SCHED_FIFO
  • Увеличение размеров буфера сокетов
  • Настройка сетевого интерфейса прерывает сродство к тому же ядру, которое обрабатывает приложение
  • Скручивание recvfrom с помощью вызовов poll(),select().

Все эти параметры дают значительное улучшение по сравнению с исходной версией кода. Теперь приложение будет работать в течение ~ 1-2 часов. Но этого все еще недостаточно.

Несколько наблюдений:

  • Я получаю огромный дамп этих отпечатков времени декодирования, когда я принимаю ssh-сессии на Linux-машине во время работы приложения (что заставляет меня думать, что сетевая связь через другой интерфейс Ethernet 1G создает помехи для интерфейса Ethernet 10G).
  • Приложение работает лучше в RHEL (время работы около 2-3 часов), чем Centos (время работы около 30 минут - 1,5 часа)
  • Время выполнения также зависит от машин Linux с различными конфигурациями оборудования с той же ОС.

Просьба указать, есть ли какие-либо другие способы улучшения времени выполнения приложения.

Спасибо заранее.

Ответ 1

Во-первых, вам необходимо проверить точность метода timestamping; clock_gettime. Разрешение - наносекунды, но точность и точность под вопросом. Это не ответ на вашу проблему, но информирует о том, насколько надежна отметка времени перед продолжением. См. Разница между CLOCK_REALTIME и CLOCK_MONOTONIC? за то, почему CLOCK_MONOTONIC следует использовать для вашего приложения.

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

Операции для каждого декодирования Я не могу комментировать, поскольку код был упрощен в вашем сообщении. Эта проблема также может быть профилирована и проверена.

Контекстное переключение на процесс может быть легко проверено и контролироваться https://unix.stackexchange.com/a/84345

Как заявил Рон, это очень строгие требования времени для сети. Это должна быть изолированная сеть и единая цель. Ваше наблюдение за временем перекодировки, когда ssh'ing указывает на весь другой трафик, должно быть предотвращено. Это вызывает беспокойство, учитывая отдельные сетевые адаптеры. Таким образом, я подозреваю, что проблема IRQ. См. /Proc/interrupts.

Для достижения согласованного времени декодирования в течение длинных интервалов (часов- > дней) потребуется значительно упростить ОС. Удаление ненужных процессов и сервисов, оборудования и, возможно, создание собственного ядра. Все для уменьшения переключения контекста и прерываний. В этот момент следует рассмотреть ОС реального времени. Это только улучшит вероятность согласованного времени декодирования, а не гарантирует.

Моя работа заключается в разработке системы сбора данных, которая представляет собой комбинацию АЦП с ПЛИС, ПК и ethernet. Неизбежно, несогласованность многоцелевого ПК означает, что некоторые функции должны быть перенесены на выделенное оборудование. Рассмотрите преимущества/недостатки разработки вашего приложения для ПК и переноса его на аппаратное обеспечение.