[PATCH net-next 13/15] batman-adv: tp_meter: keep unacked list for receivers
Simon Wunderlich <[email protected]> Tue, 30 Jun 2026 16:06:21 +0200
| Newsgroups | org.open-mesh.lists.batman,org.kernel.vger.netdev |
|---|---|
| Message-ID | <[email protected]> |
From: Sven Eckelmann <[email protected]> There is no need to share the unacked list between sender and receivers. Only receivers will ever write to and read from it. The initialization in batadv_tp_start() was therefore never needed. After its removal, it is enough to just store it in struct batadv_tp_receiver. Signed-off-by: Sven Eckelmann <[email protected]> Signed-off-by: Simon Wunderlich <[email protected]> --- net/batman-adv/tp_meter.c | 110 +++++++++++++++++++++----------------- net/batman-adv/types.h | 20 +++---- 2 files changed, 71 insertions(+), 59 deletions(-) diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c index 5cc719c81ea0b..f18ce360839d3 100644 --- a/net/batman-adv/tp_meter.c +++ b/net/batman-adv/tp_meter.c @@ -358,28 +358,16 @@ batadv_tp_list_find_sender_session(struct batadv_priv *bat_priv, const u8 *dst, } /** - * batadv_tp_vars_common_release() - release batadv_tp_vars_common from lists + * batadv_tp_sender_release() - release batadv_tp_sender * and queue for free after rcu grace period - * @ref: kref pointer of the batadv_tp_vars_common + * @ref: kref pointer of the batadv_tp_sender */ -static void batadv_tp_vars_common_release(struct kref *ref) +static void batadv_tp_sender_release(struct kref *ref) { - struct batadv_tp_vars_common *tp_vars; - struct batadv_tp_unacked *un, *safe; - - tp_vars = container_of(ref, struct batadv_tp_vars_common, refcount); - - /* lock should not be needed because this object is now out of any - * context! - */ - spin_lock_bh(&tp_vars->unacked_lock); - list_for_each_entry_safe(un, safe, &tp_vars->unacked_list, list) { - list_del(&un->list); - kfree(un); - } - spin_unlock_bh(&tp_vars->unacked_lock); + struct batadv_tp_sender *tp_vars; - kfree_rcu(tp_vars, rcu); + tp_vars = container_of(ref, struct batadv_tp_sender, common.refcount); + kfree_rcu(tp_vars, common.rcu); } /** @@ -392,7 +380,7 @@ static void batadv_tp_sender_put(struct batadv_tp_sender *tp_vars) if (!tp_vars) return; - kref_put(&tp_vars->common.refcount, batadv_tp_vars_common_release); + kref_put(&tp_vars->common.refcount, batadv_tp_sender_release); } /** @@ -1145,9 +1133,6 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst, init_waitqueue_head(&tp_vars->more_bytes); init_completion(&tp_vars->finished); - spin_lock_init(&tp_vars->common.unacked_lock); - INIT_LIST_HEAD(&tp_vars->common.unacked_list); - spin_lock_init(&tp_vars->cc_lock); tp_vars->prerandom_offset = 0; @@ -1251,6 +1236,33 @@ batadv_tp_list_find_receiver_session(struct batadv_priv *bat_priv, const u8 *dst return tp_vars; } +/** + * batadv_tp_receiver_release() - release batadv_tp_receiver + * and queue for free after rcu grace period + * @ref: kref pointer of the batadv_tp_receiver + */ +static void batadv_tp_receiver_release(struct kref *ref) +{ + struct batadv_tp_receiver *tp_vars; + struct batadv_tp_unacked *safe; + struct batadv_tp_unacked *un; + + tp_vars = container_of(ref, struct batadv_tp_receiver, common.refcount); + + /* lock should not be needed because this object is now out of any + * context! + */ + spin_lock_bh(&tp_vars->unacked_lock); + list_for_each_entry_safe(un, safe, &tp_vars->unacked_list, list) { + list_del(&un->list); + kfree(un); + tp_vars->unacked_count--; + } + spin_unlock_bh(&tp_vars->unacked_lock); + + kfree_rcu(tp_vars, common.rcu); +} + /** * batadv_tp_receiver_put() - decrement the batadv_tp_receiver * refcounter and possibly release it @@ -1261,7 +1273,7 @@ static void batadv_tp_receiver_put(struct batadv_tp_receiver *tp_vars) if (!tp_vars) return; - kref_put(&tp_vars->common.refcount, batadv_tp_vars_common_release); + kref_put(&tp_vars->common.refcount, batadv_tp_receiver_release); } /** @@ -1304,13 +1316,13 @@ static void batadv_tp_receiver_shutdown(struct timer_list *t) if (batadv_tp_list_detach(&tp_vars->common)) batadv_tp_receiver_put(tp_vars); - spin_lock_bh(&tp_vars->common.unacked_lock); - list_for_each_entry_safe(un, safe, &tp_vars->common.unacked_list, list) { + spin_lock_bh(&tp_vars->unacked_lock); + list_for_each_entry_safe(un, safe, &tp_vars->unacked_list, list) { list_del(&un->list); kfree(un); - tp_vars->common.unacked_count--; + tp_vars->unacked_count--; } - spin_unlock_bh(&tp_vars->common.unacked_lock); + spin_unlock_bh(&tp_vars->unacked_lock); /* drop reference of timer */ if (WARN_ON(atomic_xchg(&tp_vars->receiving, 0) != 1)) @@ -1403,7 +1415,7 @@ static int batadv_tp_send_ack(struct batadv_priv *bat_priv, const u8 *dst, */ static bool batadv_tp_handle_out_of_order(struct batadv_tp_receiver *tp_vars, u32 seqno, u32 payload_len) - __must_hold(&tp_vars->common.unacked_lock) + __must_hold(&tp_vars->unacked_lock) { struct batadv_tp_unacked *un, *new; struct batadv_tp_unacked *safe; @@ -1417,9 +1429,9 @@ static bool batadv_tp_handle_out_of_order(struct batadv_tp_receiver *tp_vars, new->len = payload_len; /* 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++; + if (list_empty(&tp_vars->unacked_list)) { + list_add(&new->list, &tp_vars->unacked_list); + tp_vars->unacked_count++; return true; } @@ -1430,7 +1442,7 @@ static bool batadv_tp_handle_out_of_order(struct batadv_tp_receiver *tp_vars, * the last received packet (the one being processed now) has a bigger * seqno than all the others already stored. */ - list_for_each_entry_reverse(un, &tp_vars->common.unacked_list, list) { + list_for_each_entry_reverse(un, &tp_vars->unacked_list, list) { /* look for the right position - an un which is smaller */ if (batadv_seq_before(new->seqno, un->seqno)) continue; @@ -1476,19 +1488,19 @@ static bool batadv_tp_handle_out_of_order(struct batadv_tp_receiver *tp_vars, */ list_add(&new->list, &un->list); added = true; - tp_vars->common.unacked_count++; + tp_vars->unacked_count++; break; } /* received packet with smallest seqno out of order; add it to front */ if (!added) { - list_add(&new->list, &tp_vars->common.unacked_list); - tp_vars->common.unacked_count++; + list_add(&new->list, &tp_vars->unacked_list); + tp_vars->unacked_count++; } /* check if new filled the gap to the next list entries */ un = new; - list_for_each_entry_safe_continue(un, safe, &tp_vars->common.unacked_list, list) { + list_for_each_entry_safe_continue(un, safe, &tp_vars->unacked_list, list) { if (batadv_seq_before(new->seqno + new->len, un->seqno)) break; @@ -1499,16 +1511,16 @@ static bool batadv_tp_handle_out_of_order(struct batadv_tp_receiver *tp_vars, list_del(&un->list); kfree(un); - tp_vars->common.unacked_count--; + tp_vars->unacked_count--; } /* remove the last (biggest) unacked seqno when list is too large */ - if (tp_vars->common.unacked_count > BATADV_TP_MAX_UNACKED) { - un = list_last_entry(&tp_vars->common.unacked_list, + if (tp_vars->unacked_count > BATADV_TP_MAX_UNACKED) { + un = list_last_entry(&tp_vars->unacked_list, struct batadv_tp_unacked, list); list_del(&un->list); kfree(un); - tp_vars->common.unacked_count--; + tp_vars->unacked_count--; } return true; @@ -1520,7 +1532,7 @@ static bool batadv_tp_handle_out_of_order(struct batadv_tp_receiver *tp_vars, * @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) + __must_hold(&tp_vars->unacked_lock) { struct batadv_tp_unacked *un, *safe; u32 to_ack; @@ -1528,7 +1540,7 @@ static void batadv_tp_ack_unordered(struct batadv_tp_receiver *tp_vars) /* go through the unacked packet list and possibly ACK them as * well */ - list_for_each_entry_safe(un, safe, &tp_vars->common.unacked_list, list) { + list_for_each_entry_safe(un, safe, &tp_vars->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 * the packet under inspection @@ -1543,7 +1555,7 @@ static void batadv_tp_ack_unordered(struct batadv_tp_receiver *tp_vars) list_del(&un->list); kfree(un); - tp_vars->common.unacked_count--; + tp_vars->unacked_count--; } } @@ -1590,9 +1602,9 @@ batadv_tp_init_recv(struct batadv_priv *bat_priv, tp_vars->common.bat_priv = bat_priv; kref_init(&tp_vars->common.refcount); - spin_lock_init(&tp_vars->common.unacked_lock); - INIT_LIST_HEAD(&tp_vars->common.unacked_list); - tp_vars->common.unacked_count = 0; + spin_lock_init(&tp_vars->unacked_lock); + INIT_LIST_HEAD(&tp_vars->unacked_list); + tp_vars->unacked_count = 0; kref_get(&tp_vars->common.refcount); timer_setup(&tp_vars->common.timer, batadv_tp_receiver_shutdown, 0); @@ -1652,7 +1664,7 @@ static void batadv_tp_recv_msg(struct batadv_priv *bat_priv, WRITE_ONCE(tp_vars->last_recv_time, jiffies); } - spin_lock_bh(&tp_vars->common.unacked_lock); + spin_lock_bh(&tp_vars->unacked_lock); /* if the packet is a duplicate, it may be the case that an ACK has been * lost. Resend the ACK @@ -1668,7 +1680,7 @@ static void batadv_tp_recv_msg(struct batadv_priv *bat_priv, * not been enqueued correctly */ if (!batadv_tp_handle_out_of_order(tp_vars, seqno, payload_len)) { - spin_unlock_bh(&tp_vars->common.unacked_lock); + spin_unlock_bh(&tp_vars->unacked_lock); goto out; } @@ -1684,7 +1696,7 @@ static void batadv_tp_recv_msg(struct batadv_priv *bat_priv, send_ack: to_ack = tp_vars->last_recv; - spin_unlock_bh(&tp_vars->common.unacked_lock); + spin_unlock_bh(&tp_vars->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 diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index c2ab00d8ef160..c194d8069774c 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -1334,7 +1334,7 @@ struct batadv_tp_unacked { /** @len: length of the packet */ u32 len; - /** @list: list node for &batadv_tp_vars_common.unacked_list */ + /** @list: list node for &batadv_tp_receiver.unacked_list */ struct list_head list; }; @@ -1357,15 +1357,6 @@ struct batadv_tp_vars_common { /** @session: TP session identifier */ u8 session[2]; - /** @unacked_list: list of unacked packets (meta-info only) */ - struct list_head unacked_list; - - /** @unacked_lock: protect unacked_list + &batadv_tp_receiver.last_recv */ - spinlock_t unacked_lock; - - /** @unacked_count: number of unacked entries */ - size_t unacked_count; - /** @refcount: number of context where the object is used */ struct kref refcount; @@ -1479,6 +1470,15 @@ struct batadv_tp_receiver { /** @last_recv_time: time (jiffies) a msg was received */ unsigned long last_recv_time; + + /** @unacked_list: list of unacked packets (meta-info only) */ + struct list_head unacked_list; + + /** @unacked_lock: protect unacked_list + &batadv_tp_receiver.last_recv */ + spinlock_t unacked_lock; + + /** @unacked_count: number of unacked entries */ + size_t unacked_count; }; /** -- 2.47.3