私は、rawソケット(AF_PACKET、SOCK_RAW)を使用してネットワークパケットをスニッフィングし、何らかの方法でそれらを処理するプログラムを開発しています。
プログラムが十分に高速に実行され、ソケット上のすべてのパケットをキャプチャすることに成功したかどうかはわかりません。このソケットの受信バッファが(トラフィックバーストのために)ときどきいっぱいになり、一部のパケットがドロップされるのではないかと心配しています。
ソケットの受信バッファのスペースが不足しているためにパケットがドロップされたかどうかを確認するにはどうすればよいですか?
ss -f link -nlp
を実行してみました。
これは、そのソケットのリビジョンバッファに現在格納されているバイト数を出力しますが、パケットがドロップされたかどうかはわかりません。
私はbuntu 14.04.2 LTS(GNU/Linux 3.13.0-52-generic x86_64)を使用しています。
ドロップされたパケットは、netstat、ethtoolの出力から確認できます。 UDPパケットドロップについては、'netstat -us'
の出力を確認してください。パケットはNICレイヤー自体にもドロップされます。これは、'ethtool -S <device_name>'
で確認できます。
出力例:
$ netstat -us
IcmpMsg:
InType3: 44
InType8: 5
InType13: 1
InType17: 3
InType37: 1
OutType0: 5
OutType3: 599
OutType8: 4
OutType14: 1
Udp:
86942 packets received
209 packets to unknown port received.
**0 packet receive errors** <== This indicates packets dropped due to socket buffer full
213901 packets sent
UdpLite:
IpExt:
InOctets: 38683476091
OutOctets: 959938111
より大きなバッファースペース(SO_RCVBUF)を使用してみて、sysctl controlnet.core.rmem_maxを介してシステム全体の最大値を増やしてください
NICレイヤーでは、バーストトラフィックを処理するためにリングバッファを増やすこともできます(ethtool -g
で設定を確認してください)
packet(7) のマンページで説明されているように、PACKET_STATISTICSソケットオプションを使用して、プログラムで受信したパケットの総数とドロップしたパケットの数を取得できます。
#include <linux/if_packet.h>
#include <sys/socket.h>
#include <sys/types.h>
...
struct tpacket_stats lStats = {};
socklen_t lStatsLength = sizeof( lStats );
if ( getsockopt( mRawSocket, SOL_PACKET, PACKET_STATISTICS, &lStats, &lStatsLength ) == 0 )
{
printf( "Total Packets: %u\nDropped Packets: %u\n", lStats.tp_packets, lStats.tp_drops );
}
else
{
perror( "Failed to get network receive statistics" );
}