Некоторые проблемы с 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 были для первых нескольких пакетов, которые были получены, а остальные были из-за того, что приложение не успевало за входящими пакетами из-за дополнительных издержек, вызванных системными вызовами.

Другие вопросы по тегам