Re: [PATCHv1 3/5] Bluetooth: EWS: support extended seq numbers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Andrei,

* Emeltchenko Andrei <Andrei.Emeltchenko.news@xxxxxxxxx> [2011-09-07 17:05:12 +0300]:

> From: Andrei Emeltchenko <andrei.emeltchenko@xxxxxxxxx>
> 
> Adds support for extended sequence numbers found in
> extended control fields.
> 
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@xxxxxxxxx>
> ---
>  include/net/bluetooth/bluetooth.h |    2 +-
>  include/net/bluetooth/l2cap.h     |   17 ++++++++++
>  net/bluetooth/l2cap_core.c        |   63 +++++++++++++++++-------------------
>  net/bluetooth/l2cap_sock.c        |    1 +
>  4 files changed, 49 insertions(+), 34 deletions(-)
> 
> diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
> index e727555..fb1acb3 100644
> --- a/include/net/bluetooth/bluetooth.h
> +++ b/include/net/bluetooth/bluetooth.h
> @@ -158,7 +158,7 @@ struct bt_skb_cb {
>  	__u8 pkt_type;
>  	__u8 incoming;
>  	__u16 expect;
> -	__u8 tx_seq;
> +	__u16 tx_seq;
>  	__u8 retries;
>  	__u8 sar;
>  	unsigned short channel;
> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> index 5395984..27bd105 100644
> --- a/include/net/bluetooth/l2cap.h
> +++ b/include/net/bluetooth/l2cap.h
> @@ -384,6 +384,7 @@ struct l2cap_chan {
>  	__u8		fcs;
>  
>  	__u16		tx_win;
> +	__u16		tx_win_max;
>  	__u8		max_tx;
>  	__u16		retrans_timeout;
>  	__u16		monitor_timeout;
> @@ -550,6 +551,22 @@ enum {
>  		L2CAP_DEFAULT_ACK_TO);
>  #define __clear_ack_timer(c) l2cap_clear_timer(c, &c->ack_timer)
>  
> +static inline int __seq_offset(struct l2cap_chan *chan, __u16 seq1, __u16 seq2)
> +{
> +	int offset;
> +
> +	offset = (seq1 - seq2) % (chan->tx_win_max + 1);
> +	if (offset < 0)
> +		offset += (chan->tx_win_max + 1);
> +
> +	return offset;
> +}
> +
> +static inline __u16 __next_seq(struct l2cap_chan *chan, __u16 seq)
> +{
> +	return (seq + 1) % (chan->tx_win_max + 1);
> +}
> +
>  static inline int l2cap_tx_window_full(struct l2cap_chan *ch)
>  {
>  	int sub;
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index aae92df..cd61509 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -1296,7 +1296,7 @@ static void l2cap_streaming_send(struct l2cap_chan *chan)
>  
>  		l2cap_do_send(chan, skb);
>  
> -		chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
> +		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
>  	}
>  }
>  
> @@ -1390,7 +1390,8 @@ static int l2cap_ertm_send(struct l2cap_chan *chan)
>  		__set_retrans_timer(chan);
>  
>  		bt_cb(skb)->tx_seq = chan->next_tx_seq;
> -		chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
> +
> +		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
>  
>  		if (bt_cb(skb)->retries == 1)
>  			chan->unacked_frames++;
> @@ -1940,13 +1941,16 @@ static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
>  			__l2cap_ews_supported(chan)) {
>  		/* use extended control field */
>  		set_bit(FLAG_EXT_CTRL, &chan->flags);
> +		chan->tx_win_max = L2CAP_DEFAULT_MAX_EXT_WINDOW;
> +
>  		if (chan->tx_win > L2CAP_DEFAULT_MAX_EXT_WINDOW)
>  			chan->tx_win = L2CAP_DEFAULT_MAX_EXT_WINDOW;
>  	} else {
> +		clear_bit(FLAG_EXT_CTRL, &chan->flags);
> +		chan->tx_win_max = L2CAP_DEFAULT_MAX_TX_WINDOW;
> +
>  		if (chan->tx_win > L2CAP_DEFAULT_MAX_TX_WINDOW)
>  			chan->tx_win = L2CAP_DEFAULT_MAX_TX_WINDOW;
> -
> -		clear_bit(FLAG_EXT_CTRL, &chan->flags);
>  	}
>  }
>  
> @@ -2153,6 +2157,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
>  		case L2CAP_CONF_EWS:
>  			set_bit(FLAG_EXT_CTRL, &chan->flags);
>  			chan->remote_tx_win = val;
> +			chan->tx_win_max = L2CAP_DEFAULT_MAX_EXT_WINDOW;
>  			set_bit(CONF_EWS_RECV, &chan->conf_state);
>  			break;
>  
> @@ -3346,18 +3351,14 @@ static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb,
>  		return 0;
>  	}
>  
> -	tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
> -	if (tx_seq_offset < 0)
> -		tx_seq_offset += 64;
> +	tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
>  
>  	do {
>  		if (bt_cb(next_skb)->tx_seq == tx_seq)
>  			return -EINVAL;
>  
> -		next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
> -						chan->buffer_seq) % 64;
> -		if (next_tx_seq_offset < 0)
> -			next_tx_seq_offset += 64;
> +		next_tx_seq_offset = __seq_offset(chan,
> +				bt_cb(next_skb)->tx_seq, chan->buffer_seq);
>  
>  		if (next_tx_seq_offset > tx_seq_offset) {
>  			__skb_queue_before(&chan->srej_q, next_skb, skb);
> @@ -3547,9 +3548,8 @@ static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
>  			break;
>  		}
>  
> -		chan->buffer_seq_srej =
> -			(chan->buffer_seq_srej + 1) % 64;
> -		tx_seq = (tx_seq + 1) % 64;
> +		chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
> +		tx_seq = __next_seq(chan, tx_seq);
>  	}
>  }
>  
> @@ -3584,10 +3584,13 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
>  
>  		new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
>  		new->tx_seq = chan->expected_tx_seq;
> -		chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
> +
> +		chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
> +
>  		list_add_tail(&new->list, &chan->srej_l);
>  	}
> -	chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
> +
> +	chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
>  }
>  
>  static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
> @@ -3613,9 +3616,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_cont
>  	chan->expected_ack_seq = req_seq;
>  	l2cap_drop_acked_frames(chan);
>  
> -	tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
> -	if (tx_seq_offset < 0)
> -		tx_seq_offset += 64;
> +	tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
>  
>  	/* invalid tx_seq */
>  	if (tx_seq_offset >= chan->tx_win) {
> @@ -3663,10 +3664,8 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_cont
>  			l2cap_send_srejframe(chan, tx_seq);
>  		}
>  	} else {
> -		expected_tx_seq_offset =
> -			(chan->expected_tx_seq - chan->buffer_seq) % 64;
> -		if (expected_tx_seq_offset < 0)
> -			expected_tx_seq_offset += 64;
> +		expected_tx_seq_offset = __seq_offset(chan,
> +				chan->expected_tx_seq, chan->buffer_seq);
>  
>  		/* duplicated tx_seq */
>  		if (tx_seq_offset < expected_tx_seq_offset)
> @@ -3691,7 +3690,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_cont
>  	return 0;
>  
>  expected:
> -	chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
> +	chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
>  
>  	if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
>  		bt_cb(skb)->tx_seq = tx_seq;
> @@ -3701,7 +3700,8 @@ expected:
>  	}
>  
>  	err = l2cap_reassemble_sdu(chan, skb, rx_control);
> -	chan->buffer_seq = (chan->buffer_seq + 1) % 64;
> +	chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
> +
>  	if (err < 0) {
>  		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
>  		return err;
> @@ -3916,14 +3916,11 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
>  	}
>  
>  	req_seq = __get_reqseq(chan, control);
> -	req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
> -	if (req_seq_offset < 0)
> -		req_seq_offset += 64;
>  
> -	next_tx_seq_offset =
> -		(chan->next_tx_seq - chan->expected_ack_seq) % 64;
> -	if (next_tx_seq_offset < 0)
> -		next_tx_seq_offset += 64;
> +	req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
> +
> +	next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
> +			chan->expected_ack_seq);

wrong indentation.

>  
>  	/* check for invalid req-seq */
>  	if (req_seq_offset > next_tx_seq_offset) {
> @@ -4028,7 +4025,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
>  			/* TODO: Notify userland of missing data */
>  		}
>  
> -		chan->expected_tx_seq = (tx_seq + 1) % 64;
> +		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);
> diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
> index d6a4f63..bf343aa 100644
> --- a/net/bluetooth/l2cap_sock.c
> +++ b/net/bluetooth/l2cap_sock.c
> @@ -969,6 +969,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
>  
>  	/* Default config options */
>  	chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
> +	chan->tx_win_max = L2CAP_DEFAULT_MAX_TX_WINDOW;

If you set this on l2cap_txwin_setup() you don't need to set it here.

	Gustavo
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux