Bluetooth: Implement RejActioned flag
RejActioned is used to prevent retransmission when a entity is on the WAIT_F state, i.e., waiting for a frame with F-bit set due local busy condition or a expired retransmission timer. (When these two events raise they send a frame with the Poll bit set and enters in the WAIT_F state to wait for a frame with the Final bit set.) The local entity doesn't send I-frames(the data frames) until the receipt of a frame with F-bit set. When that happens it also set RejActioned to false. RejActioned is a mandatory feature of ERTM spec. Signed-off-by: Gustavo F. Padovan <gustavo@las.ic.unicamp.br> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
parent
9f121a5a80
commit
4ec10d9720
@ -374,6 +374,7 @@ struct l2cap_pinfo {
|
||||
#define L2CAP_CONN_SEND_PBIT 0x10
|
||||
#define L2CAP_CONN_REMOTE_BUSY 0x20
|
||||
#define L2CAP_CONN_LOCAL_BUSY 0x40
|
||||
#define L2CAP_CONN_REJ_ACT 0x80
|
||||
|
||||
#define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \
|
||||
jiffies + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO));
|
||||
|
@ -3362,6 +3362,16 @@ expected:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rx_control & L2CAP_CTRL_FINAL) {
|
||||
if (pi->conn_state & L2CAP_CONN_REJ_ACT)
|
||||
pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
|
||||
else {
|
||||
sk->sk_send_head = TX_QUEUE(sk)->next;
|
||||
pi->next_tx_seq = pi->expected_ack_seq;
|
||||
l2cap_ertm_send(sk);
|
||||
}
|
||||
}
|
||||
|
||||
pi->buffer_seq = (pi->buffer_seq + 1) % 64;
|
||||
|
||||
err = l2cap_sar_reassembly_sdu(sk, skb, rx_control);
|
||||
@ -3398,6 +3408,14 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
|
||||
pi->expected_ack_seq = tx_seq;
|
||||
l2cap_drop_acked_frames(sk);
|
||||
|
||||
if (pi->conn_state & L2CAP_CONN_REJ_ACT)
|
||||
pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
|
||||
else {
|
||||
sk->sk_send_head = TX_QUEUE(sk)->next;
|
||||
pi->next_tx_seq = pi->expected_ack_seq;
|
||||
l2cap_ertm_send(sk);
|
||||
}
|
||||
|
||||
if (!(pi->conn_state & L2CAP_CONN_WAIT_F))
|
||||
break;
|
||||
|
||||
@ -3425,10 +3443,24 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
|
||||
pi->expected_ack_seq = __get_reqseq(rx_control);
|
||||
l2cap_drop_acked_frames(sk);
|
||||
|
||||
sk->sk_send_head = TX_QUEUE(sk)->next;
|
||||
pi->next_tx_seq = pi->expected_ack_seq;
|
||||
if (rx_control & L2CAP_CTRL_FINAL) {
|
||||
if (pi->conn_state & L2CAP_CONN_REJ_ACT)
|
||||
pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
|
||||
else {
|
||||
sk->sk_send_head = TX_QUEUE(sk)->next;
|
||||
pi->next_tx_seq = pi->expected_ack_seq;
|
||||
l2cap_ertm_send(sk);
|
||||
}
|
||||
} else {
|
||||
sk->sk_send_head = TX_QUEUE(sk)->next;
|
||||
pi->next_tx_seq = pi->expected_ack_seq;
|
||||
l2cap_ertm_send(sk);
|
||||
|
||||
l2cap_ertm_send(sk);
|
||||
if (pi->conn_state & L2CAP_CONN_WAIT_F) {
|
||||
pi->srej_save_reqseq = tx_seq;
|
||||
pi->conn_state |= L2CAP_CONN_REJ_ACT;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user