Skip to content

Commit a5e1df1

Browse files
committed
batman-adv: Merge bugfixes from 2025.0
* force stop of throughput detection workers on interface removal Signed-off-by: Sven Eckelmann <[email protected]>
1 parent 12b7112 commit a5e1df1

4 files changed

+438
-1
lines changed

batman-adv/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ include $(TOPDIR)/rules.mk
44

55
PKG_NAME:=batman-adv
66
PKG_VERSION:=2023.1
7-
PKG_RELEASE:=9
7+
PKG_RELEASE:=10
88

99
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
1010
PKG_SOURCE_URL:=https://downloads.open-mesh.org/batman/releases/batman-adv-$(PKG_VERSION)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
From: Andy Strohman <[email protected]>
2+
Date: Thu, 9 Jan 2025 02:27:56 +0000
3+
Subject: batman-adv: fix panic during interface removal
4+
5+
Reference counting is used to ensure that
6+
batadv_hardif_neigh_node and batadv_hard_iface
7+
are not freed before/during
8+
batadv_v_elp_throughput_metric_update work is
9+
finished.
10+
11+
But there isn't a guarantee that the hard if will
12+
remain associated with a soft interface up until
13+
the work is finished.
14+
15+
This fixes a crash triggered by reboot that looks
16+
like this:
17+
18+
Call trace:
19+
batadv_v_mesh_free+0xd0/0x4dc [batman_adv]
20+
batadv_v_elp_throughput_metric_update+0x1c/0xa4
21+
process_one_work+0x178/0x398
22+
worker_thread+0x2e8/0x4d0
23+
kthread+0xd8/0xdc
24+
ret_from_fork+0x10/0x20
25+
26+
(the batadv_v_mesh_free call is misleading,
27+
and does not actually happen)
28+
29+
I was able to make the issue happen more reliably
30+
by changing hardif_neigh->bat_v.metric_work work
31+
to be delayed work. This allowed me to track down
32+
and confirm the fix.
33+
34+
Fixes: 5c3245172c01 ("batman-adv: ELP - compute the metric based on the estimated throughput")
35+
Signed-off-by: Andy Strohman <[email protected]>
36+
[[email protected]: prevent entering batadv_v_elp_get_throughput without
37+
soft_iface]
38+
Signed-off-by: Sven Eckelmann <[email protected]>
39+
Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/1d7c8ac629678b8cd23ef9def7c7b111cb9e8ed5
40+
41+
--- a/net/batman-adv/bat_v_elp.c
42+
+++ b/net/batman-adv/bat_v_elp.c
43+
@@ -66,12 +66,19 @@ static void batadv_v_elp_start_timer(str
44+
static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
45+
{
46+
struct batadv_hard_iface *hard_iface = neigh->if_incoming;
47+
+ struct net_device *soft_iface = hard_iface->soft_iface;
48+
struct ethtool_link_ksettings link_settings;
49+
struct net_device *real_netdev;
50+
struct station_info sinfo;
51+
u32 throughput;
52+
int ret;
53+
54+
+ /* don't query throughput when no longer associated with any
55+
+ * batman-adv interface
56+
+ */
57+
+ if (!soft_iface)
58+
+ return BATADV_THROUGHPUT_DEFAULT_VALUE;
59+
+
60+
/* if the user specified a customised value for this interface, then
61+
* return it directly
62+
*/
63+
@@ -141,7 +148,7 @@ static u32 batadv_v_elp_get_throughput(s
64+
65+
default_throughput:
66+
if (!(hard_iface->bat_v.flags & BATADV_WARNING_DEFAULT)) {
67+
- batadv_info(hard_iface->soft_iface,
68+
+ batadv_info(soft_iface,
69+
"WiFi driver or ethtool info does not provide information about link speeds on interface %s, therefore defaulting to hardcoded throughput values of %u.%1u Mbps. Consider overriding the throughput manually or checking your driver.\n",
70+
hard_iface->net_dev->name,
71+
BATADV_THROUGHPUT_DEFAULT_VALUE / 10,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
From: Sven Eckelmann <[email protected]>
2+
Date: Wed, 22 Jan 2025 21:51:20 +0100
3+
Subject: batman-adv: Ignore neighbor throughput metrics in error case
4+
5+
If a temporary error happened in the evaluation of the neighbor throughput
6+
information, then the invalid throughput result should not be stored in the
7+
throughtput EWMA.
8+
9+
Signed-off-by: Sven Eckelmann <[email protected]>
10+
Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/ce8b40b7bdcc7f011191acda4c2d3067566eef54
11+
12+
--- a/net/batman-adv/bat_v_elp.c
13+
+++ b/net/batman-adv/bat_v_elp.c
14+
@@ -59,11 +59,13 @@ static void batadv_v_elp_start_timer(str
15+
/**
16+
* batadv_v_elp_get_throughput() - get the throughput towards a neighbour
17+
* @neigh: the neighbour for which the throughput has to be obtained
18+
+ * @pthroughput: calculated throughput towards the given neighbour in multiples
19+
+ * of 100kpbs (a value of '1' equals 0.1Mbps, '10' equals 1Mbps, etc).
20+
*
21+
- * Return: The throughput towards the given neighbour in multiples of 100kpbs
22+
- * (a value of '1' equals 0.1Mbps, '10' equals 1Mbps, etc).
23+
+ * Return: true when value behind @pthroughput was set
24+
*/
25+
-static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
26+
+static bool batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh,
27+
+ u32 *pthroughput)
28+
{
29+
struct batadv_hard_iface *hard_iface = neigh->if_incoming;
30+
struct net_device *soft_iface = hard_iface->soft_iface;
31+
@@ -77,14 +79,16 @@ static u32 batadv_v_elp_get_throughput(s
32+
* batman-adv interface
33+
*/
34+
if (!soft_iface)
35+
- return BATADV_THROUGHPUT_DEFAULT_VALUE;
36+
+ return false;
37+
38+
/* if the user specified a customised value for this interface, then
39+
* return it directly
40+
*/
41+
throughput = atomic_read(&hard_iface->bat_v.throughput_override);
42+
- if (throughput != 0)
43+
- return throughput;
44+
+ if (throughput != 0) {
45+
+ *pthroughput = throughput;
46+
+ return true;
47+
+ }
48+
49+
/* if this is a wireless device, then ask its throughput through
50+
* cfg80211 API
51+
@@ -111,19 +115,24 @@ static u32 batadv_v_elp_get_throughput(s
52+
* possible to delete this neighbor. For now set
53+
* the throughput metric to 0.
54+
*/
55+
- return 0;
56+
+ *pthroughput = 0;
57+
+ return true;
58+
}
59+
if (ret)
60+
goto default_throughput;
61+
62+
- if (sinfo.filled & BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT))
63+
- return sinfo.expected_throughput / 100;
64+
+ if (sinfo.filled & BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT)) {
65+
+ *pthroughput = sinfo.expected_throughput / 100;
66+
+ return true;
67+
+ }
68+
69+
/* try to estimate the expected throughput based on reported tx
70+
* rates
71+
*/
72+
- if (sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE))
73+
- return cfg80211_calculate_bitrate(&sinfo.txrate) / 3;
74+
+ if (sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE)) {
75+
+ *pthroughput = cfg80211_calculate_bitrate(&sinfo.txrate) / 3;
76+
+ return true;
77+
+ }
78+
79+
goto default_throughput;
80+
}
81+
@@ -142,8 +151,10 @@ static u32 batadv_v_elp_get_throughput(s
82+
hard_iface->bat_v.flags &= ~BATADV_FULL_DUPLEX;
83+
84+
throughput = link_settings.base.speed;
85+
- if (throughput && throughput != SPEED_UNKNOWN)
86+
- return throughput * 10;
87+
+ if (throughput && throughput != SPEED_UNKNOWN) {
88+
+ *pthroughput = throughput * 10;
89+
+ return true;
90+
+ }
91+
}
92+
93+
default_throughput:
94+
@@ -157,7 +168,8 @@ default_throughput:
95+
}
96+
97+
/* if none of the above cases apply, return the base_throughput */
98+
- return BATADV_THROUGHPUT_DEFAULT_VALUE;
99+
+ *pthroughput = BATADV_THROUGHPUT_DEFAULT_VALUE;
100+
+ return true;
101+
}
102+
103+
/**
104+
@@ -169,15 +181,21 @@ void batadv_v_elp_throughput_metric_upda
105+
{
106+
struct batadv_hardif_neigh_node_bat_v *neigh_bat_v;
107+
struct batadv_hardif_neigh_node *neigh;
108+
+ u32 throughput;
109+
+ bool valid;
110+
111+
neigh_bat_v = container_of(work, struct batadv_hardif_neigh_node_bat_v,
112+
metric_work);
113+
neigh = container_of(neigh_bat_v, struct batadv_hardif_neigh_node,
114+
bat_v);
115+
116+
- ewma_throughput_add(&neigh->bat_v.throughput,
117+
- batadv_v_elp_get_throughput(neigh));
118+
+ valid = batadv_v_elp_get_throughput(neigh, &throughput);
119+
+ if (!valid)
120+
+ goto put_neigh;
121+
+
122+
+ ewma_throughput_add(&neigh->bat_v.throughput, throughput);
123+
124+
+put_neigh:
125+
/* decrement refcounter to balance increment performed before scheduling
126+
* this task
127+
*/

0 commit comments

Comments
 (0)