[Bluez-devel] L2CAP Flow Control 5th stage

From: Martin Röhricht <hidden>
Date: 2006-07-21 14:54:30

Hello together,

this is an update on my attempt to implement L2CAP flow control for the
BlueZ stack. I attached the current patch from my snapshot. Be aware
that this patch is far from being complete. Instead I'd like to present
some results of my coding in the past. So the current patch compiles and
should still work with devices that do not want to use flow control. But
this code is not meant to be tested in binary mode ;-)

I already implemented the whole configuration procedure in the past. I
consider this part as being done in terms of functionality. This time
I'd like to emphasize more on the real flow control procedural work that
I currently work on. For the beginning I started working on the
reception of I- and S-Frames.

Whenever we get a frame from the layer beneath us, l2cap_recv_acldata()
is called. Within this function the protocol specific headers of the ACL
layer is extracted, error checks are performed and finally the ACL
information payload, which consists of a plain L2CAP frame, is being
passed to l2cap_recv_frame() in form of a socket buffer. 
l2cap_recv_frame() decides whether we are using a signalling channel, a
connectionless channel or a data channel. We are only concerned for the
latter one as flow control mode can only be used in therein.

(1) l2cap_data_channel()
I did not change any of the old functionality that is used for B-Frames.
But when a link is configured to be used in flow control mode I-Frames
and S-Frames are used instead of B-Frames, so I added some functionality
there. First of all, we check if the frame that is being sent is valid.
This check is performed in l2cap_invalid_frame_detection(). If this
check fails the frame is dropped. The next check is based on the frame's
type itself -- the last bit shows whether we are getting an I-Frame or a
S-Frame. In both cases we are checking the ReqSeq value and in case of
an I-Frame also the TxSeq value. Further more we need to make sure that
segmented I-Frames that form one SDU are reassembled and passed to the
upper layer. This is done in l2cap_reassembly().

(2) l2cap_invalid_frame_detection()
This is an easy to follow function. The first check ensures if the
length field within the L2CAP header is true -- so it must be the same
as the length of the socket buffer (the whole frame) excluding the l2cap
header. All the other checks are the ones mentioned in the check list of
the specification on page 40 (section 3.3.6 Invalid frame detection).
Worth being mentioned is only that check number six is not implemented
yet within this function: »I-Frame with SAR bits that do not correspond
to a normal sequence of either unsegmented or start, continuation, end
for the given CID« -- this check is done later within the reassembly
function. We are not making use of any error reporting technique yet.
But interesting is the use of the crc16() function of the crc16 module.
I assume this should do the trick as the generator polynomial is the
same. Unfortunately this would require to have the crc16 module loaded
to use BlueZ in the future.

(3) l2cap_process_txseq()
The TxSeq is extracted and checked for validity. In case a frame gets
lost in L2CAP flow control mode, the specification forces us not to make
use of any retransmission nor can we use a special buffer for
out-of-sequence frames. Instead those frames considered lost are just
ignored and the ExpectedTxSeq value is based upon the last I-Frame
received. Duplicated I-Frames are dropped as well es invalid frames.
Unfortunately the specification mentions that the ReqSeq value shall be
processed according to Section 8.5.4 in case of a duplicated I-Frame,
but I didn't figure out what that means practically in this case ...

(4) l2cap_process_reqseq()
This function is alike the above one. First there is a "magical
byte-check" which only checks whether we have either an I-Frame (last
bit is a 0) or we are getting an S-Frame where the last four bits must
be of the form 0001. The next check is concerned about the ReqSeq
sequence error. If something went wrong the specification indicates:
»The L2CAP entity shall close the channel as a consequence of an ReqSeq
Sequence error.« -- so do we.
In case everything went fine, one of the two timers will be started --
but the timer stuff hasn't been finished yet.

(5) l2cap_reassembly()
This function is currently the most interesting one. Whenever a SDU is
segmented into more than one I-Frames we will reassemble those segments
here. In case of an unsegmented I-Frame the already complete SDU is
passed to the application via sock_queue_rcv_skb() -- I assume this is
the function to be used for this action ... is that right?
In case of segmentation we have to perform some more logic and to be a
bit careful. The logic means we are going to allocate a new socket
buffer which we provide per socket (l2cap_pi(sk)->sdu) with the length
that is provided within the SDU length field of the first segmented
I-Frame. We memcpy the current frame into this new skb data field. In
case we receive a frame with the continuation or end flags set, we make
two error checks. If both went well we memcpy this frame into the sdu
skb. Just in case the SAR_END flag is set and(!) the sdu length matches
the length of all the frames that were put into this sdu, we are passing
the SDU to the above layer.
It is important to make sure this technique works also when one or more
frames get lost. Therefore I provided the last mentioned mechanism and
to avoid unnecessary memory consumption I made sure to free the
currently allocated sdu memory block when we receive a new frame with
SAR_START flags set. So I think this should already work for the cases
that the start frame is lost, onw or more of the continuation frames are
lost or even if the end frame is lost. But maybe somebody wants to dive
into this error checking once more?!

That's basically it. I didn't do anything regarding timer control
mechanism nor did I investigate the send mechanism closer. But to give
some interested developers the chance to take a look into my code, make
some proposals or find bugs, I post this message here.

Martin

Attachments

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help