1 // SPDX-License-Identifier: GPL-2.0 1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (C) B.A.T.M.A.N. contributors: !! 2 /* Copyright (C) 2009-2020 B.A.T.M.A.N. contributors: 3 * 3 * 4 * Marek Lindner 4 * Marek Lindner 5 */ 5 */ 6 6 7 #include "gateway_common.h" 7 #include "gateway_common.h" 8 #include "main.h" 8 #include "main.h" 9 9 10 #include <linux/atomic.h> 10 #include <linux/atomic.h> 11 #include <linux/byteorder/generic.h> 11 #include <linux/byteorder/generic.h> >> 12 #include <linux/errno.h> >> 13 #include <linux/kernel.h> >> 14 #include <linux/limits.h> >> 15 #include <linux/math64.h> >> 16 #include <linux/netdevice.h> 12 #include <linux/stddef.h> 17 #include <linux/stddef.h> 13 #include <linux/types.h> !! 18 #include <linux/string.h> 14 #include <uapi/linux/batadv_packet.h> 19 #include <uapi/linux/batadv_packet.h> 15 #include <uapi/linux/batman_adv.h> 20 #include <uapi/linux/batman_adv.h> 16 21 17 #include "gateway_client.h" 22 #include "gateway_client.h" >> 23 #include "log.h" 18 #include "tvlv.h" 24 #include "tvlv.h" 19 25 20 /** 26 /** >> 27 * batadv_parse_throughput() - parse supplied string buffer to extract >> 28 * throughput information >> 29 * @net_dev: the soft interface net device >> 30 * @buff: string buffer to parse >> 31 * @description: text shown when throughput string cannot be parsed >> 32 * @throughput: pointer holding the returned throughput information >> 33 * >> 34 * Return: false on parse error and true otherwise. >> 35 */ >> 36 bool batadv_parse_throughput(struct net_device *net_dev, char *buff, >> 37 const char *description, u32 *throughput) >> 38 { >> 39 enum batadv_bandwidth_units bw_unit_type = BATADV_BW_UNIT_KBIT; >> 40 u64 lthroughput; >> 41 char *tmp_ptr; >> 42 int ret; >> 43 >> 44 if (strlen(buff) > 4) { >> 45 tmp_ptr = buff + strlen(buff) - 4; >> 46 >> 47 if (strncasecmp(tmp_ptr, "mbit", 4) == 0) >> 48 bw_unit_type = BATADV_BW_UNIT_MBIT; >> 49 >> 50 if (strncasecmp(tmp_ptr, "kbit", 4) == 0 || >> 51 bw_unit_type == BATADV_BW_UNIT_MBIT) >> 52 *tmp_ptr = '\0'; >> 53 } >> 54 >> 55 ret = kstrtou64(buff, 10, <hroughput); >> 56 if (ret) { >> 57 batadv_err(net_dev, >> 58 "Invalid throughput speed for %s: %s\n", >> 59 description, buff); >> 60 return false; >> 61 } >> 62 >> 63 switch (bw_unit_type) { >> 64 case BATADV_BW_UNIT_MBIT: >> 65 /* prevent overflow */ >> 66 if (U64_MAX / 10 < lthroughput) { >> 67 batadv_err(net_dev, >> 68 "Throughput speed for %s too large: %s\n", >> 69 description, buff); >> 70 return false; >> 71 } >> 72 >> 73 lthroughput *= 10; >> 74 break; >> 75 case BATADV_BW_UNIT_KBIT: >> 76 default: >> 77 lthroughput = div_u64(lthroughput, 100); >> 78 break; >> 79 } >> 80 >> 81 if (lthroughput > U32_MAX) { >> 82 batadv_err(net_dev, >> 83 "Throughput speed for %s too large: %s\n", >> 84 description, buff); >> 85 return false; >> 86 } >> 87 >> 88 *throughput = lthroughput; >> 89 >> 90 return true; >> 91 } >> 92 >> 93 /** >> 94 * batadv_parse_gw_bandwidth() - parse supplied string buffer to extract >> 95 * download and upload bandwidth information >> 96 * @net_dev: the soft interface net device >> 97 * @buff: string buffer to parse >> 98 * @down: pointer holding the returned download bandwidth information >> 99 * @up: pointer holding the returned upload bandwidth information >> 100 * >> 101 * Return: false on parse error and true otherwise. >> 102 */ >> 103 static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff, >> 104 u32 *down, u32 *up) >> 105 { >> 106 char *slash_ptr; >> 107 bool ret; >> 108 >> 109 slash_ptr = strchr(buff, '/'); >> 110 if (slash_ptr) >> 111 *slash_ptr = 0; >> 112 >> 113 ret = batadv_parse_throughput(net_dev, buff, "download gateway speed", >> 114 down); >> 115 if (!ret) >> 116 return false; >> 117 >> 118 /* we also got some upload info */ >> 119 if (slash_ptr) { >> 120 ret = batadv_parse_throughput(net_dev, slash_ptr + 1, >> 121 "upload gateway speed", up); >> 122 if (!ret) >> 123 return false; >> 124 } >> 125 >> 126 return true; >> 127 } >> 128 >> 129 /** 21 * batadv_gw_tvlv_container_update() - update 130 * batadv_gw_tvlv_container_update() - update the gw tvlv container after 22 * gateway setting change 131 * gateway setting change 23 * @bat_priv: the bat priv with all the soft i 132 * @bat_priv: the bat priv with all the soft interface information 24 */ 133 */ 25 void batadv_gw_tvlv_container_update(struct ba 134 void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv) 26 { 135 { 27 struct batadv_tvlv_gateway_data gw; 136 struct batadv_tvlv_gateway_data gw; 28 u32 down, up; 137 u32 down, up; 29 char gw_mode; 138 char gw_mode; 30 139 31 gw_mode = atomic_read(&bat_priv->gw.mo 140 gw_mode = atomic_read(&bat_priv->gw.mode); 32 141 33 switch (gw_mode) { 142 switch (gw_mode) { 34 case BATADV_GW_MODE_OFF: 143 case BATADV_GW_MODE_OFF: 35 case BATADV_GW_MODE_CLIENT: 144 case BATADV_GW_MODE_CLIENT: 36 batadv_tvlv_container_unregist 145 batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_GW, 1); 37 break; 146 break; 38 case BATADV_GW_MODE_SERVER: 147 case BATADV_GW_MODE_SERVER: 39 down = atomic_read(&bat_priv-> 148 down = atomic_read(&bat_priv->gw.bandwidth_down); 40 up = atomic_read(&bat_priv->gw 149 up = atomic_read(&bat_priv->gw.bandwidth_up); 41 gw.bandwidth_down = htonl(down 150 gw.bandwidth_down = htonl(down); 42 gw.bandwidth_up = htonl(up); 151 gw.bandwidth_up = htonl(up); 43 batadv_tvlv_container_register 152 batadv_tvlv_container_register(bat_priv, BATADV_TVLV_GW, 1, 44 153 &gw, sizeof(gw)); 45 break; 154 break; 46 } 155 } 47 } 156 } 48 157 49 /** 158 /** >> 159 * batadv_gw_bandwidth_set() - Parse and set download/upload gateway bandwidth >> 160 * from supplied string buffer >> 161 * @net_dev: netdev struct of the soft interface >> 162 * @buff: the buffer containing the user data >> 163 * @count: number of bytes in the buffer >> 164 * >> 165 * Return: 'count' on success or a negative error code in case of failure >> 166 */ >> 167 ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff, >> 168 size_t count) >> 169 { >> 170 struct batadv_priv *bat_priv = netdev_priv(net_dev); >> 171 u32 down_curr; >> 172 u32 up_curr; >> 173 u32 down_new = 0; >> 174 u32 up_new = 0; >> 175 bool ret; >> 176 >> 177 down_curr = (unsigned int)atomic_read(&bat_priv->gw.bandwidth_down); >> 178 up_curr = (unsigned int)atomic_read(&bat_priv->gw.bandwidth_up); >> 179 >> 180 ret = batadv_parse_gw_bandwidth(net_dev, buff, &down_new, &up_new); >> 181 if (!ret) >> 182 return -EINVAL; >> 183 >> 184 if (!down_new) >> 185 down_new = 1; >> 186 >> 187 if (!up_new) >> 188 up_new = down_new / 5; >> 189 >> 190 if (!up_new) >> 191 up_new = 1; >> 192 >> 193 if (down_curr == down_new && up_curr == up_new) >> 194 return count; >> 195 >> 196 batadv_gw_reselect(bat_priv); >> 197 batadv_info(net_dev, >> 198 "Changing gateway bandwidth from: '%u.%u/%u.%u MBit' to: '%u.%u/%u.%u MBit'\n", >> 199 down_curr / 10, down_curr % 10, up_curr / 10, up_curr % 10, >> 200 down_new / 10, down_new % 10, up_new / 10, up_new % 10); >> 201 >> 202 atomic_set(&bat_priv->gw.bandwidth_down, down_new); >> 203 atomic_set(&bat_priv->gw.bandwidth_up, up_new); >> 204 batadv_gw_tvlv_container_update(bat_priv); >> 205 >> 206 return count; >> 207 } >> 208 >> 209 /** 50 * batadv_gw_tvlv_ogm_handler_v1() - process i 210 * batadv_gw_tvlv_ogm_handler_v1() - process incoming gateway tvlv container 51 * @bat_priv: the bat priv with all the soft i 211 * @bat_priv: the bat priv with all the soft interface information 52 * @orig: the orig_node of the ogm 212 * @orig: the orig_node of the ogm 53 * @flags: flags indicating the tvlv state (se 213 * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags) 54 * @tvlv_value: tvlv buffer containing the gat 214 * @tvlv_value: tvlv buffer containing the gateway data 55 * @tvlv_value_len: tvlv buffer length 215 * @tvlv_value_len: tvlv buffer length 56 */ 216 */ 57 static void batadv_gw_tvlv_ogm_handler_v1(stru 217 static void batadv_gw_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, 58 stru 218 struct batadv_orig_node *orig, 59 u8 f 219 u8 flags, 60 void 220 void *tvlv_value, u16 tvlv_value_len) 61 { 221 { 62 struct batadv_tvlv_gateway_data gatewa 222 struct batadv_tvlv_gateway_data gateway, *gateway_ptr; 63 223 64 /* only fetch the tvlv value if the ha 224 /* only fetch the tvlv value if the handler wasn't called via the 65 * CIFNOTFND flag and if there is data 225 * CIFNOTFND flag and if there is data to fetch 66 */ 226 */ 67 if (flags & BATADV_TVLV_HANDLER_OGM_CI 227 if (flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND || 68 tvlv_value_len < sizeof(gateway)) 228 tvlv_value_len < sizeof(gateway)) { 69 gateway.bandwidth_down = 0; 229 gateway.bandwidth_down = 0; 70 gateway.bandwidth_up = 0; 230 gateway.bandwidth_up = 0; 71 } else { 231 } else { 72 gateway_ptr = tvlv_value; 232 gateway_ptr = tvlv_value; 73 gateway.bandwidth_down = gatew 233 gateway.bandwidth_down = gateway_ptr->bandwidth_down; 74 gateway.bandwidth_up = gateway 234 gateway.bandwidth_up = gateway_ptr->bandwidth_up; 75 if (gateway.bandwidth_down == 235 if (gateway.bandwidth_down == 0 || 76 gateway.bandwidth_up == 0) 236 gateway.bandwidth_up == 0) { 77 gateway.bandwidth_down 237 gateway.bandwidth_down = 0; 78 gateway.bandwidth_up = 238 gateway.bandwidth_up = 0; 79 } 239 } 80 } 240 } 81 241 82 batadv_gw_node_update(bat_priv, orig, 242 batadv_gw_node_update(bat_priv, orig, &gateway); 83 243 84 /* restart gateway selection */ 244 /* restart gateway selection */ 85 if (gateway.bandwidth_down != 0 && 245 if (gateway.bandwidth_down != 0 && 86 atomic_read(&bat_priv->gw.mode) == 246 atomic_read(&bat_priv->gw.mode) == BATADV_GW_MODE_CLIENT) 87 batadv_gw_check_election(bat_p 247 batadv_gw_check_election(bat_priv, orig); 88 } 248 } 89 249 90 /** 250 /** 91 * batadv_gw_init() - initialise the gateway h 251 * batadv_gw_init() - initialise the gateway handling internals 92 * @bat_priv: the bat priv with all the soft i 252 * @bat_priv: the bat priv with all the soft interface information 93 */ 253 */ 94 void batadv_gw_init(struct batadv_priv *bat_pr 254 void batadv_gw_init(struct batadv_priv *bat_priv) 95 { 255 { 96 if (bat_priv->algo_ops->gw.init_sel_cl 256 if (bat_priv->algo_ops->gw.init_sel_class) 97 bat_priv->algo_ops->gw.init_se 257 bat_priv->algo_ops->gw.init_sel_class(bat_priv); 98 else 258 else 99 atomic_set(&bat_priv->gw.sel_c 259 atomic_set(&bat_priv->gw.sel_class, 1); 100 260 101 batadv_tvlv_handler_register(bat_priv, 261 batadv_tvlv_handler_register(bat_priv, batadv_gw_tvlv_ogm_handler_v1, 102 NULL, NUL !! 262 NULL, BATADV_TVLV_GW, 1, 103 BATADV_TV 263 BATADV_TVLV_HANDLER_OGM_CIFNOTFND); 104 } 264 } 105 265 106 /** 266 /** 107 * batadv_gw_free() - free the gateway handlin 267 * batadv_gw_free() - free the gateway handling internals 108 * @bat_priv: the bat priv with all the soft i 268 * @bat_priv: the bat priv with all the soft interface information 109 */ 269 */ 110 void batadv_gw_free(struct batadv_priv *bat_pr 270 void batadv_gw_free(struct batadv_priv *bat_priv) 111 { 271 { 112 batadv_tvlv_container_unregister(bat_p 272 batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_GW, 1); 113 batadv_tvlv_handler_unregister(bat_pri 273 batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_GW, 1); 114 } 274 } 115 275
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.