Skip to content

Commit af5a069

Browse files
ecsvgregkh
authored andcommitted
batman-adv: tp_meter: handle overlapping packets
commit cbde75c upstream. If the size of the packets would change during the transmission, it could happen that some retries of packets are overlapping. In this case, precise comparisons of sequence numbers by the receiver would be wrong. It is then necessary to check if the start sequence number to the end sequence number ("seqno + length") would contain a new range. If this is the case then this is enough to accept this packet. In all other cases, the packet still has to be dropped (and not acked). Cc: stable@kernel.org Fixes: 33a3bb4 ("batman-adv: throughput meter implementation") [ Switch to pre-splitted tp_vars structure names ] Signed-off-by: Sven Eckelmann <sven@narfation.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent d511c72 commit af5a069

1 file changed

Lines changed: 11 additions & 14 deletions

File tree

net/batman-adv/tp_meter.c

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,7 +1284,8 @@ static int batadv_tp_send_ack(struct batadv_priv *bat_priv, const u8 *dst,
12841284
/**
12851285
* batadv_tp_handle_out_of_order() - store an out of order packet
12861286
* @tp_vars: the private data of the current TP meter session
1287-
* @skb: the buffer containing the received packet
1287+
* @seqno: sequence number of new received packet
1288+
* @payload_len: length of the received packet
12881289
*
12891290
* Store the out of order packet in the unacked list for late processing. This
12901291
* packets are kept in this list so that they can be ACKed at once as soon as
@@ -1293,22 +1294,17 @@ static int batadv_tp_send_ack(struct batadv_priv *bat_priv, const u8 *dst,
12931294
* Return: true if the packed has been successfully processed, false otherwise
12941295
*/
12951296
static bool batadv_tp_handle_out_of_order(struct batadv_tp_vars *tp_vars,
1296-
const struct sk_buff *skb)
1297+
u32 seqno, u32 payload_len)
12971298
__must_hold(&tp_vars->unacked_lock)
12981299
{
1299-
const struct batadv_icmp_tp_packet *icmp;
13001300
struct batadv_tp_unacked *un, *new;
1301-
u32 payload_len;
13021301
bool added = false;
13031302

13041303
new = kmalloc(sizeof(*new), GFP_ATOMIC);
13051304
if (unlikely(!new))
13061305
return false;
13071306

1308-
icmp = (struct batadv_icmp_tp_packet *)skb->data;
1309-
1310-
new->seqno = ntohl(icmp->seqno);
1311-
payload_len = skb->len - sizeof(struct batadv_unicast_packet);
1307+
new->seqno = seqno;
13121308
new->len = payload_len;
13131309

13141310
/* if the list is empty immediately attach this new object */
@@ -1476,7 +1472,7 @@ static void batadv_tp_recv_msg(struct batadv_priv *bat_priv,
14761472
{
14771473
const struct batadv_icmp_tp_packet *icmp;
14781474
struct batadv_tp_vars *tp_vars;
1479-
size_t packet_size;
1475+
u32 payload_len;
14801476
u32 to_ack;
14811477
u32 seqno;
14821478

@@ -1511,15 +1507,17 @@ static void batadv_tp_recv_msg(struct batadv_priv *bat_priv,
15111507
/* if the packet is a duplicate, it may be the case that an ACK has been
15121508
* lost. Resend the ACK
15131509
*/
1514-
if (batadv_seq_before(seqno, tp_vars->last_recv))
1510+
payload_len = skb->len - sizeof(struct batadv_unicast_packet);
1511+
to_ack = seqno + payload_len;
1512+
if (batadv_seq_before(to_ack, tp_vars->last_recv))
15151513
goto send_ack;
15161514

15171515
/* if the packet is out of order enqueue it */
1518-
if (ntohl(icmp->seqno) != tp_vars->last_recv) {
1516+
if (batadv_seq_before(tp_vars->last_recv, seqno)) {
15191517
/* exit immediately (and do not send any ACK) if the packet has
15201518
* not been enqueued correctly
15211519
*/
1522-
if (!batadv_tp_handle_out_of_order(tp_vars, skb)) {
1520+
if (!batadv_tp_handle_out_of_order(tp_vars, seqno, payload_len)) {
15231521
spin_unlock_bh(&tp_vars->unacked_lock);
15241522
goto out;
15251523
}
@@ -1529,8 +1527,7 @@ static void batadv_tp_recv_msg(struct batadv_priv *bat_priv,
15291527
}
15301528

15311529
/* if everything was fine count the ACKed bytes */
1532-
packet_size = skb->len - sizeof(struct batadv_unicast_packet);
1533-
tp_vars->last_recv += packet_size;
1530+
tp_vars->last_recv = to_ack;
15341531

15351532
/* check if this ordered message filled a gap.... */
15361533
batadv_tp_ack_unordered(tp_vars);

0 commit comments

Comments
 (0)