linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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 13/25] Bluetooth: Add implementation for retransmitting all unacked frames
Date: Thu, 17 May 2012 20:53:43 -0700	[thread overview]
Message-ID: <1337313235-26535-14-git-send-email-mathewm@codeaurora.org> (raw)
In-Reply-To: <1337313235-26535-1-git-send-email-mathewm@codeaurora.org>

This adds l2cap_ertm_resend to retransmit frames based on the sequence
numbers in chan->retrans_list.  If the retransmit limit is reached for
any individual frame is reached, the connection is dropped.  skbs that
are cloned already are copied to avoid modifying shared data (this is
uncommon).  To retransmit all frames, l2cap_retransmit_all now builds
a list of all unacked sequence numbers and then calls
l2cap_ertm_resend.

Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
---
 net/bluetooth/l2cap_core.c |  106 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 105 insertions(+), 1 deletion(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 86c4253..090d489 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1757,10 +1757,114 @@ static int l2cap_ertm_send(struct l2cap_chan *chan)
 	return sent;
 }
 
+static void l2cap_ertm_resend(struct l2cap_chan *chan)
+{
+	struct l2cap_ctrl control;
+	struct sk_buff *skb;
+	struct sk_buff *tx_skb;
+	u16 seq;
+
+	BT_DBG("chan %p", chan);
+
+	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
+		return;
+
+	while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) {
+		seq = l2cap_seq_list_pop(&chan->retrans_list);
+
+		skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq);
+		if (!skb) {
+			BT_DBG("Error: Can't retransmit seq %d, frame missing",
+				seq);
+			continue;
+		}
+
+		bt_cb(skb)->control.retries++;
+		control = bt_cb(skb)->control;
+
+		if (chan->max_tx != 0 &&
+		    bt_cb(skb)->control.retries > chan->max_tx) {
+			BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
+			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+			l2cap_seq_list_clear(&chan->retrans_list);
+			break;
+		}
+
+		control.reqseq = chan->buffer_seq;
+		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
+			control.final = 1;
+		else
+			control.final = 0;
+
+		if (skb_cloned(skb)) {
+			/* Cloned sk_buffs are read-only, so we need a
+			 * writeable copy
+			 */
+			tx_skb = skb_copy(skb, GFP_ATOMIC);
+		} else {
+			tx_skb = skb_clone(skb, GFP_ATOMIC);
+		}
+
+		if (!tx_skb) {
+			l2cap_seq_list_clear(&chan->retrans_list);
+			break;
+		}
+
+		/* Update skb contents */
+		if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
+			put_unaligned_le32(__pack_extended_control(&control),
+					   tx_skb->data + L2CAP_HDR_SIZE);
+		} else {
+			put_unaligned_le16(__pack_enhanced_control(&control),
+					   tx_skb->data + L2CAP_HDR_SIZE);
+		}
+
+		if (chan->fcs == L2CAP_FCS_CRC16) {
+			u16 fcs = crc16(0, (u8 *) tx_skb->data, tx_skb->len);
+			put_unaligned_le16(fcs, skb_put(tx_skb,
+							L2CAP_FCS_SIZE));
+		}
+
+		l2cap_do_send(chan, tx_skb);
+
+		BT_DBG("Resent txseq %d", control.txseq);
+
+		chan->last_acked_seq = chan->buffer_seq;
+	}
+}
+
 static void l2cap_retransmit_all(struct l2cap_chan *chan,
 				 struct l2cap_ctrl *control)
 {
-	/* Placeholder */
+	struct sk_buff *skb;
+
+	BT_DBG("chan %p, control %p", chan, control);
+
+	if (control->poll)
+		set_bit(CONN_SEND_FBIT, &chan->conn_state);
+
+	l2cap_seq_list_clear(&chan->retrans_list);
+
+	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
+		return;
+
+	if (chan->unacked_frames) {
+		skb_queue_walk(&chan->tx_q, skb) {
+			if (bt_cb(skb)->control.txseq == control->reqseq ||
+				skb == chan->tx_send_head)
+				break;
+		}
+
+		skb_queue_walk_from(&chan->tx_q, skb) {
+			if (skb == chan->tx_send_head)
+				break;
+
+			l2cap_seq_list_append(&chan->retrans_list,
+					      bt_cb(skb)->control.txseq);
+		}
+
+		l2cap_ertm_resend(chan);
+	}
 }
 
 static void l2cap_send_ack(struct l2cap_chan *chan)
-- 
1.7.10

--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

  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 ` [PATCH 06/25] Bluetooth: Consolidate common receive code for ERTM and streaming mode Mat Martineau
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 ` Mat Martineau [this message]
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-14-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).