Closed pangorgo closed 8 years ago
Thanks for the report! It is a bit ugly that the max. PDU size is hardwired; it would be great if we could make this configurable by a command-line option. (Also, 1500 bytes is a somewhat funny size at the UDP level.) Your workaround is fine. Don't worry about TCP—the samplicator really only works for UDP.
As you point out, the "excess bytes" test seems broken in the code. It would be great to fix that. Thanks for pointing to the MSG_TRUNC
flag! We'd probably need to change from using recvfrom()
to recvmsg()
to see that flag. Correct? Personally I think that would be a good move anyway, because it opens the door to receiving several datagrams in one call (scatter/gather), which would be a performance win in situations with high packet rates.
Would you be able to propose a patch for correct truncation detection? I'll happily review it.
I changed the bug title a bit, hope that's OK!
Sure, in couple of days should find some time to propose a fix.
In Linux, there is a really clean way to solve this problem, and in many cases you don't even need to malloc. It's a datagram. Just ask the kernel how much data is waiting for you.
void always_get_entire_pdu(int fd)
{
ssize_t pending = recv(fd, NULL, 0, MSG_PEEK | MSG_TRUNC);
if (pending < 0) {
return;
}
// Now we know how big the datagram is and can push that many bytes on the stack.
#if defined(__STDC__) && (__STDC_VERSION__ >= 199901L)
uint8_t buf[pending];
#else
uint8_t *buf = alloca(pending);
#endif
ssize_t received = recv(fd, buf, pending, 0);
}
@msandstedt That looks nice. why don't you open a PR? :)
I am working with traffic from application which sends UDP datagrams longer than 1500 Bytes so they are fragmented in IP layer.
in samplicate.c PDU_SIZE is fixed to 1500 here
#define PDU_SIZE 1500
result of which - maximum 1500 bytes from buffer is copied and no warning nor error is thrown in case of longer UDP datagram.
I see that further there is some test that should catch longer datagram:
But at least in my case (kernel 2.6.18) it fails to catch it. I think the reason is lack of
MSG_TRUNC
flag inrecvfrom()
call for modern kernels (since 2.2).My workaround was changing PDU_SIZE to larger value, and it solved problem for my long UDP case but not sure if it won't broke something else - for example TCP handling.