Fragmentation and Recombination of L2CAP PDUs - first fragment size is less than (sizeof*l2cap_hdr) - packet dropped though valid (?)
Hi, I have a real life case, android app sending high throughput WriteNR packets to a ESP32-S3 device. Using MTU=323 (for desired user data payload of 320). Running BLE5 in LE 1M mode. The android device is pushing the packets through very aggressively, basically as fast as possible. Every once in a while, on certain android devices the L2CAP is fragmented such that the first fragment is only 3 bytes long. I believe this is valid in accordance to BLE spec, even the illustration in the core spec shows the CID cut in the border between the first and second fragments..
In ble_l2cap.c ble_l2cap_rx() it is assumed that always the first fragment includes at least 4 bytes with ble_l2cap_hdr, otherwise the complete recombined packet is consumed but dropped.
I believe the fragmentation is correct and the implementation in ble_l2cap.c is incorrect in this corner case, the header parsing should be done only after enough fragments with a full ble_l2cap_hdr are received.
Attached are HCI logs (data truncated to max 10 bytes to avoid log overflow) and the BLE core capture. Also some additional printouts I added.
Any thoughts from the experts? Is this a valid scenario? Wrong doing by the android or by the NIMBLE stack?
Shachar
capture_hci_odd_sized_DataPacketSmokingGun3_FirstFragmentSize3snippet.txt
That's indeed an issue in NimBLE host. I created a draft PR that reworks L2CAP RX routine and it should also fix this problem: https://github.com/apache/mynewt-nimble/pull/2022.
It seems to work fine with simple apps like bleprph so you can give it a try, but we'll need some more testing before it gets merged anyway.
Thanks @andrzej-kaczmarek , I will hopefully also review the draft PR from my side in the next few days.
Well, @andrzej-kaczmarek seems that I am unable to cherry pick and verify this on my level (my ESP32-S3 sdk is based off nimble_1_7_0_tag and there are too many changes to reliably pull these specific commits ). So I will have to wait for the next "official" release /tag and verify it then. Can you say when is the next tag planned? Are these done on a timely basis (every X months?) or per need?
@shachar-limor I rebased my code to 1.7.0, you can try to cherry-pick from this branch: https://github.com/andrzej-kaczmarek/apache-mynewt-nimble/tree/l2cap-rx-rework-170
As for the next official tag, we don't have anything planned yet. We try to do them every few month depending on the progress in development but it varies.
Hi @andrzej-kaczmarek , Thanks for your continued help. I wrestled with this rebase / cherry picking but it seems I am unable to converge with this process. I will have to wait for the next official tag, whenever it comes. Assuming this draft PR passed the necessary release gates then please merge and release it whenever possible. Thanks, Shcahar
fixed in master
Hi @sjanc @andrzej-kaczmarek , Can you tell when is the next Release / Tag planned? It has been almost a year now without an "official" release.
I'd like to try and push this with Espressif people (ESP32 / IDF still uses an older version of nimble) so that some bugfixes will be visible to me and other users. However this can only happen if we have an official release / tag. Kindly advise, Shachar
Hi,
Yeah.. we are bit sloppy on releases :( however we invested a bit into more automation for testing and hopefully will be able to do releases more often. Next one is tentatively planned next month.
Thanks @sjanc , I will keep tracking,