aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorGustavo F. Padovan <gustavo@las.ic.unicamp.br>2009-08-20 21:26:03 -0400
committerMarcel Holtmann <marcel@holtmann.org>2009-08-22 18:01:25 -0400
commit8f17154f1f70fcc6faa31ac82164fcf7f0599f38 (patch)
treef210dae590f600720b974d367082c368d03eac86 /net/bluetooth
parentfcc203c30d72dde82692f6b761a80e5ca5fdd8fa (diff)
Bluetooth: Add support for L2CAP SREJ exception
When L2CAP loses an I-frame we send a SREJ frame to the transmitter side requesting the lost packet. This patch implement all Recv I-frame events on SREJ_SENT state table except the ones that deal with SendRej (the REJ exception at receiver side is yet not implemented). Signed-off-by: Gustavo F. Padovan <gustavo@las.ic.unicamp.br> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/l2cap.c220
1 files changed, 196 insertions, 24 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 4c319003c290..70aff921db8c 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1292,6 +1292,50 @@ static int l2cap_streaming_send(struct sock *sk)
1292 return 0; 1292 return 0;
1293} 1293}
1294 1294
1295static int l2cap_retransmit_frame(struct sock *sk, u8 tx_seq)
1296{
1297 struct l2cap_pinfo *pi = l2cap_pi(sk);
1298 struct sk_buff *skb, *tx_skb;
1299 u16 control, fcs;
1300 int err;
1301
1302 skb = skb_peek(TX_QUEUE(sk));
1303 do {
1304 if (bt_cb(skb)->tx_seq != tx_seq) {
1305 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1306 break;
1307 skb = skb_queue_next(TX_QUEUE(sk), skb);
1308 continue;
1309 }
1310
1311 if (pi->remote_max_tx &&
1312 bt_cb(skb)->retries == pi->remote_max_tx) {
1313 l2cap_send_disconn_req(pi->conn, sk);
1314 break;
1315 }
1316
1317 tx_skb = skb_clone(skb, GFP_ATOMIC);
1318 bt_cb(skb)->retries++;
1319 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
1320 control |= (pi->req_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1321 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1322 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1323
1324 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16) {
1325 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1326 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1327 }
1328
1329 err = l2cap_do_send(sk, tx_skb);
1330 if (err < 0) {
1331 l2cap_send_disconn_req(pi->conn, sk);
1332 return err;
1333 }
1334 break;
1335 } while(1);
1336 return 0;
1337}
1338
1295static int l2cap_ertm_send(struct sock *sk) 1339static int l2cap_ertm_send(struct sock *sk)
1296{ 1340{
1297 struct sk_buff *skb, *tx_skb; 1341 struct sk_buff *skb, *tx_skb;
@@ -2705,6 +2749,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
2705 l2cap_monitor_timeout, (unsigned long) sk); 2749 l2cap_monitor_timeout, (unsigned long) sk);
2706 2750
2707 __skb_queue_head_init(TX_QUEUE(sk)); 2751 __skb_queue_head_init(TX_QUEUE(sk));
2752 __skb_queue_head_init(SREJ_QUEUE(sk));
2708 l2cap_chan_ready(sk); 2753 l2cap_chan_ready(sk);
2709 goto unlock; 2754 goto unlock;
2710 } 2755 }
@@ -2784,8 +2829,10 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
2784 2829
2785 sk->sk_state = BT_CONNECTED; 2830 sk->sk_state = BT_CONNECTED;
2786 l2cap_pi(sk)->expected_tx_seq = 0; 2831 l2cap_pi(sk)->expected_tx_seq = 0;
2832 l2cap_pi(sk)->buffer_seq = 0;
2787 l2cap_pi(sk)->num_to_ack = 0; 2833 l2cap_pi(sk)->num_to_ack = 0;
2788 __skb_queue_head_init(TX_QUEUE(sk)); 2834 __skb_queue_head_init(TX_QUEUE(sk));
2835 __skb_queue_head_init(SREJ_QUEUE(sk));
2789 l2cap_chan_ready(sk); 2836 l2cap_chan_ready(sk);
2790 } 2837 }
2791 2838
@@ -2817,6 +2864,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
2817 sk->sk_shutdown = SHUTDOWN_MASK; 2864 sk->sk_shutdown = SHUTDOWN_MASK;
2818 2865
2819 skb_queue_purge(TX_QUEUE(sk)); 2866 skb_queue_purge(TX_QUEUE(sk));
2867 skb_queue_purge(SREJ_QUEUE(sk));
2820 del_timer(&l2cap_pi(sk)->retrans_timer); 2868 del_timer(&l2cap_pi(sk)->retrans_timer);
2821 del_timer(&l2cap_pi(sk)->monitor_timer); 2869 del_timer(&l2cap_pi(sk)->monitor_timer);
2822 2870
@@ -2843,6 +2891,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
2843 return 0; 2891 return 0;
2844 2892
2845 skb_queue_purge(TX_QUEUE(sk)); 2893 skb_queue_purge(TX_QUEUE(sk));
2894 skb_queue_purge(SREJ_QUEUE(sk));
2846 del_timer(&l2cap_pi(sk)->retrans_timer); 2895 del_timer(&l2cap_pi(sk)->retrans_timer);
2847 del_timer(&l2cap_pi(sk)->monitor_timer); 2896 del_timer(&l2cap_pi(sk)->monitor_timer);
2848 2897
@@ -3038,6 +3087,33 @@ static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
3038 return 0; 3087 return 0;
3039} 3088}
3040 3089
3090static void l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar)
3091{
3092 struct sk_buff *next_skb;
3093
3094 bt_cb(skb)->tx_seq = tx_seq;
3095 bt_cb(skb)->sar = sar;
3096
3097 next_skb = skb_peek(SREJ_QUEUE(sk));
3098 if (!next_skb) {
3099 __skb_queue_tail(SREJ_QUEUE(sk), skb);
3100 return;
3101 }
3102
3103 do {
3104 if (bt_cb(next_skb)->tx_seq > tx_seq) {
3105 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
3106 return;
3107 }
3108
3109 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
3110 break;
3111
3112 } while((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
3113
3114 __skb_queue_tail(SREJ_QUEUE(sk), skb);
3115}
3116
3041static int l2cap_sar_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control) 3117static int l2cap_sar_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
3042{ 3118{
3043 struct l2cap_pinfo *pi = l2cap_pi(sk); 3119 struct l2cap_pinfo *pi = l2cap_pi(sk);
@@ -3118,50 +3194,143 @@ static int l2cap_sar_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 co
3118 return err; 3194 return err;
3119} 3195}
3120 3196
3197static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
3198{
3199 struct sk_buff *skb;
3200 u16 control = 0;
3201
3202 while((skb = skb_peek(SREJ_QUEUE(sk)))) {
3203 if (bt_cb(skb)->tx_seq != tx_seq)
3204 break;
3205
3206 skb = skb_dequeue(SREJ_QUEUE(sk));
3207 control |= bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
3208 l2cap_sar_reassembly_sdu(sk, skb, control);
3209 l2cap_pi(sk)->buffer_seq_srej =
3210 (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
3211 tx_seq++;
3212 }
3213}
3214
3215static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
3216{
3217 struct l2cap_pinfo *pi = l2cap_pi(sk);
3218 struct srej_list *l, *tmp;
3219 u16 control;
3220
3221 list_for_each_entry_safe(l,tmp, SREJ_LIST(sk), list) {
3222 if (l->tx_seq == tx_seq) {
3223 list_del(&l->list);
3224 kfree(l);
3225 return;
3226 }
3227 control = L2CAP_SUPER_SELECT_REJECT;
3228 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3229 l2cap_send_sframe(pi, control);
3230 list_del(&l->list);
3231 list_add_tail(&l->list, SREJ_LIST(sk));
3232 }
3233}
3234
3235static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
3236{
3237 struct l2cap_pinfo *pi = l2cap_pi(sk);
3238 struct srej_list *new;
3239 u16 control;
3240
3241 while (tx_seq != pi->expected_tx_seq) {
3242 control = L2CAP_SUPER_SELECT_REJECT;
3243 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3244 l2cap_send_sframe(pi, control);
3245
3246 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
3247 new->tx_seq = pi->expected_tx_seq++;
3248 list_add_tail(&new->list, SREJ_LIST(sk));
3249 }
3250 pi->expected_tx_seq++;
3251}
3252
3121static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb) 3253static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3122{ 3254{
3123 struct l2cap_pinfo *pi = l2cap_pi(sk); 3255 struct l2cap_pinfo *pi = l2cap_pi(sk);
3124 u8 tx_seq = __get_txseq(rx_control); 3256 u8 tx_seq = __get_txseq(rx_control);
3125 u16 tx_control = 0; 3257 u16 tx_control = 0;
3258 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
3126 int err = 0; 3259 int err = 0;
3127 3260
3128 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len); 3261 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
3129 3262
3130 if (tx_seq == pi->expected_tx_seq) { 3263 if (tx_seq == pi->expected_tx_seq)
3131 if (pi->conn_state & L2CAP_CONN_UNDER_REJ) 3264 goto expected;
3132 pi->conn_state &= ~L2CAP_CONN_UNDER_REJ;
3133 3265
3134 err = l2cap_sar_reassembly_sdu(sk, skb, rx_control); 3266 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3135 if (err < 0) 3267 struct srej_list *first;
3136 return err;
3137 3268
3138 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; 3269 first = list_first_entry(SREJ_LIST(sk),
3139 pi->num_to_ack = (pi->num_to_ack + 1) % L2CAP_DEFAULT_NUM_TO_ACK; 3270 struct srej_list, list);
3140 if (pi->num_to_ack == L2CAP_DEFAULT_NUM_TO_ACK - 1) { 3271 if (tx_seq == first->tx_seq) {
3141 tx_control |= L2CAP_SUPER_RCV_READY; 3272 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3142 tx_control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; 3273 l2cap_check_srej_gap(sk, tx_seq);
3143 goto send; 3274
3275 list_del(&first->list);
3276 kfree(first);
3277
3278 if (list_empty(SREJ_LIST(sk))) {
3279 pi->buffer_seq = pi->buffer_seq_srej;
3280 pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3281 }
3282 } else {
3283 struct srej_list *l;
3284 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3285
3286 list_for_each_entry(l, SREJ_LIST(sk), list) {
3287 if (l->tx_seq == tx_seq) {
3288 l2cap_resend_srejframe(sk, tx_seq);
3289 return 0;
3290 }
3291 }
3292 l2cap_send_srejframe(sk, tx_seq);
3144 } 3293 }
3145 } else { 3294 } else {
3146 /* Unexpected txSeq. Send a REJ S-frame */ 3295 pi->conn_state |= L2CAP_CONN_SREJ_SENT;
3147 kfree_skb(skb);
3148 if (!(pi->conn_state & L2CAP_CONN_UNDER_REJ)) {
3149 tx_control |= L2CAP_SUPER_REJECT;
3150 tx_control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3151 pi->conn_state |= L2CAP_CONN_UNDER_REJ;
3152 3296
3153 goto send; 3297 INIT_LIST_HEAD(SREJ_LIST(sk));
3154 } 3298 pi->buffer_seq_srej = pi->buffer_seq;
3299
3300 __skb_queue_head_init(SREJ_QUEUE(sk));
3301 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3302
3303 l2cap_send_srejframe(sk, tx_seq);
3155 } 3304 }
3156 return 0; 3305 return 0;
3157 3306
3158send: 3307expected:
3159 return l2cap_send_sframe(pi, tx_control); 3308 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3309
3310 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3311 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3312 return 0;
3313 }
3314
3315 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
3316
3317 err = l2cap_sar_reassembly_sdu(sk, skb, rx_control);
3318 if (err < 0)
3319 return err;
3320
3321 pi->num_to_ack = (pi->num_to_ack + 1) % L2CAP_DEFAULT_NUM_TO_ACK;
3322 if (pi->num_to_ack == L2CAP_DEFAULT_NUM_TO_ACK - 1) {
3323 tx_control |= L2CAP_SUPER_RCV_READY;
3324 tx_control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3325 l2cap_send_sframe(pi, tx_control);
3326 }
3327 return 0;
3160} 3328}
3161 3329
3162static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb) 3330static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3163{ 3331{
3164 struct l2cap_pinfo *pi = l2cap_pi(sk); 3332 struct l2cap_pinfo *pi = l2cap_pi(sk);
3333 u8 tx_seq = __get_reqseq(rx_control);
3165 3334
3166 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len); 3335 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
3167 3336
@@ -3181,7 +3350,7 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
3181 if (pi->unacked_frames > 0) 3350 if (pi->unacked_frames > 0)
3182 __mod_retrans_timer(); 3351 __mod_retrans_timer();
3183 } else { 3352 } else {
3184 pi->expected_ack_seq = __get_reqseq(rx_control); 3353 pi->expected_ack_seq = tx_seq;
3185 l2cap_drop_acked_frames(sk); 3354 l2cap_drop_acked_frames(sk);
3186 if (pi->unacked_frames > 0) 3355 if (pi->unacked_frames > 0)
3187 __mod_retrans_timer(); 3356 __mod_retrans_timer();
@@ -3200,8 +3369,11 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
3200 3369
3201 break; 3370 break;
3202 3371
3203 case L2CAP_SUPER_RCV_NOT_READY:
3204 case L2CAP_SUPER_SELECT_REJECT: 3372 case L2CAP_SUPER_SELECT_REJECT:
3373 l2cap_retransmit_frame(sk, tx_seq);
3374 break;
3375
3376 case L2CAP_SUPER_RCV_NOT_READY:
3205 break; 3377 break;
3206 } 3378 }
3207 3379