I'm sending multicast packets on a MOD54415 with 2.6.7. When sending UDP packets, assuming a free buffer is available, is there anything that can cause the send() call to block? Will it block if another packet TX is in progress or will it be queued up? I can't tell if the TX of the packets takes place on a task or just handled by an ISR. The comments for Ether_ProcessTask in ethernet.cpp talk about transmitting data but the code looks to only handle RX. I stepped into send() but eventually I reached dbetherhardware.cpp which appears to be a precompiled library so I can't tell where the send actually takes place. I was expecting it to step into EthTransmitBuffer. I did see an OSSemPend inside EthTransmitBuffer but that looks like multithread protection around the PoolPtr passed in so it wouldn't block for long.
Thanks, Bob
Can sending UDP packets block?
Re: Can sending UDP packets block?
Yes, UDP send can block. If you have queued all available TX descriptors, UDP will block until at least one descriptor is available. The chain of calls that happen is Send -> FixHeaderAndSend -> RouteOut -> TransmitBuffer (points to EthTransmitBuffer for ethernet interfaces).
In EthTransmitBuffer there is a OSSemPend( &SendSem, 0 ) call.
In EthTransmitBuffer there is a OSSemPend( &SendSem, 0 ) call.
Dan Ciliske
Project Engineer
Netburner, Inc
Project Engineer
Netburner, Inc
-
- Posts: 22
- Joined: Mon Jan 27, 2014 7:19 pm
Re: Can sending UDP packets block?
Is there a convenient way to tell if all TX descriptors are in use? I would rather just drop the packet and return an error instead of it waiting. Even if I implemented a separate task to queue up the the UDP packets, it too may back up eventually if the load is high enough (although not likely since my average TX data rate is very low). How many TX descriptors are there and is it one per packet or one per fragment?
-Bob
-Bob
Re: Can sending UDP packets block?
One descriptor per physical ethernet frame. The number of TX descriptors is set in 'ethervars.h' in the platform include. It is normally set to 3. There's not really an easy way to check, given that this is very tightly coupled deep down in the world.
Here's my workaround if you really do just want to drop the packet:
Modify ethernet.cpp to abort if the OSSemPend returns OS_TIMEOUT. Then, lock the calling task just before you send the UDP message and unlock it afterwards.
becomes
Then your calling code gets wrapped as such
I think this should work to throw the packet away.
Here's my workaround if you really do just want to drop the packet:
Modify ethernet.cpp to abort if the OSSemPend returns OS_TIMEOUT. Then, lock the calling task just before you send the UDP message and unlock it afterwards.
Code: Select all
OSSemPend ( &SemSend, 0 );
Code: Select all
if (OSSemPend( &SemSend, 0 ) == OS_TIMEOUT) {
pb->bBuffer_state = BO_SOFTWARE;
FreeBuffer ( pb );
return;
}
Code: Select all
OSLock();
pkt.Send();
OSUnlock();
Dan Ciliske
Project Engineer
Netburner, Inc
Project Engineer
Netburner, Inc
-
- Posts: 22
- Joined: Mon Jan 27, 2014 7:19 pm
Re: Can sending UDP packets block?
Great - thanks a bunch!
-Bob
-Bob
-
- Posts: 22
- Joined: Mon Jan 27, 2014 7:19 pm
Re: Can sending UDP packets block?
I think the call should be OSSemPendNoWait to check for the timeout. It's interesting - with the patch, I'm only able to get it to fail/timeout once, a few seconds after boot and never again. As a test, I'm sending 100 packets (1 KB each) back to back in a burst so you would think sending that many in a row would make it run out of the 3 TX descriptors. Or is it because the IP/Ether tasks will process all their packets before returning? Within the burst, the first send takes ~40 us, then the send times drop off to 18 us. On the one time the semaphore timed out (I modified the patch to log the timeout and then let it wait for the sem to continue), it took 60 us but that's probably due to the iprintf I stuck in there for debugging. So other than the blip a few seconds after boot, I was unable to generate a backup sending UDP packets. That's good I guess but not what I would expect.
Are the transmit packets managed on the Ether_ProcessTask or an ISR? I'm was planning on putting a a couple of very short tasks (high rate SPI reads) at a priority < ETHER_SEND_PRIO.
-Bob
Are the transmit packets managed on the Ether_ProcessTask or an ISR? I'm was planning on putting a a couple of very short tasks (high rate SPI reads) at a priority < ETHER_SEND_PRIO.
-Bob
-
- Posts: 22
- Joined: Mon Jan 27, 2014 7:19 pm
Re: Can sending UDP packets block?
Ok, you can ignore pretty much everything in my previous post (except that OSSemPendNoWait is needed to make the patch work). I fired up Wireshark and it's easier to tell what is going on. With the patch (that drops packets if busy), as expected only around 2-3 packets can be sent back-to-back without dropping some. When I was measuring 18 us for a send() call, that was the case where the packets were being dropped. Times for send() of small packets are between 50 and 100 us.
Thanks again for the help!
-Bob
Thanks again for the help!
-Bob