*/
static bool batadv_tp_handle_out_of_order(struct batadv_tp_receiver *tp_vars,
const struct sk_buff *skb)
+ __must_hold(&tp_vars->common.unacked_lock)
{
const struct batadv_icmp_tp_packet *icmp;
struct batadv_tp_unacked *un, *new;
payload_len = skb->len - sizeof(struct batadv_unicast_packet);
new->len = payload_len;
- spin_lock_bh(&tp_vars->common.unacked_lock);
/* if the list is empty immediately attach this new object */
if (list_empty(&tp_vars->common.unacked_list)) {
list_add(&new->list, &tp_vars->common.unacked_list);
tp_vars->common.unacked_count++;
- goto out;
+ return true;
}
/* otherwise loop over the list and either drop the packet because this
tp_vars->common.unacked_count--;
}
-out:
- spin_unlock_bh(&tp_vars->common.unacked_lock);
-
return true;
}
* @tp_vars: the private data of the current TP meter session
*/
static void batadv_tp_ack_unordered(struct batadv_tp_receiver *tp_vars)
+ __must_hold(&tp_vars->common.unacked_lock)
{
struct batadv_tp_unacked *un, *safe;
u32 to_ack;
/* go through the unacked packet list and possibly ACK them as
* well
*/
- spin_lock_bh(&tp_vars->common.unacked_lock);
list_for_each_entry_safe(un, safe, &tp_vars->common.unacked_list, list) {
/* the list is ordered, therefore it is possible to stop as soon
* there is a gap between the last acked seqno and the seqno of
kfree(un);
tp_vars->common.unacked_count--;
}
- spin_unlock_bh(&tp_vars->common.unacked_lock);
}
/**
const struct batadv_icmp_tp_packet *icmp;
struct batadv_tp_receiver *tp_vars;
size_t packet_size;
+ u32 to_ack;
u32 seqno;
icmp = (struct batadv_icmp_tp_packet *)skb->data;
WRITE_ONCE(tp_vars->last_recv_time, jiffies);
}
+ spin_lock_bh(&tp_vars->common.unacked_lock);
+
/* if the packet is a duplicate, it may be the case that an ACK has been
* lost. Resend the ACK
*/
/* exit immediately (and do not send any ACK) if the packet has
* not been enqueued correctly
*/
- if (!batadv_tp_handle_out_of_order(tp_vars, skb))
+ if (!batadv_tp_handle_out_of_order(tp_vars, skb)) {
+ spin_unlock_bh(&tp_vars->common.unacked_lock);
goto out;
+ }
/* send a duplicate ACK */
goto send_ack;
batadv_tp_ack_unordered(tp_vars);
send_ack:
+ to_ack = tp_vars->last_recv;
+ spin_unlock_bh(&tp_vars->common.unacked_lock);
+
/* send the ACK. If the received packet was out of order, the ACK that
* is going to be sent is a duplicate (the sender will count them and
* possibly enter Fast Retransmit as soon as it has reached 3)
*/
- batadv_tp_send_ack(bat_priv, icmp->orig, tp_vars->last_recv,
+ batadv_tp_send_ack(bat_priv, icmp->orig, to_ack,
icmp->timestamp, icmp->session, icmp->uid);
out:
batadv_tp_receiver_put(tp_vars);