Problem: Raw socket drops incoming packets.
Platform: Evm6748, current NDK, NSP
The problem is demonstrated in an application that opens a raw socket and then echoes raw packets back to the remote host. The program receives buffers and then has to release them. When packets are sent to the DSP too quickly, they are dropped. It appears that the drop rate is sensitive to how soon the buffer is freed..
In the code snippet copied below, the function sendmessage() can be a simple send(), or getsendncbuff() followed by mmCopy() andsend(). The problem behavior is the same regardless of what is in the send function.
Here is the behavior
- If the remote sends ethernet packets one at a time, everything works very well.
- If the remote sends two packets with no delay in between, one packet is received and one packet is dropped.
- If the remote sends five packets, then two out of five pacekts are dropped.
- If the call to sendmessage() is commented out, then recvnc() receives all of the packets that are sent.
- If a mmCopy() and recvncfree( ) are done before sendmessage() instead of the recvncfree() afterwards, then one in five packets is dropped.
Behavior 5 is interesting. The loop is longer because of the extra mmCopy(), yet the drop rate is lower (compare to 3.). The difference is that the buffer is freed sooner. In other words, it looks like it does not have enough buffers, or perhaps the raw socket only has one buffer.
Mitch Nelson
Code Snipper for the problem report:
fdOpenSession( TaskSelf() );
hRawSocket = socket(AF_RAWETH, SOCK_RAWETH, rawether_type );
val = 1; retval = setsockopt( hRawSocket, SOL_SOCKET, SO_IFDEVICE, &val,
sizeof(val) );
val = rawchannel_num; retval = setsockopt(hRawSocket, SOL_SOCKET, SO_PRIORITY, &val,
sizeof(val));
val = 8192; retval = setsockopt(hRawSocket, SOL_SOCKET, SO_RCVBUF, &val,
sizeof(val));
to.tv_sec = 0; to.tv_usec = 0; setsockopt( hRawSocket, SOL_SOCKET, SO_SNDTIMEO, &to,
sizeof( to ) );
setsockopt( hRawSocket, SOL_SOCKET, SO_RCVTIMEO, &to,
sizeof( to ) );
for( ; ; )
{
LOG_printf(&trace,
"linkstatus %d, calling recvnc\n", preprocessor_linkstatus );
retval = (
int) recvnc( hRawSocket, (void **) &prcvbuf, 0, &hrcvbuf );
if ( retval < 0 ) {
);
else if ( retval > 14 ) {
LOG_printf(&trace,
"recvnc returned %d\n", retval );
sendmessage( (unsigned char *)rawbuffer, nsend ) == ENOBUFS );
recvncfree()
}
}