All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marcel Holtmann <marcel@holtmann.org>
To: "Gustavo F. Padovan" <gustavo@las.ic.unicamp.br>
Cc: linux-bluetooth@vger.kernel.org, gustavo@padovan.org
Subject: Re: [PATCH 4/4] Bluetooth: Add support for Retransmission and Monitor Timers
Date: Mon, 27 Jul 2009 12:08:44 +0200	[thread overview]
Message-ID: <1248689324.28545.194.camel@violet> (raw)
In-Reply-To: <1248675424-20977-5-git-send-email-gustavo@las.ic.unicamp.br>

Hi Gustavo,

> L2CAP uses rentransmission and monitor timers to inquiry the other side
> about unacked I-frames. After send each I-frame we (re)start the
> retransmission timer, if it expires, we start a monitor timer that send a
> S-frame with P bit set and wait for S-frame with F bit set.
> If monitor timer expires, it try again, at a maximum of
> L2CAP_DEFAULT_MAX_TX.
> 
> Signed-off-by: Gustavo F. Padovan <gustavo@las.ic.unicamp.br>
> ---
>  include/net/bluetooth/bluetooth.h |    1 +
>  include/net/bluetooth/l2cap.h     |   15 +++++-
>  net/bluetooth/l2cap.c             |   83 +++++++++++++++++++++++++++++++++++--
>  3 files changed, 92 insertions(+), 7 deletions(-)
> 
> diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
> index 65a5cf8..b8b9a84 100644
> --- a/include/net/bluetooth/bluetooth.h
> +++ b/include/net/bluetooth/bluetooth.h
> @@ -139,6 +139,7 @@ struct bt_skb_cb {
>  	__u8 pkt_type;
>  	__u8 incoming;
>  	__u8 tx_seq;
> +	__u8 retries;
>  };
>  #define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb))
>  
> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> index 653c313..02871df 100644
> --- a/include/net/bluetooth/l2cap.h
> +++ b/include/net/bluetooth/l2cap.h
> @@ -31,9 +31,9 @@
>  #define L2CAP_DEFAULT_FLUSH_TO		0xffff
>  #define L2CAP_DEFAULT_TX_WINDOW		63
>  #define L2CAP_DEFAULT_NUM_TO_ACK        (L2CAP_DEFAULT_TX_WINDOW/5)
> -#define L2CAP_DEFAULT_MAX_RECEIVE	1
> -#define L2CAP_DEFAULT_RETRANS_TO	300    /* 300 milliseconds */
> -#define L2CAP_DEFAULT_MONITOR_TO	1000   /* 1 second */
> +#define L2CAP_DEFAULT_MAX_TX		3
> +#define L2CAP_DEFAULT_RETRANS_TO	1000    /* 1 second */
> +#define L2CAP_DEFAULT_MONITOR_TO	12000   /* 12 seconds */
>  #define L2CAP_DEFAULT_MAX_PDU_SIZE	672
>  
>  #define L2CAP_CONN_TIMEOUT	(40000) /* 40 seconds */
> @@ -320,6 +320,7 @@ struct l2cap_pinfo {
>  	__u8		req_seq;
>  	__u8		expected_tx_seq;
>  	__u8		unacked_frames;
> +	__u8		retry_count;
>  	__u8		num_to_ack;
>  	__u16		sdu_len;
>  	__u16		partial_sdu_len;
> @@ -336,6 +337,8 @@ struct l2cap_pinfo {
>  
>  	__le16		sport;
>  
> +	struct timer_list	retrans_timer;
> +	struct timer_list	monitor_timer;
>  	struct sk_buff_head	tx_queue;
>  	struct l2cap_conn	*conn;
>  	struct sock		*next_c;
> @@ -355,6 +358,12 @@ struct l2cap_pinfo {
>  
>  #define L2CAP_CONN_SAR_SDU         0x01
>  #define L2CAP_CONN_UNDER_REJ       0x02
> +#define L2CAP_CONN_WAIT_ACK        0x04
> +
> +#define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \
> +		jiffies +  msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO));
> +#define __mod_monitor_timer() mod_timer(&l2cap_pi(sk)->monitor_timer, \
> +		jiffies + msecs_to_jiffies(L2CAP_DEFAULT_MONITOR_TO));
>  
>  static inline int l2cap_tx_window_full(struct sock *sk)
>  {
> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
> index 938d6db..bcfa9b9 100644
> --- a/net/bluetooth/l2cap.c
> +++ b/net/bluetooth/l2cap.c
> @@ -1179,6 +1179,37 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l
>  	return 0;
>  }
>  
> +static void l2cap_monitor_timeout(unsigned long arg)
> +{
> +	struct sock *sk = (void *) arg;
> +	u16 control;
> +
> +	if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
> +		l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk);
> +		return;
> +	}
> +
> +	l2cap_pi(sk)->retry_count++;
> +	__mod_monitor_timer();
> +
> +	control = L2CAP_CTRL_POLL;
> +	l2cap_send_sframe(l2cap_pi(sk), control);
> +}
> +
> +static void l2cap_retrans_timeout(unsigned long arg)
> +{
> +	struct sock *sk = (void *) arg;
> +	u16 control;
> +
> +	l2cap_pi(sk)->retry_count = 1;
> +	__mod_monitor_timer();
> +
> +	l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_ACK;
> +
> +	control = L2CAP_CTRL_POLL;
> +	l2cap_send_sframe(l2cap_pi(sk), control);
> +}
> +
>  static void l2cap_drop_acked_frames(struct sock *sk)
>  {
>  	struct sk_buff *skb;
> @@ -1193,6 +1224,9 @@ static void l2cap_drop_acked_frames(struct sock *sk)
>  		l2cap_pi(sk)->unacked_frames--;
>  	}
>  
> +	if (!l2cap_pi(sk)->unacked_frames)
> +		del_timer(&l2cap_pi(sk)->retrans_timer);
> +
>  	return;
>  }
>  
> @@ -1219,10 +1253,21 @@ static int l2cap_ertm_send(struct sock *sk)
>  	u16 *control;
>  	int err;
>  
> +	if (pi->conn_state & L2CAP_CONN_WAIT_ACK)
> +		return 0;
> +
>  	while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
>  		tx_seq = pi->next_tx_seq;
>  		tx_skb = skb_clone(skb, GFP_ATOMIC);
>  
> +		if (pi->remote_max_tx &&
> +				bt_cb(skb)->retries == pi->remote_max_tx) {
> +			l2cap_send_disconn_req(pi->conn, sk);
> +			break;
> +		}
> +
> +		bt_cb(skb)->retries++;
> +
>  		control = (u16 *)(skb->data + L2CAP_HDR_SIZE);
>  		*control |= cpu_to_le16(
>  				(pi->req_seq << L2CAP_CTRL_REQSEQ_SHIFT)
> @@ -1234,6 +1279,8 @@ static int l2cap_ertm_send(struct sock *sk)
>  			return err;
>  		}
>  
> +		__mod_retrans_timer();
> +
>  		L2CAP_SEQ_NUM_INC(pi->next_tx_seq);
>  		bt_cb(skb)->tx_seq = tx_seq;
>  
> @@ -1323,6 +1370,8 @@ static struct sk_buff *l2cap_create_pdu(struct sock *sk, struct msghdr *msg, siz
>  		kfree_skb(skb);
>  		return ERR_PTR(err);
>  	}
> +
> +	bt_cb(skb)->retries = 0;
>  	return skb;
>  }
>  
> @@ -2011,7 +2060,7 @@ done:
>  	case L2CAP_MODE_ERTM:
>  		rfc.mode            = L2CAP_MODE_ERTM;
>  		rfc.txwin_size      = L2CAP_DEFAULT_TX_WINDOW;
> -		rfc.max_transmit    = L2CAP_DEFAULT_MAX_RECEIVE;
> +		rfc.max_transmit    = L2CAP_DEFAULT_MAX_TX;
>  		rfc.retrans_timeout = 0;
>  		rfc.monitor_timeout = 0;
>  		rfc.max_pdu_size    = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
> @@ -2506,6 +2555,12 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
>  		l2cap_pi(sk)->next_tx_seq = 0;
>  		l2cap_pi(sk)->expected_ack_seq = 0;
>  		l2cap_pi(sk)->unacked_frames = 0;
> +
> +		setup_timer(&l2cap_pi(sk)->retrans_timer,
> +				l2cap_retrans_timeout, (unsigned long) sk);
> +		setup_timer(&l2cap_pi(sk)->monitor_timer,
> +				l2cap_monitor_timeout, (unsigned long) sk);
> +
>  		__skb_queue_head_init(TX_QUEUE(sk));
>  		l2cap_chan_ready(sk);
>  		goto unlock;
> @@ -2615,6 +2670,8 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
>  	sk->sk_shutdown = SHUTDOWN_MASK;
>  
>  	skb_queue_purge(TX_QUEUE(sk));
> +	del_timer(&l2cap_pi(sk)->retrans_timer);
> +	del_timer(&l2cap_pi(sk)->monitor_timer);
>  
>  	l2cap_chan_del(sk, ECONNRESET);
>  	bh_unlock_sock(sk);
> @@ -2639,6 +2696,8 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
>  		return 0;
>  
>  	skb_queue_purge(TX_QUEUE(sk));
> +	del_timer(&l2cap_pi(sk)->retrans_timer);
> +	del_timer(&l2cap_pi(sk)->monitor_timer);
>  
>  	l2cap_chan_del(sk, 0);
>  	bh_unlock_sock(sk);
> @@ -2944,9 +3003,25 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
>  
>  	switch (rx_control & L2CAP_CTRL_SUPERVISE) {
>  	case L2CAP_SUPER_RCV_READY:
> -		pi->expected_ack_seq = __get_reqseq(rx_control);
> -		l2cap_drop_acked_frames(sk);
> -		l2cap_ertm_send(sk);
> +		if (rx_control & L2CAP_CTRL_POLL) {
> +			u16 control = L2CAP_CTRL_FINAL;
> +			l2cap_send_sframe(l2cap_pi(sk), control);
> +		}
> +		else if (rx_control & L2CAP_CTRL_FINAL) {

Coding style is } else if.

> +			if (pi->conn_state & L2CAP_CONN_WAIT_ACK)
> +				break;
> +
> +			pi->conn_state &= !L2CAP_CONN_WAIT_ACK;
> +			del_timer(&pi->monitor_timer);
> +
> +			if (pi->unacked_frames > 0)
> +				__mod_retrans_timer();
> +		}
> +		else {

Same here.

> +			pi->expected_ack_seq = __get_reqseq(rx_control);
> +			l2cap_drop_acked_frames(sk);
> +			l2cap_ertm_send(sk);
> +		}
>  		break;
>  
>  	case L2CAP_SUPER_REJECT:

Regards

Marcel



  reply	other threads:[~2009-07-27 10:08 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-07-27  6:17 [PATCH 0/4] Bluetooth: Patch set for ERTM Gustavo F. Padovan
2009-07-27  6:17 ` [PATCH 1/4] Bluetooth: Add initial support for ERTM packets transfers Gustavo F. Padovan
2009-07-27  6:17   ` [PATCH 2/4] Bluetooth: Add support for Segmentation and Reassembly of SDUs Gustavo F. Padovan
2009-07-27  6:17     ` [PATCH 3/4] Bluetooth: Initial support for retransmission of packets with REJ frames Gustavo F. Padovan
2009-07-27  6:17       ` [PATCH 4/4] Bluetooth: Add support for Retransmission and Monitor Timers Gustavo F. Padovan
2009-07-27 10:08         ` Marcel Holtmann [this message]
2009-07-27 10:06       ` [PATCH 3/4] Bluetooth: Initial support for retransmission of packets with REJ frames Marcel Holtmann
2009-07-27 10:05     ` [PATCH 2/4] Bluetooth: Add support for Segmentation and Reassembly of SDUs Marcel Holtmann
2009-07-28 11:30       ` Gustavo F. Padovan
2009-07-27  9:59   ` [PATCH 1/4] Bluetooth: Add initial support for ERTM packets transfers Marcel Holtmann
2009-07-28 11:24     ` Gustavo F. Padovan
     [not found] <1249080824-6780-1-git-send-email-gustavo@las.ic.unicamp.br>
2009-07-31 22:53 ` [PATCH 2/4] Bluetooth: Add support for Segmentation and Reassembly of SDUs Gustavo F. Padovan
2009-07-31 22:53   ` [PATCH 3/4] Bluetooth: Initial support for retransmission of packets with REJ frames Gustavo F. Padovan
2009-07-31 22:53     ` [PATCH 4/4] Bluetooth: Add support for Retransmission and Monitor Timers Gustavo F. Padovan
  -- strict thread matches above, loose matches on Subject: below --
2009-07-31 22:57 [PATCH 1/4] Bluetooth: Add initial support for ERTM packets transfers Gustavo F. Padovan
2009-07-31 22:57 ` [PATCH 2/4] Bluetooth: Add support for Segmentation and Reassembly of SDUs Gustavo F. Padovan
2009-07-31 22:57   ` [PATCH 3/4] Bluetooth: Initial support for retransmission of packets with REJ frames Gustavo F. Padovan
2009-07-31 22:57     ` [PATCH 4/4] Bluetooth: Add support for Retransmission and Monitor Timers Gustavo F. 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=1248689324.28545.194.camel@violet \
    --to=marcel@holtmann.org \
    --cc=gustavo@las.ic.unicamp.br \
    --cc=gustavo@padovan.org \
    --cc=linux-bluetooth@vger.kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.