Wi-Fi driver throws out packets if sent too fast. How can we know when the driver queue is full so we can wait and not overload it?

We need very fast Wi-Fi transfer rates at times.  I have been able to tune the code and Wi-Fi driver settings to get up to 30-35 Mbps which is great.  But if I don't throttle the transmission then the faster the packets are sent, the higher the percentage are thrown out by the Wi-Fi driver.

The application level zsock_send(sock, packet, size, 0) function blocks, so I would think that would automatically throttle how fast the data is sent from the application so that it doesn't overflow any downstream buffers such as in the Wi-Fi driver.  But that is not the case.  If the data is sent too quickly, then a large percentage of packets are lost.  I traced it down to the Wi-Fi driver:

nrf_wifi_if_send() -> nrf_wifi_fmac_start_xmit() -> nrf_wifi_fmac_tx() -> tx_process() - tx_enqueue()

If the queue is full then it just silently discards any additional packets.  This does not block the application, so it just keeps sending without knowing that 10-25% (depending on the sending speed) of the packets are being ignored and never sent.

So if the queue being full doesn't bubble up and cause the zsock_send() call to block, how do I know when I'm sending too fast and the driver queue is overflowing?  I tried increasing the queue size with CONFIG_NRF700X_MAX_TX_PENDING_QLEN, but that doesn't really help since we have sustained high speeds for a few seconds.  If the queue is being filled faster than it is being emptied, no matter how big it is it will overflow.  So I need some way to automatically slow the sending of the packets to avoid the overflow.

  • Is there a function to call to get the low level driver queue state?
  • Is there a way to get a count of how many packets the tx_enqueue or tx_process functions are discarding?  Maybe I could poll that as a way to infer when overflow is occurring.  But I'd rather not have any overflow at all, because that means lost packets and I won't know which ones.
  • Is there maybe a callback or something that can send an event when the queue is getting close to full?
  • Is there a way to make zsock_send() truly block if the downstream queue is full?

The zperf speed test has a loop that generates successive packets and calls zsock_send() to send them.  If the loop time is too short for the target data rate it is trying to get then it will insert delays with k_sleep() to slow things down.  But if the target speed is set too high, the Wi-Fi driver starts throwing out packets.  And if the delay is removed completely so the loop runs as fast as the zsock_send() blocking allows, then even more packets get thrown out.

There has to be a way to send as fast as possible, but wait when the Wi-Fi Tx queue gets full so it can catch up.  How can I do this?

Parents Reply Children
No Data
Related