as of r2352
I don't see any automatic fragmentation done on L2CAP, it would be nice to have.
I am expecting to send and receive 700-800 byte packets in my application, and it seems like my RN-42 only supports a local buffer of 310 bytes
I will implement this myself and submit a patch when I am done
I am unsure how to do this in a way that is friendly to developers. Because of the way that the transport data source works, I can't simply add a loop to send all the fragments. If I wait for "can send next packet", I also need to constantly check if the previous ACL has been sent. However, there is no way for me to access execute_once, or access the transport->data_source->process, so the wait-loop will freeze.
Another option is to queue up the fragment. The user can then check if a fragment is waiting on the next packet complete event, or even make it automatic
For receiving fragmented packets, I suggest adding "L2CAP_DATA_PACKET_START" and "L2CAP_DATA_PACKET_FRAGMENT" as additional packet types, so the user's packet handler can distinguish between them
Comment #1
Posted on Feb 6, 2014 by Swift Oxshort overview: BTstack does recombination up to the size of ACL packets. So even if your RN42 only has 310 bytes ACL buffered, BTstack will deliver a complete L2CAP packet up to whatever you've configured as packet size.
It doesn't do fragmentation though. If you use 1021 bytes as ACL packets, it allows for 1+ kB L2CAP packets which is above the default MTU of 672 (or so) and I haven't seen a service, maybe aside from BNEP, that requires larger MTUs.
Adding fragmentation wouldn't be too hard to do under the assumption that the data provided by the app needs to be available until a "l2cap data packet sent" event is received. Then, l2cap could fragment and send the fragments one by one with only a few extra bytes in the l2cap channel struct.
Fragmentation isn't that hard to implement. BTstack assumes that the data for an L2CAP is available until the packet is sent and a DAEMON_EVENT_PAKCET_SENT event was received (that might be not as clear. Or.. if your data stays within the size of a packet buffer, that buffer could also be sent in fragments without further changes to the expected behavior. (so this is clearly welcome.. although modern chipset have the max ACL buffers)
I can see the need for l2cap packet fragments but also are worried about the additional complexity and the fact that I don't see many cases where these fragments could be used without recombining them first.
Where do you need 700-800 bytes packets btw?
Comment #2
Posted on Feb 6, 2014 by Swift DogThe SDP packet used by the DualShock 4 is 717 bytes
I've made changes to your code that simply keeps track of another index in the acl_buffer array, such that the entire buffer is written once and only once, and the fragmentation is done automatically. The user is not allowed to overwrite the buffer until all fragments have been sent.
This only works in my single threaded system with only one or two tightly controlled connections. It also does not handle errors or disconnections yet.
Comment #3
Posted on Feb 6, 2014 by Swift OxWell. Large SDP records are fine. SDP was designed to work with less than the minimal MTU of 48 bytes as it allows the SDP server to respond "here's the first 50 of your answer, if you wan the rest, ask me again and tell me to use offset 50". BTstack implements that fully, so you don't need to do anything to server large SDP records.
Comment #4
Posted on Jan 15, 2015 by Swift OxBTstack supports packet fragmentation since Fall 2014 and it has been tested exensively with both sync and async transport, closing this.
Status: Fixed
Labels:
Type-Enhancement
Priority-Medium