Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

batman-adv: Ignore neighbor throughput metrics in error case

If a temporary error happened in the evaluation of the neighbor throughput
information, then the invalid throughput result should not be stored in the
throughtput EWMA.

Cc: stable@vger.kernel.org
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>

authored by

Sven Eckelmann and committed by
Simon Wunderlich
e7e34ffc ccb7276a

+34 -16
+34 -16
net/batman-adv/bat_v_elp.c
··· 59 59 /** 60 60 * batadv_v_elp_get_throughput() - get the throughput towards a neighbour 61 61 * @neigh: the neighbour for which the throughput has to be obtained 62 + * @pthroughput: calculated throughput towards the given neighbour in multiples 63 + * of 100kpbs (a value of '1' equals 0.1Mbps, '10' equals 1Mbps, etc). 62 64 * 63 - * Return: The throughput towards the given neighbour in multiples of 100kpbs 64 - * (a value of '1' equals 0.1Mbps, '10' equals 1Mbps, etc). 65 + * Return: true when value behind @pthroughput was set 65 66 */ 66 - static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh) 67 + static bool batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh, 68 + u32 *pthroughput) 67 69 { 68 70 struct batadv_hard_iface *hard_iface = neigh->if_incoming; 69 71 struct net_device *soft_iface = hard_iface->soft_iface; ··· 79 77 * batman-adv interface 80 78 */ 81 79 if (!soft_iface) 82 - return BATADV_THROUGHPUT_DEFAULT_VALUE; 80 + return false; 83 81 84 82 /* if the user specified a customised value for this interface, then 85 83 * return it directly 86 84 */ 87 85 throughput = atomic_read(&hard_iface->bat_v.throughput_override); 88 - if (throughput != 0) 89 - return throughput; 86 + if (throughput != 0) { 87 + *pthroughput = throughput; 88 + return true; 89 + } 90 90 91 91 /* if this is a wireless device, then ask its throughput through 92 92 * cfg80211 API ··· 115 111 * possible to delete this neighbor. For now set 116 112 * the throughput metric to 0. 117 113 */ 118 - return 0; 114 + *pthroughput = 0; 115 + return true; 119 116 } 120 117 if (ret) 121 118 goto default_throughput; 122 119 123 - if (sinfo.filled & BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT)) 124 - return sinfo.expected_throughput / 100; 120 + if (sinfo.filled & BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT)) { 121 + *pthroughput = sinfo.expected_throughput / 100; 122 + return true; 123 + } 125 124 126 125 /* try to estimate the expected throughput based on reported tx 127 126 * rates 128 127 */ 129 - if (sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE)) 130 - return cfg80211_calculate_bitrate(&sinfo.txrate) / 3; 128 + if (sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE)) { 129 + *pthroughput = cfg80211_calculate_bitrate(&sinfo.txrate) / 3; 130 + return true; 131 + } 131 132 132 133 goto default_throughput; 133 134 } ··· 151 142 hard_iface->bat_v.flags &= ~BATADV_FULL_DUPLEX; 152 143 153 144 throughput = link_settings.base.speed; 154 - if (throughput && throughput != SPEED_UNKNOWN) 155 - return throughput * 10; 145 + if (throughput && throughput != SPEED_UNKNOWN) { 146 + *pthroughput = throughput * 10; 147 + return true; 148 + } 156 149 } 157 150 158 151 default_throughput: ··· 168 157 } 169 158 170 159 /* if none of the above cases apply, return the base_throughput */ 171 - return BATADV_THROUGHPUT_DEFAULT_VALUE; 160 + *pthroughput = BATADV_THROUGHPUT_DEFAULT_VALUE; 161 + return true; 172 162 } 173 163 174 164 /** ··· 181 169 { 182 170 struct batadv_hardif_neigh_node_bat_v *neigh_bat_v; 183 171 struct batadv_hardif_neigh_node *neigh; 172 + u32 throughput; 173 + bool valid; 184 174 185 175 neigh_bat_v = container_of(work, struct batadv_hardif_neigh_node_bat_v, 186 176 metric_work); 187 177 neigh = container_of(neigh_bat_v, struct batadv_hardif_neigh_node, 188 178 bat_v); 189 179 190 - ewma_throughput_add(&neigh->bat_v.throughput, 191 - batadv_v_elp_get_throughput(neigh)); 180 + valid = batadv_v_elp_get_throughput(neigh, &throughput); 181 + if (!valid) 182 + goto put_neigh; 192 183 184 + ewma_throughput_add(&neigh->bat_v.throughput, throughput); 185 + 186 + put_neigh: 193 187 /* decrement refcounter to balance increment performed before scheduling 194 188 * this task 195 189 */