2013-05-03 3 views
2

J'utilise packet_mmap pour lire un flux rapide de paquets UDP. Lorsque vous utilisez l'un des segments de code suivants pour attendre les trames entrantes, il fonctionne très bien.Quelques problèmes avec PACKET_MMAP

// 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) 
    } 

Cependant lorsque je tente d'attente occupé (while(!(header -> tp_status & TP_STATUS_USER)) ; la déclaration reste vrai indéfiniment après quelques paquets sont lus Pourquoi est-ce donc? ? est-ce que le noyau ne transférer que des cadres dans la mémoire tampon de sonnerie lorsqu'un appel système est émis la prise d'entrée est initialisée comme si:. socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))

aussi, lorsque vous utilisez ce code (en utilisant sondage ou nanosleep), il semble être à la baisse des paquets, alors qu'un simple code de réception utilisant une socket UDP ne le fait pas, ce qui rend l'implémentation de packet_mmap plus lente, parfois les paquets perdus sont détectés par les sockets, mais en utilisant leOption-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); 
    } 

il déclare qu'aucun paquet ont été abandonnées (exemple de sortie: "la perte de paquets: [0, 5]"). Est-ce que PACKET_STATISTICS se comporte différemment sur les sockets PACKET_RX_RING?

Le code complet pour ce code liste est disponible here

Répondre

2

Juste au cas où quelqu'un rencontre ce problème, attente occupé était « suspendu » parce tpacket_hdr était en cours d'optimisation et dans les registres et sa valeur non cochée dans la mémoire. Marquer cela comme volatile garantit que toute modification apportée par le noyau à cette structure est vue par l'application.

Les baisses de paquets détectées avec PACKET_STATISTICS étaient pour les premiers paquets reçus, et le reste était dû au fait que l'application ne suivait pas les paquets entrants en raison du surcoût causé par les appels système.

Questions connexes