From: Mat Martineau <mathewm@codeaurora.org>
To: linux-bluetooth@vger.kernel.org, gustavo@padovan.org,
marcel@holtmann.org, ulisses@profusion.mobi
Cc: pkrystad@codeaurora.org
Subject: [PATCH 06/25] Bluetooth: Consolidate common receive code for ERTM and streaming mode
Date: Thu, 17 May 2012 20:53:36 -0700 [thread overview]
Message-ID: <1337313235-26535-7-git-send-email-mathewm@codeaurora.org> (raw)
In-Reply-To: <1337313235-26535-1-git-send-email-mathewm@codeaurora.org>
Creates a new l2cap_data_rcv function that combines previous code from
l2cap_ertm_data_rcv and l2cap_data_channel. This reduces duplicate
code for streaming mode, and sets up a framework for the ERTM receive
state machine.
Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
---
net/bluetooth/l2cap_core.c | 126 ++++++++++++++++++++++----------------------
1 file changed, 62 insertions(+), 64 deletions(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index fd645ff..3f6bec9 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -789,9 +789,11 @@ static inline void __unpack_control(struct l2cap_chan *chan,
if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
__unpack_extended_control(get_unaligned_le32(skb->data),
&bt_cb(skb)->control);
+ skb_pull(skb, L2CAP_EXT_CTRL_SIZE);
} else {
__unpack_enhanced_control(get_unaligned_le16(skb->data),
&bt_cb(skb)->control);
+ skb_pull(skb, L2CAP_ENH_CTRL_SIZE);
}
}
@@ -4817,27 +4819,39 @@ static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u32 rx_cont
return 0;
}
-static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
+static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
+ struct sk_buff *skb, u8 event)
{
- u32 control;
- u16 req_seq;
- int len, next_tx_seq_offset, req_seq_offset;
+ /* Placeholder */
+ return -ENOTSUPP;
+}
+
+static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
+ struct sk_buff *skb)
+{
+ /* Placeholder */
+ return -ENOTSUPP;
+}
+
+static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
+{
+ struct l2cap_ctrl *control = &bt_cb(skb)->control;
+ u16 len;
+ u8 event;
__unpack_control(chan, skb);
- control = __get_control(chan, skb->data);
- skb_pull(skb, __ctrl_size(chan));
len = skb->len;
/*
* We can just drop the corrupted I-frame here.
* Receiver will miss it and start proper recovery
- * procedures and ask retransmission.
+ * procedures and ask for retransmission.
*/
if (l2cap_check_fcs(chan, skb))
goto drop;
- if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
+ if (!control->sframe && control->sar == L2CAP_SAR_START)
len -= L2CAP_SDULEN_SIZE;
if (chan->fcs == L2CAP_FCS_CRC16)
@@ -4848,34 +4862,57 @@ static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
goto drop;
}
- req_seq = __get_reqseq(chan, control);
+ if (!control->sframe) {
+ int err;
- req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
+ BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d",
+ control->sar, control->reqseq, control->final,
+ control->txseq);
- next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
- chan->expected_ack_seq);
-
- /* check for invalid req-seq */
- if (req_seq_offset > next_tx_seq_offset) {
- l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
- goto drop;
- }
-
- if (!__is_sframe(chan, control)) {
- if (len < 0) {
- l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+ /* Validate F-bit - F=0 always valid, F=1 only
+ * valid in TX WAIT_F
+ */
+ if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F)
goto drop;
+
+ if (chan->mode != L2CAP_MODE_STREAMING) {
+ event = L2CAP_EV_RECV_IFRAME;
+ err = l2cap_rx(chan, control, skb, event);
+ } else {
+ err = l2cap_stream_rx(chan, control, skb);
}
- l2cap_data_channel_iframe(chan, control, skb);
+ if (err)
+ l2cap_send_disconn_req(chan->conn, chan,
+ ECONNRESET);
} else {
+ const u8 rx_func_to_event[4] = {
+ L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ,
+ L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ
+ };
+
+ /* Only I-frames are expected in streaming mode */
+ if (chan->mode == L2CAP_MODE_STREAMING)
+ goto drop;
+
+ BT_DBG("sframe reqseq %d, final %d, poll %d, super %d",
+ control->reqseq, control->final, control->poll,
+ control->super);
+
if (len != 0) {
BT_ERR("%d", len);
l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
goto drop;
}
- l2cap_data_channel_sframe(chan, control, skb);
+ /* Validate F and P bits */
+ if (control->final && (control->poll ||
+ chan->tx_state != L2CAP_TX_STATE_WAIT_F))
+ goto drop;
+
+ event = rx_func_to_event[control->super];
+ if (l2cap_rx(chan, control, skb, event))
+ l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
}
return 0;
@@ -4888,9 +4925,6 @@ drop:
static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
{
struct l2cap_chan *chan;
- u32 control;
- u16 tx_seq;
- int len;
chan = l2cap_get_chan_by_scid(conn, cid);
if (!chan) {
@@ -4920,44 +4954,8 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
break;
case L2CAP_MODE_ERTM:
- l2cap_ertm_data_rcv(chan, skb);
-
- goto done;
-
case L2CAP_MODE_STREAMING:
- control = __get_control(chan, skb->data);
- skb_pull(skb, __ctrl_size(chan));
- len = skb->len;
-
- if (l2cap_check_fcs(chan, skb))
- goto drop;
-
- if (__is_sar_start(chan, control))
- len -= L2CAP_SDULEN_SIZE;
-
- if (chan->fcs == L2CAP_FCS_CRC16)
- len -= L2CAP_FCS_SIZE;
-
- if (len > chan->mps || len < 0 || __is_sframe(chan, control))
- goto drop;
-
- tx_seq = __get_txseq(chan, control);
-
- if (chan->expected_tx_seq != tx_seq) {
- /* Frame(s) missing - must discard partial SDU */
- kfree_skb(chan->sdu);
- chan->sdu = NULL;
- chan->sdu_last_frag = NULL;
- chan->sdu_len = 0;
-
- /* TODO: Notify userland of missing data */
- }
-
- chan->expected_tx_seq = __next_seq(chan, tx_seq);
-
- if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
- l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
-
+ l2cap_data_rcv(chan, skb);
goto done;
default:
--
1.7.10
--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
next prev parent reply other threads:[~2012-05-18 3:53 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-05-18 3:53 [PATCH 00/25] ERTM state machine changes, part 3 Mat Martineau
2012-05-18 3:53 ` [PATCH 01/25] Bluetooth: Change default state of ERTM disable flag Mat Martineau
2012-05-18 3:53 ` [PATCH 02/25] Bluetooth: Add a new L2CAP ERTM transmit state machine Mat Martineau
2012-05-18 19:54 ` Gustavo Padovan
2012-05-18 20:19 ` Mat Martineau
2012-05-18 3:53 ` [PATCH 03/25] Bluetooth: Refactor l2cap_streaming_send Mat Martineau
2012-05-18 3:53 ` [PATCH 04/25] Bluetooth: Refactor l2cap_ertm_send Mat Martineau
2012-05-18 3:53 ` [PATCH 05/25] Bluetooth: Refactor l2cap_send_sframe Mat Martineau
2012-05-18 3:53 ` Mat Martineau [this message]
2012-05-18 3:53 ` [PATCH 07/25] Bluetooth: Add streaming mode receive and incoming packet classifier Mat Martineau
2012-05-18 3:53 ` [PATCH 08/25] Bluetooth: Remove receive code that has been superceded Mat Martineau
2012-05-18 3:53 ` [PATCH 09/25] Bluetooth: Refactor l2cap_send_ack Mat Martineau
2012-05-18 3:53 ` [PATCH 10/25] Bluetooth: Use the transmit state machine for busy state changes Mat Martineau
2012-05-18 3:53 ` [PATCH 11/25] Bluetooth: Update l2cap_send_i_or_rr_or_rnr to fit the spec better Mat Martineau
2012-05-18 3:53 ` [PATCH 12/25] Bluetooth: Add the ERTM receive state machine Mat Martineau
2012-05-18 3:53 ` [PATCH 13/25] Bluetooth: Add implementation for retransmitting all unacked frames Mat Martineau
2012-05-18 3:53 ` [PATCH 14/25] Bluetooth: Send SREJ frames when packets go missing Mat Martineau
2012-05-18 3:53 ` [PATCH 15/25] Bluetooth: Reassemble all available data when retransmissions succeed Mat Martineau
2012-05-18 3:53 ` [PATCH 16/25] Bluetooth: Handle SREJ requests to resend unacked frames Mat Martineau
2012-05-18 3:53 ` [PATCH 17/25] Bluetooth: Handle incoming REJ frames Mat Martineau
2012-05-18 3:53 ` [PATCH 18/25] Bluetooth: Use new header structures in l2cap_send_rr_or_rnr Mat Martineau
2012-05-18 3:53 ` [PATCH 19/25] Bluetooth: Check rules when setting retransmit or monitor timers Mat Martineau
2012-05-18 3:53 ` [PATCH 20/25] Bluetooth: Use the ERTM transmit state machine from timeout handlers Mat Martineau
2012-05-18 3:53 ` [PATCH 21/25] Bluetooth: Simplify the ERTM ack timeout Mat Martineau
2012-05-18 3:53 ` [PATCH 22/25] Bluetooth: Remove unneccesary inline Mat Martineau
2012-05-18 3:53 ` [PATCH 23/25] Bluetooth: Set txwin values for streaming mode Mat Martineau
2012-05-18 3:53 ` [PATCH 24/25] Bluetooth: Remove unused ERTM control field macros Mat Martineau
2012-05-18 3:53 ` [PATCH 25/25] Bluetooth: Enable ERTM by default Mat Martineau
2012-05-18 20:56 ` Gustavo Padovan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1337313235-26535-7-git-send-email-mathewm@codeaurora.org \
--to=mathewm@codeaurora.org \
--cc=gustavo@padovan.org \
--cc=linux-bluetooth@vger.kernel.org \
--cc=marcel@holtmann.org \
--cc=pkrystad@codeaurora.org \
--cc=ulisses@profusion.mobi \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).