This cleanup patchset includes the following patches, all by

Sven Eckelmann:
 
 - tp_meter: fix various minor issues (8 patches)
 
 - tp_meter: split generic session type in sender and receiver type
 
 - tp_meter: consolidate locking for congestion control (2 patches)
 
 - bla: annotate lasttime access with READ/WRITE_ONCE
 
 - elp: prevent transmission interval underflow
 
 - tt: sync local and global tvlv preparation return values
 
 - tt: directly retrieve wifi flags of net_device
 -----BEGIN PGP SIGNATURE-----
 
 iQJKBAABCgA0FiEE1ilQI7G+y+fdhnrfoSvjmEKSnqEFAmof1RcWHHN3QHNpbW9u
 d3VuZGVybGljaC5kZQAKCRChK+OYQpKeoXFpD/9vC4c/dbbOq/s28H3awYuF8gNK
 6YcElAe+1fXVCCwpHuxmK9Zqc8sCTVrHB5utwEgL+NYK9foIgbUrNW7rlL7R8Yuz
 5Rxq1s85kVCtp2hjKZHrIcEoSejDXyqEWz1oUpyW0yO07FczuG5Jd9hsPpvRWGhI
 oAMiUvbeiBZKjqJdN+KiI2vGX4IB1+RVIp8h1rplmyJBBLflItuc/jm+x8Bzqoy3
 4rjVGZqmS6wiiMbo6m1cK0PCPnwALHrR3tBM5ALHtpz3Z5lPOLEFsOYA+5MyeqQT
 urIoW63V3XyQZwAUY/4hG4RuCXAGgye2rjJhduvN4Lx1sDP0j7BoEXry7uiObvUy
 CG/csdSmipHLCiKd9QGJ5KEOHaPG3JA51Yfy4MWDiEHQbfQGbOEpXHNwW4lbBPOc
 ubj5eHA7PksWAHE+GZYB6SyB300T0SI/aVCOKhjVHTI9UWH56z6t5O34XMEhFqt8
 5zcD1sSnqjL0vHXGt1bNEpCVVTli0AK5SyWar+R+6w76QZcPdXOHfAMGpuQWItJ3
 BYR36YCnHuUhNPYI8JLi+3xOcatrGzL6iiAqK+DCUltJDgqg73FAPHzME8aqZf51
 X7SUlW5oXG6LpOyXEaToBSIj1uAvr6BKb48tMxB6fgWSAYJ2gvh2aY2ogglgUMAa
 nHboJuY4zGwRj+ddAA==
 =HPzZ
 -----END PGP SIGNATURE-----

Merge tag 'batadv-next-pullrequest-20260603' of https://git.open-mesh.org/batadv

Simon Wunderlich says:

====================
This cleanup patchset includes the following patches, all by
Sven Eckelmann:

- tp_meter: fix various minor issues (8 patches)

- tp_meter: split generic session type in sender and receiver type

- tp_meter: consolidate locking for congestion control (2 patches)

- bla: annotate lasttime access with READ/WRITE_ONCE

- elp: prevent transmission interval underflow

- tt: sync local and global tvlv preparation return values

- tt: directly retrieve wifi flags of net_device

* tag 'batadv-next-pullrequest-20260603' of https://git.open-mesh.org/batadv:
  batman-adv: tt: directly retrieve wifi flags of net_device
  batman-adv: tt: sync local and global tvlv preparation return values
  batman-adv: prevent ELP transmission interval underflow
  batman-adv: bla: annotate lasttime access with READ/WRITE_ONCE
  batman-adv: tp_meter: consolidate congestion control variables
  batman-adv: tp_meter: use locking for all congestion control variables
  batman-adv: tp_meter: split vars into sender and receiver types
  batman-adv: tp_meter: add only finished tp_vars to lists
  batman-adv: tp_meter: handle seqno wrap-around for fast recovery detection
  batman-adv: tp_meter: fix fast recovery precondition
  batman-adv: tp_meter: avoid divide-by-zero for dec_cwnd
  batman-adv: tp_meter: avoid window underflow
  batman-adv: tp_meter: initialize dec_cwnd explicitly
  batman-adv: tp_meter: initialize dup_acks explicitly
  batman-adv: tp_meter: keep unacked list in ascending ordered
====================

Link: https://patch.msgid.link/20260603072527.174487-1-sw@simonwunderlich.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-06-04 19:14:35 -07:00
commit bfa3d89cc1
8 changed files with 580 additions and 413 deletions

View File

@ -513,7 +513,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, const u8 *orig,
return NULL;
entry->vid = vid;
entry->lasttime = jiffies;
WRITE_ONCE(entry->lasttime, jiffies);
entry->crc = BATADV_BLA_CRC_INIT;
entry->bat_priv = bat_priv;
spin_lock_init(&entry->crc_lock);
@ -581,7 +581,7 @@ batadv_bla_update_own_backbone_gw(struct batadv_priv *bat_priv,
if (unlikely(!backbone_gw))
return;
backbone_gw->lasttime = jiffies;
WRITE_ONCE(backbone_gw->lasttime, jiffies);
batadv_backbone_gw_put(backbone_gw);
}
@ -715,7 +715,7 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
ether_addr_copy(claim->addr, mac);
spin_lock_init(&claim->backbone_lock);
claim->vid = vid;
claim->lasttime = jiffies;
WRITE_ONCE(claim->lasttime, jiffies);
kref_get(&backbone_gw->refcount);
claim->backbone_gw = backbone_gw;
kref_init(&claim->refcount);
@ -737,7 +737,7 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
return;
}
} else {
claim->lasttime = jiffies;
WRITE_ONCE(claim->lasttime, jiffies);
if (claim->backbone_gw == backbone_gw)
/* no need to register a new backbone */
goto claim_free_ref;
@ -770,7 +770,7 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
spin_lock_bh(&backbone_gw->crc_lock);
backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN);
spin_unlock_bh(&backbone_gw->crc_lock);
backbone_gw->lasttime = jiffies;
WRITE_ONCE(backbone_gw->lasttime, jiffies);
claim_free_ref:
batadv_claim_put(claim);
@ -859,7 +859,7 @@ static bool batadv_handle_announce(struct batadv_priv *bat_priv, u8 *an_addr,
return true;
/* handle as ANNOUNCE frame */
backbone_gw->lasttime = jiffies;
WRITE_ONCE(backbone_gw->lasttime, jiffies);
crc = ntohs(*((__force __be16 *)(&an_addr[4])));
batadv_dbg(BATADV_DBG_BLA, bat_priv,
@ -1254,7 +1254,7 @@ static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now)
head, hash_entry) {
if (now)
goto purge_now;
if (!batadv_has_timed_out(backbone_gw->lasttime,
if (!batadv_has_timed_out(READ_ONCE(backbone_gw->lasttime),
BATADV_BLA_BACKBONE_TIMEOUT))
continue;
@ -1335,7 +1335,7 @@ static void batadv_bla_purge_claims(struct batadv_priv *bat_priv,
primary_if->net_dev->dev_addr))
goto skip;
if (!batadv_has_timed_out(claim->lasttime,
if (!batadv_has_timed_out(READ_ONCE(claim->lasttime),
BATADV_BLA_CLAIM_TIMEOUT))
goto skip;
@ -1495,7 +1495,7 @@ static void batadv_bla_periodic_work(struct work_struct *work)
eth_random_addr(bat_priv->bla.loopdetect_addr);
bat_priv->bla.loopdetect_addr[0] = 0xba;
bat_priv->bla.loopdetect_addr[1] = 0xbe;
bat_priv->bla.loopdetect_lasttime = jiffies;
WRITE_ONCE(bat_priv->bla.loopdetect_lasttime, jiffies);
atomic_set(&bat_priv->bla.loopdetect_next,
BATADV_BLA_LOOPDETECT_PERIODS);
@ -1516,7 +1516,7 @@ static void batadv_bla_periodic_work(struct work_struct *work)
primary_if->net_dev->dev_addr))
continue;
backbone_gw->lasttime = jiffies;
WRITE_ONCE(backbone_gw->lasttime, jiffies);
batadv_bla_send_announce(bat_priv, backbone_gw);
if (send_loopdetect)
@ -1900,7 +1900,7 @@ batadv_bla_loopdetect_check(struct batadv_priv *bat_priv, struct sk_buff *skb,
/* If the packet came too late, don't forward it on the mesh
* but don't consider that as loop. It might be a coincidence.
*/
if (batadv_has_timed_out(bat_priv->bla.loopdetect_lasttime,
if (batadv_has_timed_out(READ_ONCE(bat_priv->bla.loopdetect_lasttime),
BATADV_BLA_LOOPDETECT_TIMEOUT))
return true;
@ -2015,7 +2015,7 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
if (own_claim) {
/* ... allow it in any case */
claim->lasttime = jiffies;
WRITE_ONCE(claim->lasttime, jiffies);
goto allow;
}
@ -2117,7 +2117,7 @@ bool batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
/* if yes, the client has roamed and we have
* to unclaim it.
*/
if (batadv_has_timed_out(claim->lasttime, 100)) {
if (batadv_has_timed_out(READ_ONCE(claim->lasttime), 100)) {
/* only unclaim if the last claim entry is
* older than 100 ms to make sure we really
* have a roaming client here.
@ -2362,7 +2362,7 @@ batadv_bla_backbone_dump_entry(struct sk_buff *msg, u32 portid,
backbone_crc = backbone_gw->crc;
spin_unlock_bh(&backbone_gw->crc_lock);
msecs = jiffies_to_msecs(jiffies - backbone_gw->lasttime);
msecs = jiffies_to_msecs(jiffies - READ_ONCE(backbone_gw->lasttime));
if (is_own)
if (nla_put_flag(msg, BATADV_ATTR_BLA_OWN)) {

View File

@ -365,6 +365,28 @@ static u32 batadv_wifi_flags_evaluate(struct net_device *net_device)
return wifi_flags;
}
/**
* batadv_netdev_get_wifi_flags() - retrieve wifi flags for net_device
* @net_dev: the device to check
*
* Return: batadv_hard_iface_wifi_flags flags of the device
*/
u32 batadv_netdev_get_wifi_flags(struct net_device *net_dev)
{
struct batadv_wifi_net_device_state *device_state;
u32 wifi_flags = 0;
rcu_read_lock();
device_state = rhashtable_lookup_fast(&batadv_wifi_net_devices,
&net_dev,
batadv_wifi_net_devices_params);
if (device_state)
wifi_flags = READ_ONCE(device_state->wifi_flags);
rcu_read_unlock();
return wifi_flags;
}
/**
* batadv_hardif_get_wifi_flags() - retrieve wifi flags for hard_iface
* @hard_iface: the device to check
@ -373,21 +395,10 @@ static u32 batadv_wifi_flags_evaluate(struct net_device *net_device)
*/
u32 batadv_hardif_get_wifi_flags(struct batadv_hard_iface *hard_iface)
{
struct batadv_wifi_net_device_state *device_state;
u32 wifi_flags = 0;
if (!hard_iface)
return 0;
rcu_read_lock();
device_state = rhashtable_lookup_fast(&batadv_wifi_net_devices,
&hard_iface->net_dev,
batadv_wifi_net_devices_params);
if (device_state)
wifi_flags = READ_ONCE(device_state->wifi_flags);
rcu_read_unlock();
return wifi_flags;
return batadv_netdev_get_wifi_flags(hard_iface->net_dev);
}
/**

View File

@ -70,6 +70,7 @@ extern struct notifier_block batadv_hard_if_notifier;
struct net_device *__batadv_get_real_netdev(struct net_device *net_device);
struct net_device *batadv_get_real_netdev(struct net_device *net_device);
u32 batadv_netdev_get_wifi_flags(struct net_device *net_dev);
u32 batadv_hardif_get_wifi_flags(struct batadv_hard_iface *hard_iface);
bool batadv_is_wifi_hardif(struct batadv_hard_iface *hard_iface);
struct batadv_hard_iface*

View File

@ -194,7 +194,8 @@ int batadv_mesh_init(struct net_device *mesh_iface)
INIT_HLIST_HEAD(&bat_priv->tvlv.container_list);
INIT_HLIST_HEAD(&bat_priv->tvlv.handler_list);
INIT_HLIST_HEAD(&bat_priv->meshif_vlan_list);
INIT_HLIST_HEAD(&bat_priv->tp_list);
INIT_HLIST_HEAD(&bat_priv->tp_sender_list);
INIT_HLIST_HEAD(&bat_priv->tp_receiver_list);
bat_priv->gw.generation = 0;

View File

@ -919,9 +919,15 @@ static int batadv_netlink_set_hardif(struct sk_buff *skb,
#ifdef CONFIG_BATMAN_ADV_BATMAN_V
if (info->attrs[BATADV_ATTR_ELP_INTERVAL]) {
attr = info->attrs[BATADV_ATTR_ELP_INTERVAL];
u32 elp_interval;
WRITE_ONCE(hard_iface->bat_v.elp_interval, nla_get_u32(attr));
attr = info->attrs[BATADV_ATTR_ELP_INTERVAL];
elp_interval = nla_get_u32(attr);
elp_interval = min_t(u32, elp_interval, INT_MAX);
elp_interval = max_t(u32, elp_interval, BATADV_JITTER);
WRITE_ONCE(hard_iface->bat_v.elp_interval, elp_interval);
}
if (info->attrs[BATADV_ATTR_THROUGHPUT_OVERRIDE]) {

File diff suppressed because it is too large Load Diff

View File

@ -596,20 +596,23 @@ bool batadv_tt_local_add(struct net_device *mesh_iface, const u8 *addr,
struct net *net = dev_net(mesh_iface);
struct batadv_meshif_vlan *vlan;
struct net_device *in_dev = NULL;
struct batadv_hard_iface *in_hardif = NULL;
struct hlist_head *head;
struct batadv_tt_orig_list_entry *orig_entry;
int hash_added, table_size, packet_size_max;
bool ret = false;
bool roamed_back = false;
bool iif_is_wifi = false;
u8 remote_flags;
u32 match_mark;
if (ifindex != BATADV_NULL_IFINDEX)
in_dev = dev_get_by_index(net, ifindex);
if (in_dev)
in_hardif = batadv_hardif_get_by_netdev(in_dev);
if (in_dev) {
u32 wifi_flags = batadv_netdev_get_wifi_flags(in_dev);
iif_is_wifi = batadv_is_wifi(wifi_flags);
}
tt_local = batadv_tt_local_hash_find(bat_priv, addr, vid);
@ -684,7 +687,7 @@ bool batadv_tt_local_add(struct net_device *mesh_iface, const u8 *addr,
*/
tt_local->common.flags = BATADV_TT_CLIENT_NEW;
tt_local->common.vid = vid;
if (batadv_is_wifi_hardif(in_hardif))
if (iif_is_wifi)
tt_local->common.flags |= BATADV_TT_CLIENT_WIFI;
kref_init(&tt_local->common.refcount);
tt_local->last_seen = jiffies;
@ -743,7 +746,7 @@ bool batadv_tt_local_add(struct net_device *mesh_iface, const u8 *addr,
*/
remote_flags = tt_local->common.flags & BATADV_TT_REMOTE_MASK;
if (batadv_is_wifi_hardif(in_hardif))
if (iif_is_wifi)
tt_local->common.flags |= BATADV_TT_CLIENT_WIFI;
else
tt_local->common.flags &= ~BATADV_TT_CLIENT_WIFI;
@ -767,7 +770,6 @@ bool batadv_tt_local_add(struct net_device *mesh_iface, const u8 *addr,
ret = true;
out:
batadv_hardif_put(in_hardif);
dev_put(in_dev);
batadv_tt_local_entry_put(tt_local);
batadv_tt_global_entry_put(tt_global);
@ -797,21 +799,22 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
struct batadv_tvlv_tt_change **tt_change,
s32 *tt_len)
{
u16 num_vlan = 0;
u16 tvlv_len = 0;
struct batadv_tvlv_tt_vlan_data *tt_vlan;
struct batadv_orig_node_vlan *vlan;
u16 total_entries = 0;
size_t change_offset;
u8 *tt_change_ptr;
u16 num_vlan = 0;
int vlan_entries;
u16 sum_entries;
u16 tvlv_len;
spin_lock_bh(&orig_node->vlan_list_lock);
hlist_for_each_entry(vlan, &orig_node->vlan_list, list) {
vlan_entries = atomic_read(&vlan->tt.num_entries);
if (check_add_overflow(vlan_entries, total_entries, &sum_entries)) {
tvlv_len = 0;
*tt_len = 0;
goto out;
}
@ -827,12 +830,14 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
*tt_len = batadv_tt_len(total_entries);
if (check_add_overflow(*tt_len, change_offset, &tvlv_len)) {
tvlv_len = 0;
*tt_len = 0;
goto out;
}
*tt_data = kmalloc(tvlv_len, GFP_ATOMIC);
if (!*tt_data) {
tvlv_len = 0;
*tt_len = 0;
goto out;
}
@ -867,6 +872,7 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
out:
spin_unlock_bh(&orig_node->vlan_list_lock);
return tvlv_len;
}
@ -896,13 +902,13 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
{
struct batadv_tvlv_tt_vlan_data *tt_vlan;
struct batadv_meshif_vlan *vlan;
size_t change_offset;
u16 num_vlan = 0;
u16 total_entries = 0;
u16 tvlv_len;
size_t change_offset;
u8 *tt_change_ptr;
u16 num_vlan = 0;
int vlan_entries;
u16 sum_entries;
u16 tvlv_len;
spin_lock_bh(&bat_priv->meshif_vlan_list_lock);
hlist_for_each_entry(vlan, &bat_priv->meshif_vlan_list, list) {
@ -910,6 +916,7 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
if (check_add_overflow(vlan_entries, total_entries, &sum_entries)) {
tvlv_len = 0;
*tt_len = 0;
goto out;
}
@ -925,12 +932,14 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
if (check_add_overflow(*tt_len, change_offset, &tvlv_len)) {
tvlv_len = 0;
*tt_len = 0;
goto out;
}
*tt_data = kmalloc(tvlv_len, GFP_ATOMIC);
if (!*tt_data) {
tvlv_len = 0;
*tt_len = 0;
goto out;
}
@ -964,6 +973,7 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
out:
spin_unlock_bh(&bat_priv->meshif_vlan_list_lock);
return tvlv_len;
}

View File

@ -1336,21 +1336,10 @@ struct batadv_tp_unacked {
};
/**
* enum batadv_tp_meter_role - Modus in tp meter session
* struct batadv_tp_vars_common - common tp meter private variables per session
*/
enum batadv_tp_meter_role {
/** @BATADV_TP_RECEIVER: Initialized as receiver */
BATADV_TP_RECEIVER,
/** @BATADV_TP_SENDER: Initialized as sender */
BATADV_TP_SENDER
};
/**
* struct batadv_tp_vars - tp meter private variables per session
*/
struct batadv_tp_vars {
/** @list: list node for &bat_priv.tp_list */
struct batadv_tp_vars_common {
/** @list: list node for &bat_priv.tp_sender_list/&bat_priv.tp_receiver_list */
struct hlist_node list;
/** @timer: timer for ack (receiver) and retry (sender) */
@ -1359,40 +1348,32 @@ struct batadv_tp_vars {
/** @bat_priv: pointer to the mesh object */
struct batadv_priv *bat_priv;
/** @start_time: start time in jiffies */
unsigned long start_time;
/** @other_end: mac address of remote */
u8 other_end[ETH_ALEN];
/** @role: receiver/sender modi */
enum batadv_tp_meter_role role;
/**
* @send_result: 0 when sending is ongoing and otherwise
* enum batadv_tp_meter_reason
*/
atomic_t send_result;
/** @receiving: receiving binary semaphore: 1 if receiving, 0 is not */
atomic_t receiving;
/** @finish_work: work item for the finishing procedure */
struct delayed_work finish_work;
/** @finished: completion signaled when a sender thread exits */
struct completion finished;
/** @test_length: test length in milliseconds */
u32 test_length;
/** @session: TP session identifier */
u8 session[2];
/** @icmp_uid: local ICMP "socket" index */
u8 icmp_uid;
/** @unacked_list: list of unacked packets (meta-info only) */
struct list_head unacked_list;
/* sender variables */
/** @unacked_lock: protect unacked_list */
spinlock_t unacked_lock;
/** @refcount: number of context where the object is used */
struct kref refcount;
/** @rcu: struct used for freeing in an RCU-safe manner */
struct rcu_head rcu;
};
/** struct batadv_tp_sender_cc - congestion control variables */
struct batadv_tp_sender_cc {
/** @fast_recovery: true if in Fast Recovery mode */
bool fast_recovery:1;
/** @dup_acks: duplicate ACKs counter */
u8 dup_acks;
/** @dec_cwnd: decimal part of the cwnd used during linear growth */
u16 dec_cwnd;
@ -1400,9 +1381,6 @@ struct batadv_tp_vars {
/** @cwnd: current size of the congestion window */
u32 cwnd;
/** @cwnd_lock: lock do protect @cwnd & @dec_cwnd */
spinlock_t cwnd_lock;
/**
* @ss_threshold: Slow Start threshold. Once cwnd exceeds this value the
* connection switches to the Congestion Avoidance state
@ -1410,20 +1388,11 @@ struct batadv_tp_vars {
u32 ss_threshold;
/** @last_acked: last acked byte */
atomic_t last_acked;
u32 last_acked;
/** @last_sent: last sent byte, not yet acked */
u32 last_sent;
/** @tot_sent: amount of data sent/ACKed so far */
atomic64_t tot_sent;
/** @dup_acks: duplicate ACKs counter */
atomic_t dup_acks;
/** @fast_recovery: true if in Fast Recovery mode */
unsigned char fast_recovery:1;
/** @recover: last sent seqno when entering Fast Recovery */
u32 recover;
@ -1435,6 +1404,44 @@ struct batadv_tp_vars {
/** @rttvar: RTT variation scaled by 2^2 */
u32 rttvar;
};
/**
* struct batadv_tp_sender - sender tp meter private variables per session
*/
struct batadv_tp_sender {
/** @common: common batadv_tp_vars (best be first member) */
struct batadv_tp_vars_common common;
/** @start_time: start time in jiffies */
unsigned long start_time;
/**
* @send_result: 0 when sending is ongoing and otherwise
* enum batadv_tp_meter_reason
*/
atomic_t send_result;
/** @finish_work: work item for the finishing procedure */
struct delayed_work finish_work;
/** @finished: completion signaled when a sender thread exits */
struct completion finished;
/** @test_length: test length in milliseconds */
u32 test_length;
/** @icmp_uid: local ICMP "socket" index */
u8 icmp_uid;
/** @cc: congestion control variables */
struct batadv_tp_sender_cc cc;
/** @cc_lock: lock do protect @cc */
spinlock_t cc_lock;
/** @tot_sent: amount of data sent/ACKed so far */
atomic64_t tot_sent;
/**
* @more_bytes: waiting queue anchor when waiting for more ack/retry
@ -1447,26 +1454,23 @@ struct batadv_tp_vars {
/** @prerandom_lock: spinlock protecting access to prerandom_offset */
spinlock_t prerandom_lock;
};
/* receiver variables */
/**
* struct batadv_tp_receiver - receiver tp meter private variables per session
*/
struct batadv_tp_receiver {
/** @common: common batadv_tp_vars (best be first member) */
struct batadv_tp_vars_common common;
/** @receiving: receiving binary semaphore: 1 if receiving, 0 is not */
atomic_t receiving;
/** @last_recv: last in-order received packet */
u32 last_recv;
/** @unacked_list: list of unacked packets (meta-info only) */
struct list_head unacked_list;
/** @unacked_lock: protect unacked_list */
spinlock_t unacked_lock;
/** @last_recv_time: time (jiffies) a msg was received */
unsigned long last_recv_time;
/** @refcount: number of context where the object is used */
struct kref refcount;
/** @rcu: struct used for freeing in an RCU-safe manner */
struct rcu_head rcu;
};
/**
@ -1643,8 +1647,11 @@ struct batadv_priv {
*/
struct hlist_head forw_bcast_list;
/** @tp_list: list of tp sessions */
struct hlist_head tp_list;
/** @tp_sender_list: list of tp sender sessions */
struct hlist_head tp_sender_list;
/** @tp_receiver_list: list of tp receiver sessions */
struct hlist_head tp_receiver_list;
/** @orig_hash: hash table containing mesh participants (orig nodes) */
struct batadv_hashtable *orig_hash;