Ich möchte die Linux-Socket-Option SO_RXQ_OVFL verwenden, um UDP-Überlauf zu erkennen. Diese Option verwendet eine zusätzliche Nachricht, um die Anzahl der gelöschten Pakete zu melden. Von Mann:Wie kann man mit Hilfe von SO_RXQ_OVFL einen UDP-Überlauf auf einem Linux-Socket erkennen?
SO_RXQ_OVFL (since Linux 2.6.33)
Indicates that an unsigned 32-bit value ancillary message (cmsg) should be
attached to received skbs indicating the number of packets dropped by the
socket between the last received packet and this received packet.
Mein Code findet die zusätzliche Nachricht nicht. Hier ist, was ich tue:
Beim Start ich den Socket erstellen und die SO_RXQ_OVFL Socket-Option angeben:
int dropmonitor_on = 1;
if (setsockopt(udpSocket, SOL_SOCKET, SO_RXQ_OVFL, &dropmonitor_on, sizeof(dropmonitor_on)) != 0)
{
perror("setsockopt SO_RXQ_OVFL not supported by your Linux Kernel");
}
Dann habe ich eine Funktion erhalten, die recvmsg ruft und sucht die Neben Nachricht:
struct sockaddr_in src_addr; // The source address will be assigned to here
struct iovec iov[1];
iov[0].iov_base=ap_rxBuffer;
iov[0].iov_len=a_maxSizeBytes-1;
int cmsg_len = CMSG_SPACE(sizeof(uint32_t));
char cmsg[CMSG_SPACE(sizeof(uint32_t))];
memset(cmsg,0,cmsg_len);
struct msghdr message;
memset(&message,0,sizeof(struct msghdr));
message.msg_name=&src_addr;
message.msg_namelen=sizeof(struct sockaddr_in);
message.msg_iov=iov;
message.msg_iovlen=1;
message.msg_control=cmsg;
message.msg_controllen=cmsg_len;
int receivedBytes = 0;
if ((receivedBytes = recvmsg(a_socket, &message, 0)) == SOCKET_ERROR)
{
closeSocket(a_socket);
fatal("recvmsg() failed");
}
else
{
// Reception successful so interrogate ancillary message to get number of dropped packets
int udp_packets_dropped = 0;
struct cmsghdr* p_cmsg;
p_cmsg = CMSG_FIRSTHDR(&message);
for (p_cmsg = CMSG_FIRSTHDR(&message); p_cmsg != NULL; p_cmsg = CMSG_NXTHDR(&message, p_cmsg))
{
if ((p_cmsg->cmsg_level == SOL_SOCKET) && (p_cmsg->cmsg_type == SO_RXQ_OVFL))
{
int* p_udp_packets_dropped = (int *) CMSG_DATA(p_cmsg);
udp_packets_dropped = *p_udp_packets_dropped;
cout << "UDP pkts dropped: " << udp_packets_dropped << endl;
break;
}
}
if (p_cmsg == NULL)
{
fatal("Error: p_cmsg == NULL");
}
}
Wenn ich führen sie den Code mit diesem fatalen Fehler stoppt:
Error: p_cmsg == NULL
die i s generiert durch den obigen Code und zeigt an, dass keine zusätzliche Nachricht gefunden wurde. Seltsamerweise bekomme ich manchmal eine ergänzende Nachricht, vielleicht habe ich etwas nicht initialisiert.
Ich habe den Code sorgfältig überprüft, kann aber nichts falsches sehen. Ich wäre Ihnen für eine Hilfe dankbar.
Ich habe einige Testcodes geschrieben und jetzt kann ich sicher sein. Ich habe auch festgestellt, dass der Wert in SOCK_SKB_CB (skb) -> dropcount nach recvmsg nicht zurückgesetzt wird. Als ich den Kernel-Code gelesen habe, war ich voller Neugierde, warum ich den irgendwo den Wert nicht zurücksetzen kann. Das heißt, wenn der Wert nicht Null ist, erhalten Sie den Wert in cmsg. – alpha