gateway_common.c 7.8 KB

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