Некоторые проблемы с PACKET_MMAP
Я использую package_mmap для чтения быстрого потока пакетов UDP. При использовании любого из следующих сегментов кода для ожидания входящих кадров все работает нормально:
// ring[i].iov_base points to the start address of the ith frame
struct tpacket_hdr *header = (struct tpacket_hdr *) ring[i].iov_base;
// Using poll on socket to wait for data
while(!(header -> tp_status & TP_STATUS_USER))
{
struct pollfd pfd;
pfd.fd = _socket;
pfd.events = POLLIN | POLLERR;
pfd.revents = 0;
poll(&pfd, 1, -1);
}
// Using nanosleep to wait for incoming data
while(!(header -> tp_status & TP_STATUS_USER))
{
struct timespec t, r;
t.tv_nsec = 1;
t.tv_sec = 0;
nanosleep(&t, &r)
}
Однако, когда я пытаюсь заняты ждать (while(!(header -> tp_status & TP_STATUS_USER)) ;
утверждение остается Истинным бесконечно после считывания нескольких пакетов. Почему это так? Передает ли ядро только кадры в кольцевой буфер при системном вызове? Входной сокет инициализируется так: socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))
,
Кроме того, при использовании этого кода (с использованием poll или nanosleep) кажется, что он отбрасывает пакеты, в то время как простой код приема, использующий сокет UDP, этого не делает, что замедляет реализацию packet_mmap. Иногда отбрасываемые пакеты обнаруживаются сокетами, однако при использовании PACKET_STATISTICS
возможность getsockopt
:
if (header -> tp_status & TP_STATUS_LOSING)
{
struct tpacket_stats stats;
socklen_t size_sock = sizeof(tpacket_stats);
if (getsockopt(_socket, SOL_PACKET, PACKET_STATISTICS, &stats, &size_sock) > -1)
printf("Dropped packets: [%d, %d]\n", stats.tp_drops, stats.tp_packets);
}
в нем говорится, что ни один пакет не был отброшен (пример вывода: "Отброшенные пакеты: [0, 5]"). Есть ли PACKET_STATISTICS
вести себя по-разному на PACKET_RX_RING
Розетки?
Полный список кодов для этого кода доступен здесь
1 ответ
На всякий случай, если кто-то сталкивается с этой проблемой, ожидание "зависло", потому что tpacket_hdr
был оптимизирован и в регистры, и это значение не проверяется в памяти. Отмечать это как volatile
гарантирует, что любое изменение, внесенное ядром в эту структуру, будет замечено приложением.
Отбрасывание пакетов обнаружено с PACKET_STATISTICS
были для первых нескольких пакетов, которые были получены, а остальные были из-за того, что приложение не успевало за входящими пакетами из-за дополнительных издержек, вызванных системными вызовами.