BlueZ: status update into the L2CAP layer

Since the last post here (it was a long time ago :-) too much work was done, but ERTM isn’t fully implemented yet. So, what did I do last month?
I’ll explain each of the features I implemented on the next paragraphs, but if this are boring for you just take a look at the roadmap at the end of this post.

First I did the support to send and receive I-frames (the data frames) and created the support to RR S-frames to acknowledge the received I-frames. It first worked with a txWindow=1 (which means only one packet can be send without receive acknowledge from the receiver side). The next step was support a txWindow up to 63 (the maximum value specified). To bring this support I have been using sk_buff lists from the net core implementation.

Support for Segmentation and Reassembly(SAR) of L2CAP SDUs: this feature allows upper applications to use a buffer greater than the L2CAP size packet. The buffer is break down in many packet on the transmitter side and then reassembled on the receiver side and pushed to the upper layer.

REJ frame exception: When a packet is lost we need to start the recoveries procedures. BlueZ won’t support raise of REJ exception (we support only raise of SREJ exception by now, spec says that we can choose one of them). But we need to support the receipt of a REJ-exception (i.e. receive a REJ frame). On the receipt of a REJ frame the L2CAP entity needs to stop the transmission and starts to retransmit the requested packets.  A REJ frame tells the ReqSeq(packet id sequence) and all packets up to ReqSeq – 1 shall be considered acknowledged, the others shall be retransmitted.

SREJ frame exception: BlueZ starts a SREJ exception when it detects lost packets. It sets its state to SREJ_SENT(It means that L2CAP entity is under recovery proccess) and sends a SREJ S-frame for each lost packets. The transmitter side shall resend the packets requested in the SREJ frames without stops transmission of new frames. SREJ exception saves retransmission of unneeded frames.

Retransmission And Monitor Timers: The Retransmission Timer shall be (re)started each time we send a I-frame. If it expires we send a RR-frame and start the Monitor Timer. The other side should response the RR frame immediately, if the the other side do not response and the Monitor Timer expires we resend the RR frame. A maximum value for the of Monitor Timer’s timeouts can be defined. If a L2CAP entity exceeds this value the channel shall be disconnected.

Busy condition on the remote side: If the remote side enters in a busy condition it will send a RNR frame. So, when the local side receives this frame it should mark the remote busy flag as true and stop the transmission of packets. It restarts the sending of packets only when the remote sides send a REJ, SREJ or RR frame. This says the remote busy condition was cleared.

Streaming mode: This mode of operation is useful to the Bluetooth Streaming Profiles such as A2DP and VDP(not yet implemented). It can take advantages of the Segmentation and Reassembly features.

FCS Option: It is a crc16 check for L2CAP packets. It is the default if both sides support it. If a L2CAP entity receives a packet with a broken crc16 it will drop. The receive procedure will miss it and start the recovery procedure.

Roadmap updated:

  1. Implement ERTM with txWindow=1 and retransmission disabled.
    1. send I-frames
    2. receive I-frames
    3. support RR S-frames to acknowledge I-frames received
    4. acknowledge I-frames
  2. Support txWindow up to 63
  3. Support segmentation and reassembly of L2CAP SDUs
  4. Enable retransmission
    1. support receipt REJ S-Frame
    2. support receipt SREJ S-Frame
    3. support raise of SREJ exception
  5. Support busy conditions exceptions
  6. Enable Retransmission Timer
  7. Enable Monitor Timer
  8. Implement Streaming Mode
  9. Implement FCS Option
  10. Support duplex channel
  11. Use SOCK_STREAM as default for Enhanced Retransmission and Streaming Modes.
  12. Test BlueZ against others stacks

What’s next?

Now I’m working the busy condition exception and the support for the ERTM duplex channel. Today, just one side can send data packets. Then I’ll put ERTM as default when SOCK_STREAM is selected. I expect finish these issues on the coming weeks. After, I’ll spend my time fixing the bugs I find trough the code.

ps: Sorry for my too not bad English ;-)

One Comment

Leave a Reply