CoreBluetooth L2CAP Channel MTU Limit

I have been working with the newly added ability to open an L2CAP channel with my peripheral (for over-the-air updates). It seems to work well up to a 2KB MTU. Up to 2KB, my peripheral gets the data in one chunk and processing continues as expected. If I increase the MTU of the channel on the peripheral side to something above 2KB, the packets become fragmented. What is interesting is that when I write to the L2CAP channel's output stream on the iOS Central side, it states that the correct amount of bytes were written, even above 2K MTU sizes. Moreover, I sniffed the BLE airwaves and found that the channel was successfully opened and the MTU is correct. Everything so far is pointing to CoreBluetooth fragmenting the packets.


Is there is an MTU limit on L2CAP channels in CoreBluetooth? I have been doing all of my testing on an iPhone 7 Plus running iOS 11 beta 2.

The peripheral should request the largest MTU it can support, but in the end the Apple devices will determine the optimal MTU to use based on the configuration at the time.


You should check the maximumWriteValueLength() function for your peripheral at the time, and send the according amount of data for optimal performance.

Thanks for the reply. I get back 512 for the value that you mentioned, however isn't that for ATT writes? I am going through an L2CAP CoE channel. How does that explain being able to use values like 1500 as the MTU? Everything works up to 2048. After that, the fragments start. I thought the theoretical limit of an L2CAP COE channel was 65536?

What is the ATT_MTU value you are getting back from iOS when you ask for larger than 2KB?


If the returned ATT_MTU after the MTU exchange is less than what your peripheral asks for, that is the MTU which will be used, and would explain the issue.


Also, when you say fragmentation, do not confuse MTU with the radio packet size. Regardless of the MTU, radio packets are the same old size (larger if you are using EDL)


If the returned MTU is larger than 2KB, but you are seeing actual data fragmentation (not just separate radio packets) when you send data that should fit in the MTU (minus the L2CAP header), please file a bug report on this.

Thanks for the reply. I think there is some confusion with what I am experiencing.


On my peripheral I see the L2CAP channel MTU get negotiated to 512 (from the iPhone 7 Plus). Since this is an L2CAP "side" channel, on the peripheral side, I force the MTU to say 1500 for example. With my BLE sniffer, I see that the MTU of the L2CAP channel gets set to 1500. On the iPhone Central side I use the L2CAP channel's stream object to send 1500 bytes of data at a time. On the peripheral side, I have a callback that is invoked when I get L2CAP data and I successfully get the 1500 bytes. I have tried everything up to 2048, however when I force an MTU over 2048, I start getting multiple packets in my L2CAP callback. I am forcing the higher MTU because in theory L2CAP vendor-defined channels should support a much higher MTU than 512. There isn't much benefit to using it otherwise given that I am getting an ATT MTU of 247 for an iPhone 7.


From my understanding, and based on your What's New in CoreBluetooth video from WWDC 2017, I should be able to take advantage of the L2CAP channel to get much higher data transfer rates and increased packet sizes.

Hi,Can you tell me which chip you use as peripheral ? Such as Nordic, TI or Dialog

6 years later, CoreBluetooth still does not provide a proper API for setting the connection parameters and the L2CAP COC parameters when being a central. I'm sorry, but I don't buy that the SDK chooses the "best" parameters for the current situation.

When the Apple device is the peripheral, I can get up to 100KB/sec, when the Apple device is the central, I get up to 36KB/sec, which is sub-par.

FWIW, I recently managed to get a 15ms connection interval negotiated (initiated by the peripheral), so 60KB/sec is now possible with an Apple device as the central.

CoreBluetooth L2CAP Channel MTU Limit
 
 
Q