sysfs.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright (C) 2010-2020 B.A.T.M.A.N. contributors:
  3. *
  4. * Marek Lindner
  5. */
  6. #include "sysfs.h"
  7. #include "main.h"
  8. #include <asm/current.h>
  9. #include <linux/atomic.h>
  10. #include <linux/compiler.h>
  11. #include <linux/device.h>
  12. #include <linux/errno.h>
  13. #include <linux/gfp.h>
  14. #include <linux/if.h>
  15. #include <linux/if_vlan.h>
  16. #include <linux/kernel.h>
  17. #include <linux/kobject.h>
  18. #include <linux/kref.h>
  19. #include <linux/limits.h>
  20. #include <linux/netdevice.h>
  21. #include <linux/printk.h>
  22. #include <linux/rculist.h>
  23. #include <linux/rcupdate.h>
  24. #include <linux/rtnetlink.h>
  25. #include <linux/sched.h>
  26. #include <linux/slab.h>
  27. #include <linux/stddef.h>
  28. #include <linux/string.h>
  29. #include <linux/stringify.h>
  30. #include <linux/workqueue.h>
  31. #include <uapi/linux/batadv_packet.h>
  32. #include <uapi/linux/batman_adv.h>
  33. #include "bridge_loop_avoidance.h"
  34. #include "distributed-arp-table.h"
  35. #include "gateway_client.h"
  36. #include "gateway_common.h"
  37. #include "hard-interface.h"
  38. #include "log.h"
  39. #include "netlink.h"
  40. #include "network-coding.h"
  41. #include "soft-interface.h"
  42. /**
  43. * batadv_sysfs_deprecated() - Log use of deprecated batadv sysfs access
  44. * @attr: attribute which was accessed
  45. */
  46. static void batadv_sysfs_deprecated(struct attribute *attr)
  47. {
  48. pr_warn_ratelimited(DEPRECATED "%s (pid %d) Use of sysfs file \"%s\".\nUse batadv genl family instead",
  49. current->comm, task_pid_nr(current), attr->name);
  50. }
  51. static struct net_device *batadv_kobj_to_netdev(struct kobject *obj)
  52. {
  53. struct device *dev = container_of(obj->parent, struct device, kobj);
  54. return to_net_dev(dev);
  55. }
  56. static struct batadv_priv *batadv_kobj_to_batpriv(struct kobject *obj)
  57. {
  58. struct net_device *net_dev = batadv_kobj_to_netdev(obj);
  59. return netdev_priv(net_dev);
  60. }
  61. /**
  62. * batadv_vlan_kobj_to_batpriv() - convert a vlan kobj in the associated batpriv
  63. * @obj: kobject to covert
  64. *
  65. * Return: the associated batadv_priv struct.
  66. */
  67. static struct batadv_priv *batadv_vlan_kobj_to_batpriv(struct kobject *obj)
  68. {
  69. /* VLAN specific attributes are located in the root sysfs folder if they
  70. * refer to the untagged VLAN..
  71. */
  72. if (!strcmp(BATADV_SYSFS_IF_MESH_SUBDIR, obj->name))
  73. return batadv_kobj_to_batpriv(obj);
  74. /* ..while the attributes for the tagged vlans are located in
  75. * the in the corresponding "vlan%VID" subfolder
  76. */
  77. return batadv_kobj_to_batpriv(obj->parent);
  78. }
  79. /**
  80. * batadv_kobj_to_vlan() - convert a kobj in the associated softif_vlan struct
  81. * @bat_priv: the bat priv with all the soft interface information
  82. * @obj: kobject to covert
  83. *
  84. * Return: the associated softif_vlan struct if found, NULL otherwise.
  85. */
  86. static struct batadv_softif_vlan *
  87. batadv_kobj_to_vlan(struct batadv_priv *bat_priv, struct kobject *obj)
  88. {
  89. struct batadv_softif_vlan *vlan_tmp, *vlan = NULL;
  90. rcu_read_lock();
  91. hlist_for_each_entry_rcu(vlan_tmp, &bat_priv->softif_vlan_list, list) {
  92. if (vlan_tmp->kobj != obj)
  93. continue;
  94. if (!kref_get_unless_zero(&vlan_tmp->refcount))
  95. continue;
  96. vlan = vlan_tmp;
  97. break;
  98. }
  99. rcu_read_unlock();
  100. return vlan;
  101. }
  102. /* Use this, if you have customized show and store functions for vlan attrs */
  103. #define BATADV_ATTR_VLAN(_name, _mode, _show, _store) \
  104. struct batadv_attribute batadv_attr_vlan_##_name = { \
  105. .attr = {.name = __stringify(_name), \
  106. .mode = _mode }, \
  107. .show = _show, \
  108. .store = _store, \
  109. }
  110. /* Use this, if you have customized show and store functions */
  111. #define BATADV_ATTR(_name, _mode, _show, _store) \
  112. struct batadv_attribute batadv_attr_##_name = { \
  113. .attr = {.name = __stringify(_name), \
  114. .mode = _mode }, \
  115. .show = _show, \
  116. .store = _store, \
  117. }
  118. #define BATADV_ATTR_SIF_STORE_BOOL(_name, _post_func) \
  119. ssize_t batadv_store_##_name(struct kobject *kobj, \
  120. struct attribute *attr, char *buff, \
  121. size_t count) \
  122. { \
  123. struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \
  124. struct batadv_priv *bat_priv = netdev_priv(net_dev); \
  125. ssize_t length; \
  126. \
  127. batadv_sysfs_deprecated(attr); \
  128. length = __batadv_store_bool_attr(buff, count, _post_func, attr,\
  129. &bat_priv->_name, net_dev); \
  130. \
  131. batadv_netlink_notify_mesh(bat_priv); \
  132. \
  133. return length; \
  134. }
  135. #define BATADV_ATTR_SIF_SHOW_BOOL(_name) \
  136. ssize_t batadv_show_##_name(struct kobject *kobj, \
  137. struct attribute *attr, char *buff) \
  138. { \
  139. struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); \
  140. \
  141. batadv_sysfs_deprecated(attr); \
  142. return sprintf(buff, "%s\n", \
  143. atomic_read(&bat_priv->_name) == 0 ? \
  144. "disabled" : "enabled"); \
  145. } \
  146. /* Use this, if you are going to turn a [name] in the soft-interface
  147. * (bat_priv) on or off
  148. */
  149. #define BATADV_ATTR_SIF_BOOL(_name, _mode, _post_func) \
  150. static BATADV_ATTR_SIF_STORE_BOOL(_name, _post_func) \
  151. static BATADV_ATTR_SIF_SHOW_BOOL(_name) \
  152. static BATADV_ATTR(_name, _mode, batadv_show_##_name, \
  153. batadv_store_##_name)
  154. #define BATADV_ATTR_SIF_STORE_UINT(_name, _var, _min, _max, _post_func) \
  155. ssize_t batadv_store_##_name(struct kobject *kobj, \
  156. struct attribute *attr, char *buff, \
  157. size_t count) \
  158. { \
  159. struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \
  160. struct batadv_priv *bat_priv = netdev_priv(net_dev); \
  161. ssize_t length; \
  162. \
  163. batadv_sysfs_deprecated(attr); \
  164. length = __batadv_store_uint_attr(buff, count, _min, _max, \
  165. _post_func, attr, \
  166. &bat_priv->_var, net_dev, \
  167. NULL); \
  168. \
  169. batadv_netlink_notify_mesh(bat_priv); \
  170. \
  171. return length; \
  172. }
  173. #define BATADV_ATTR_SIF_SHOW_UINT(_name, _var) \
  174. ssize_t batadv_show_##_name(struct kobject *kobj, \
  175. struct attribute *attr, char *buff) \
  176. { \
  177. struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); \
  178. \
  179. batadv_sysfs_deprecated(attr); \
  180. return sprintf(buff, "%i\n", atomic_read(&bat_priv->_var)); \
  181. } \
  182. /* Use this, if you are going to set [name] in the soft-interface
  183. * (bat_priv) to an unsigned integer value
  184. */
  185. #define BATADV_ATTR_SIF_UINT(_name, _var, _mode, _min, _max, _post_func)\
  186. static BATADV_ATTR_SIF_STORE_UINT(_name, _var, _min, _max, _post_func)\
  187. static BATADV_ATTR_SIF_SHOW_UINT(_name, _var) \
  188. static BATADV_ATTR(_name, _mode, batadv_show_##_name, \
  189. batadv_store_##_name)
  190. #define BATADV_ATTR_VLAN_STORE_BOOL(_name, _post_func) \
  191. ssize_t batadv_store_vlan_##_name(struct kobject *kobj, \
  192. struct attribute *attr, char *buff, \
  193. size_t count) \
  194. { \
  195. struct batadv_priv *bat_priv = batadv_vlan_kobj_to_batpriv(kobj);\
  196. struct batadv_softif_vlan *vlan = batadv_kobj_to_vlan(bat_priv, \
  197. kobj); \
  198. size_t res = __batadv_store_bool_attr(buff, count, _post_func, \
  199. attr, &vlan->_name, \
  200. bat_priv->soft_iface); \
  201. \
  202. batadv_sysfs_deprecated(attr); \
  203. if (vlan->vid) \
  204. batadv_netlink_notify_vlan(bat_priv, vlan); \
  205. else \
  206. batadv_netlink_notify_mesh(bat_priv); \
  207. \
  208. batadv_softif_vlan_put(vlan); \
  209. return res; \
  210. }
  211. #define BATADV_ATTR_VLAN_SHOW_BOOL(_name) \
  212. ssize_t batadv_show_vlan_##_name(struct kobject *kobj, \
  213. struct attribute *attr, char *buff) \
  214. { \
  215. struct batadv_priv *bat_priv = batadv_vlan_kobj_to_batpriv(kobj);\
  216. struct batadv_softif_vlan *vlan = batadv_kobj_to_vlan(bat_priv, \
  217. kobj); \
  218. size_t res = sprintf(buff, "%s\n", \
  219. atomic_read(&vlan->_name) == 0 ? \
  220. "disabled" : "enabled"); \
  221. \
  222. batadv_sysfs_deprecated(attr); \
  223. batadv_softif_vlan_put(vlan); \
  224. return res; \
  225. }
  226. /* Use this, if you are going to turn a [name] in the vlan struct on or off */
  227. #define BATADV_ATTR_VLAN_BOOL(_name, _mode, _post_func) \
  228. static BATADV_ATTR_VLAN_STORE_BOOL(_name, _post_func) \
  229. static BATADV_ATTR_VLAN_SHOW_BOOL(_name) \
  230. static BATADV_ATTR_VLAN(_name, _mode, batadv_show_vlan_##_name, \
  231. batadv_store_vlan_##_name)
  232. #define BATADV_ATTR_HIF_STORE_UINT(_name, _var, _min, _max, _post_func) \
  233. ssize_t batadv_store_##_name(struct kobject *kobj, \
  234. struct attribute *attr, char *buff, \
  235. size_t count) \
  236. { \
  237. struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \
  238. struct batadv_hard_iface *hard_iface; \
  239. struct batadv_priv *bat_priv; \
  240. ssize_t length; \
  241. \
  242. batadv_sysfs_deprecated(attr); \
  243. hard_iface = batadv_hardif_get_by_netdev(net_dev); \
  244. if (!hard_iface) \
  245. return 0; \
  246. \
  247. length = __batadv_store_uint_attr(buff, count, _min, _max, \
  248. _post_func, attr, \
  249. &hard_iface->_var, \
  250. hard_iface->soft_iface, \
  251. net_dev); \
  252. \
  253. if (hard_iface->soft_iface) { \
  254. bat_priv = netdev_priv(hard_iface->soft_iface); \
  255. batadv_netlink_notify_hardif(bat_priv, hard_iface); \
  256. } \
  257. \
  258. batadv_hardif_put(hard_iface); \
  259. return length; \
  260. }
  261. #define BATADV_ATTR_HIF_SHOW_UINT(_name, _var) \
  262. ssize_t batadv_show_##_name(struct kobject *kobj, \
  263. struct attribute *attr, char *buff) \
  264. { \
  265. struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \
  266. struct batadv_hard_iface *hard_iface; \
  267. ssize_t length; \
  268. \
  269. batadv_sysfs_deprecated(attr); \
  270. hard_iface = batadv_hardif_get_by_netdev(net_dev); \
  271. if (!hard_iface) \
  272. return 0; \
  273. \
  274. length = sprintf(buff, "%i\n", atomic_read(&hard_iface->_var)); \
  275. \
  276. batadv_hardif_put(hard_iface); \
  277. return length; \
  278. }
  279. /* Use this, if you are going to set [name] in hard_iface to an
  280. * unsigned integer value
  281. */
  282. #define BATADV_ATTR_HIF_UINT(_name, _var, _mode, _min, _max, _post_func)\
  283. static BATADV_ATTR_HIF_STORE_UINT(_name, _var, _min, \
  284. _max, _post_func) \
  285. static BATADV_ATTR_HIF_SHOW_UINT(_name, _var) \
  286. static BATADV_ATTR(_name, _mode, batadv_show_##_name, \
  287. batadv_store_##_name)
  288. static int batadv_store_bool_attr(char *buff, size_t count,
  289. struct net_device *net_dev,
  290. const char *attr_name, atomic_t *attr,
  291. bool *changed)
  292. {
  293. int enabled = -1;
  294. *changed = false;
  295. if (buff[count - 1] == '\n')
  296. buff[count - 1] = '\0';
  297. if ((strncmp(buff, "1", 2) == 0) ||
  298. (strncmp(buff, "enable", 7) == 0) ||
  299. (strncmp(buff, "enabled", 8) == 0))
  300. enabled = 1;
  301. if ((strncmp(buff, "0", 2) == 0) ||
  302. (strncmp(buff, "disable", 8) == 0) ||
  303. (strncmp(buff, "disabled", 9) == 0))
  304. enabled = 0;
  305. if (enabled < 0) {
  306. batadv_info(net_dev, "%s: Invalid parameter received: %s\n",
  307. attr_name, buff);
  308. return -EINVAL;
  309. }
  310. if (atomic_read(attr) == enabled)
  311. return count;
  312. batadv_info(net_dev, "%s: Changing from: %s to: %s\n", attr_name,
  313. atomic_read(attr) == 1 ? "enabled" : "disabled",
  314. enabled == 1 ? "enabled" : "disabled");
  315. *changed = true;
  316. atomic_set(attr, (unsigned int)enabled);
  317. return count;
  318. }
  319. static inline ssize_t
  320. __batadv_store_bool_attr(char *buff, size_t count,
  321. void (*post_func)(struct net_device *),
  322. struct attribute *attr,
  323. atomic_t *attr_store, struct net_device *net_dev)
  324. {
  325. bool changed;
  326. int ret;
  327. ret = batadv_store_bool_attr(buff, count, net_dev, attr->name,
  328. attr_store, &changed);
  329. if (post_func && changed)
  330. post_func(net_dev);
  331. return ret;
  332. }
  333. static int batadv_store_uint_attr(const char *buff, size_t count,
  334. struct net_device *net_dev,
  335. struct net_device *slave_dev,
  336. const char *attr_name,
  337. unsigned int min, unsigned int max,
  338. atomic_t *attr)
  339. {
  340. char ifname[IFNAMSIZ + 3] = "";
  341. unsigned long uint_val;
  342. int ret;
  343. ret = kstrtoul(buff, 10, &uint_val);
  344. if (ret) {
  345. batadv_info(net_dev, "%s: Invalid parameter received: %s\n",
  346. attr_name, buff);
  347. return -EINVAL;
  348. }
  349. if (uint_val < min) {
  350. batadv_info(net_dev, "%s: Value is too small: %lu min: %u\n",
  351. attr_name, uint_val, min);
  352. return -EINVAL;
  353. }
  354. if (uint_val > max) {
  355. batadv_info(net_dev, "%s: Value is too big: %lu max: %u\n",
  356. attr_name, uint_val, max);
  357. return -EINVAL;
  358. }
  359. if (atomic_read(attr) == uint_val)
  360. return count;
  361. if (slave_dev)
  362. snprintf(ifname, sizeof(ifname), "%s: ", slave_dev->name);
  363. batadv_info(net_dev, "%s: %sChanging from: %i to: %lu\n",
  364. attr_name, ifname, atomic_read(attr), uint_val);
  365. atomic_set(attr, uint_val);
  366. return count;
  367. }
  368. static ssize_t __batadv_store_uint_attr(const char *buff, size_t count,
  369. int min, int max,
  370. void (*post_func)(struct net_device *),
  371. const struct attribute *attr,
  372. atomic_t *attr_store,
  373. struct net_device *net_dev,
  374. struct net_device *slave_dev)
  375. {
  376. int ret;
  377. ret = batadv_store_uint_attr(buff, count, net_dev, slave_dev,
  378. attr->name, min, max, attr_store);
  379. if (post_func && ret)
  380. post_func(net_dev);
  381. return ret;
  382. }
  383. static ssize_t batadv_show_bat_algo(struct kobject *kobj,
  384. struct attribute *attr, char *buff)
  385. {
  386. struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
  387. batadv_sysfs_deprecated(attr);
  388. return sprintf(buff, "%s\n", bat_priv->algo_ops->name);
  389. }
  390. static void batadv_post_gw_reselect(struct net_device *net_dev)
  391. {
  392. struct batadv_priv *bat_priv = netdev_priv(net_dev);
  393. batadv_gw_reselect(bat_priv);
  394. }
  395. static ssize_t batadv_show_gw_mode(struct kobject *kobj, struct attribute *attr,
  396. char *buff)
  397. {
  398. struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
  399. int bytes_written;
  400. batadv_sysfs_deprecated(attr);
  401. /* GW mode is not available if the routing algorithm in use does not
  402. * implement the GW API
  403. */
  404. if (!bat_priv->algo_ops->gw.get_best_gw_node ||
  405. !bat_priv->algo_ops->gw.is_eligible)
  406. return -ENOENT;
  407. switch (atomic_read(&bat_priv->gw.mode)) {
  408. case BATADV_GW_MODE_CLIENT:
  409. bytes_written = sprintf(buff, "%s\n",
  410. BATADV_GW_MODE_CLIENT_NAME);
  411. break;
  412. case BATADV_GW_MODE_SERVER:
  413. bytes_written = sprintf(buff, "%s\n",
  414. BATADV_GW_MODE_SERVER_NAME);
  415. break;
  416. default:
  417. bytes_written = sprintf(buff, "%s\n",
  418. BATADV_GW_MODE_OFF_NAME);
  419. break;
  420. }
  421. return bytes_written;
  422. }
  423. static ssize_t batadv_store_gw_mode(struct kobject *kobj,
  424. struct attribute *attr, char *buff,
  425. size_t count)
  426. {
  427. struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
  428. struct batadv_priv *bat_priv = netdev_priv(net_dev);
  429. char *curr_gw_mode_str;
  430. int gw_mode_tmp = -1;
  431. batadv_sysfs_deprecated(attr);
  432. /* toggling GW mode is allowed only if the routing algorithm in use
  433. * provides the GW API
  434. */
  435. if (!bat_priv->algo_ops->gw.get_best_gw_node ||
  436. !bat_priv->algo_ops->gw.is_eligible)
  437. return -EINVAL;
  438. if (buff[count - 1] == '\n')
  439. buff[count - 1] = '\0';
  440. if (strncmp(buff, BATADV_GW_MODE_OFF_NAME,
  441. strlen(BATADV_GW_MODE_OFF_NAME)) == 0)
  442. gw_mode_tmp = BATADV_GW_MODE_OFF;
  443. if (strncmp(buff, BATADV_GW_MODE_CLIENT_NAME,
  444. strlen(BATADV_GW_MODE_CLIENT_NAME)) == 0)
  445. gw_mode_tmp = BATADV_GW_MODE_CLIENT;
  446. if (strncmp(buff, BATADV_GW_MODE_SERVER_NAME,
  447. strlen(BATADV_GW_MODE_SERVER_NAME)) == 0)
  448. gw_mode_tmp = BATADV_GW_MODE_SERVER;
  449. if (gw_mode_tmp < 0) {
  450. batadv_info(net_dev,
  451. "Invalid parameter for 'gw mode' setting received: %s\n",
  452. buff);
  453. return -EINVAL;
  454. }
  455. if (atomic_read(&bat_priv->gw.mode) == gw_mode_tmp)
  456. return count;
  457. switch (atomic_read(&bat_priv->gw.mode)) {
  458. case BATADV_GW_MODE_CLIENT:
  459. curr_gw_mode_str = BATADV_GW_MODE_CLIENT_NAME;
  460. break;
  461. case BATADV_GW_MODE_SERVER:
  462. curr_gw_mode_str = BATADV_GW_MODE_SERVER_NAME;
  463. break;
  464. default:
  465. curr_gw_mode_str = BATADV_GW_MODE_OFF_NAME;
  466. break;
  467. }
  468. batadv_info(net_dev, "Changing gw mode from: %s to: %s\n",
  469. curr_gw_mode_str, buff);
  470. /* Invoking batadv_gw_reselect() is not enough to really de-select the
  471. * current GW. It will only instruct the gateway client code to perform
  472. * a re-election the next time that this is needed.
  473. *
  474. * When gw client mode is being switched off the current GW must be
  475. * de-selected explicitly otherwise no GW_ADD uevent is thrown on
  476. * client mode re-activation. This is operation is performed in
  477. * batadv_gw_check_client_stop().
  478. */
  479. batadv_gw_reselect(bat_priv);
  480. /* always call batadv_gw_check_client_stop() before changing the gateway
  481. * state
  482. */
  483. batadv_gw_check_client_stop(bat_priv);
  484. atomic_set(&bat_priv->gw.mode, (unsigned int)gw_mode_tmp);
  485. batadv_gw_tvlv_container_update(bat_priv);
  486. batadv_netlink_notify_mesh(bat_priv);
  487. return count;
  488. }
  489. static ssize_t batadv_show_gw_sel_class(struct kobject *kobj,
  490. struct attribute *attr, char *buff)
  491. {
  492. struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
  493. batadv_sysfs_deprecated(attr);
  494. /* GW selection class is not available if the routing algorithm in use
  495. * does not implement the GW API
  496. */
  497. if (!bat_priv->algo_ops->gw.get_best_gw_node ||
  498. !bat_priv->algo_ops->gw.is_eligible)
  499. return -ENOENT;
  500. if (bat_priv->algo_ops->gw.show_sel_class)
  501. return bat_priv->algo_ops->gw.show_sel_class(bat_priv, buff);
  502. return sprintf(buff, "%i\n", atomic_read(&bat_priv->gw.sel_class));
  503. }
  504. static ssize_t batadv_store_gw_sel_class(struct kobject *kobj,
  505. struct attribute *attr, char *buff,
  506. size_t count)
  507. {
  508. struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
  509. ssize_t length;
  510. batadv_sysfs_deprecated(attr);
  511. /* setting the GW selection class is allowed only if the routing
  512. * algorithm in use implements the GW API
  513. */
  514. if (!bat_priv->algo_ops->gw.get_best_gw_node ||
  515. !bat_priv->algo_ops->gw.is_eligible)
  516. return -EINVAL;
  517. if (buff[count - 1] == '\n')
  518. buff[count - 1] = '\0';
  519. if (bat_priv->algo_ops->gw.store_sel_class)
  520. return bat_priv->algo_ops->gw.store_sel_class(bat_priv, buff,
  521. count);
  522. length = __batadv_store_uint_attr(buff, count, 1, BATADV_TQ_MAX_VALUE,
  523. batadv_post_gw_reselect, attr,
  524. &bat_priv->gw.sel_class,
  525. bat_priv->soft_iface, NULL);
  526. batadv_netlink_notify_mesh(bat_priv);
  527. return length;
  528. }
  529. static ssize_t batadv_show_gw_bwidth(struct kobject *kobj,
  530. struct attribute *attr, char *buff)
  531. {
  532. struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
  533. u32 down, up;
  534. batadv_sysfs_deprecated(attr);
  535. down = atomic_read(&bat_priv->gw.bandwidth_down);
  536. up = atomic_read(&bat_priv->gw.bandwidth_up);
  537. return sprintf(buff, "%u.%u/%u.%u MBit\n", down / 10,
  538. down % 10, up / 10, up % 10);
  539. }
  540. static ssize_t batadv_store_gw_bwidth(struct kobject *kobj,
  541. struct attribute *attr, char *buff,
  542. size_t count)
  543. {
  544. struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
  545. struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
  546. ssize_t length;
  547. batadv_sysfs_deprecated(attr);
  548. if (buff[count - 1] == '\n')
  549. buff[count - 1] = '\0';
  550. length = batadv_gw_bandwidth_set(net_dev, buff, count);
  551. batadv_netlink_notify_mesh(bat_priv);
  552. return length;
  553. }
  554. /**
  555. * batadv_show_isolation_mark() - print the current isolation mark/mask
  556. * @kobj: kobject representing the private mesh sysfs directory
  557. * @attr: the batman-adv attribute the user is interacting with
  558. * @buff: the buffer that will contain the data to send back to the user
  559. *
  560. * Return: the number of bytes written into 'buff' on success or a negative
  561. * error code in case of failure
  562. */
  563. static ssize_t batadv_show_isolation_mark(struct kobject *kobj,
  564. struct attribute *attr, char *buff)
  565. {
  566. struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
  567. batadv_sysfs_deprecated(attr);
  568. return sprintf(buff, "%#.8x/%#.8x\n", bat_priv->isolation_mark,
  569. bat_priv->isolation_mark_mask);
  570. }
  571. /**
  572. * batadv_store_isolation_mark() - parse and store the isolation mark/mask
  573. * entered by the user
  574. * @kobj: kobject representing the private mesh sysfs directory
  575. * @attr: the batman-adv attribute the user is interacting with
  576. * @buff: the buffer containing the user data
  577. * @count: number of bytes in the buffer
  578. *
  579. * Return: 'count' on success or a negative error code in case of failure
  580. */
  581. static ssize_t batadv_store_isolation_mark(struct kobject *kobj,
  582. struct attribute *attr, char *buff,
  583. size_t count)
  584. {
  585. struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
  586. struct batadv_priv *bat_priv = netdev_priv(net_dev);
  587. u32 mark, mask;
  588. char *mask_ptr;
  589. batadv_sysfs_deprecated(attr);
  590. /* parse the mask if it has been specified, otherwise assume the mask is
  591. * the biggest possible
  592. */
  593. mask = 0xFFFFFFFF;
  594. mask_ptr = strchr(buff, '/');
  595. if (mask_ptr) {
  596. *mask_ptr = '\0';
  597. mask_ptr++;
  598. /* the mask must be entered in hex base as it is going to be a
  599. * bitmask and not a prefix length
  600. */
  601. if (kstrtou32(mask_ptr, 16, &mask) < 0)
  602. return -EINVAL;
  603. }
  604. /* the mark can be entered in any base */
  605. if (kstrtou32(buff, 0, &mark) < 0)
  606. return -EINVAL;
  607. bat_priv->isolation_mark_mask = mask;
  608. /* erase bits not covered by the mask */
  609. bat_priv->isolation_mark = mark & bat_priv->isolation_mark_mask;
  610. batadv_info(net_dev,
  611. "New skb mark for extended isolation: %#.8x/%#.8x\n",
  612. bat_priv->isolation_mark, bat_priv->isolation_mark_mask);
  613. batadv_netlink_notify_mesh(bat_priv);
  614. return count;
  615. }
  616. BATADV_ATTR_SIF_BOOL(aggregated_ogms, 0644, NULL);
  617. BATADV_ATTR_SIF_BOOL(bonding, 0644, NULL);
  618. #ifdef CONFIG_BATMAN_ADV_BLA
  619. BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, 0644, batadv_bla_status_update);
  620. #endif
  621. #ifdef CONFIG_BATMAN_ADV_DAT
  622. BATADV_ATTR_SIF_BOOL(distributed_arp_table, 0644, batadv_dat_status_update);
  623. #endif
  624. BATADV_ATTR_SIF_BOOL(fragmentation, 0644, batadv_update_min_mtu);
  625. static BATADV_ATTR(routing_algo, 0444, batadv_show_bat_algo, NULL);
  626. static BATADV_ATTR(gw_mode, 0644, batadv_show_gw_mode, batadv_store_gw_mode);
  627. BATADV_ATTR_SIF_UINT(orig_interval, orig_interval, 0644, 2 * BATADV_JITTER,
  628. INT_MAX, NULL);
  629. BATADV_ATTR_SIF_UINT(hop_penalty, hop_penalty, 0644, 0, BATADV_TQ_MAX_VALUE,
  630. NULL);
  631. static BATADV_ATTR(gw_sel_class, 0644, batadv_show_gw_sel_class,
  632. batadv_store_gw_sel_class);
  633. static BATADV_ATTR(gw_bandwidth, 0644, batadv_show_gw_bwidth,
  634. batadv_store_gw_bwidth);
  635. #ifdef CONFIG_BATMAN_ADV_MCAST
  636. BATADV_ATTR_SIF_BOOL(multicast_mode, 0644, NULL);
  637. #endif
  638. #ifdef CONFIG_BATMAN_ADV_DEBUG
  639. BATADV_ATTR_SIF_UINT(log_level, log_level, 0644, 0, BATADV_DBG_ALL, NULL);
  640. #endif
  641. #ifdef CONFIG_BATMAN_ADV_NC
  642. BATADV_ATTR_SIF_BOOL(network_coding, 0644, batadv_nc_status_update);
  643. #endif
  644. static BATADV_ATTR(isolation_mark, 0644, batadv_show_isolation_mark,
  645. batadv_store_isolation_mark);
  646. static struct batadv_attribute *batadv_mesh_attrs[] = {
  647. &batadv_attr_aggregated_ogms,
  648. &batadv_attr_bonding,
  649. #ifdef CONFIG_BATMAN_ADV_BLA
  650. &batadv_attr_bridge_loop_avoidance,
  651. #endif
  652. #ifdef CONFIG_BATMAN_ADV_DAT
  653. &batadv_attr_distributed_arp_table,
  654. #endif
  655. #ifdef CONFIG_BATMAN_ADV_MCAST
  656. &batadv_attr_multicast_mode,
  657. #endif
  658. &batadv_attr_fragmentation,
  659. &batadv_attr_routing_algo,
  660. &batadv_attr_gw_mode,
  661. &batadv_attr_orig_interval,
  662. &batadv_attr_hop_penalty,
  663. &batadv_attr_gw_sel_class,
  664. &batadv_attr_gw_bandwidth,
  665. #ifdef CONFIG_BATMAN_ADV_DEBUG
  666. &batadv_attr_log_level,
  667. #endif
  668. #ifdef CONFIG_BATMAN_ADV_NC
  669. &batadv_attr_network_coding,
  670. #endif
  671. &batadv_attr_isolation_mark,
  672. NULL,
  673. };
  674. BATADV_ATTR_VLAN_BOOL(ap_isolation, 0644, NULL);
  675. /* array of vlan specific sysfs attributes */
  676. static struct batadv_attribute *batadv_vlan_attrs[] = {
  677. &batadv_attr_vlan_ap_isolation,
  678. NULL,
  679. };
  680. /**
  681. * batadv_sysfs_add_meshif() - Add soft interface specific sysfs entries
  682. * @dev: netdev struct of the soft interface
  683. *
  684. * Return: 0 on success or negative error number in case of failure
  685. */
  686. int batadv_sysfs_add_meshif(struct net_device *dev)
  687. {
  688. struct kobject *batif_kobject = &dev->dev.kobj;
  689. struct batadv_priv *bat_priv = netdev_priv(dev);
  690. struct batadv_attribute **bat_attr;
  691. int err;
  692. bat_priv->mesh_obj = kobject_create_and_add(BATADV_SYSFS_IF_MESH_SUBDIR,
  693. batif_kobject);
  694. if (!bat_priv->mesh_obj) {
  695. batadv_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
  696. BATADV_SYSFS_IF_MESH_SUBDIR);
  697. goto out;
  698. }
  699. for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr) {
  700. err = sysfs_create_file(bat_priv->mesh_obj,
  701. &((*bat_attr)->attr));
  702. if (err) {
  703. batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n",
  704. dev->name, BATADV_SYSFS_IF_MESH_SUBDIR,
  705. ((*bat_attr)->attr).name);
  706. goto rem_attr;
  707. }
  708. }
  709. return 0;
  710. rem_attr:
  711. for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr)
  712. sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
  713. kobject_uevent(bat_priv->mesh_obj, KOBJ_REMOVE);
  714. kobject_del(bat_priv->mesh_obj);
  715. kobject_put(bat_priv->mesh_obj);
  716. bat_priv->mesh_obj = NULL;
  717. out:
  718. return -ENOMEM;
  719. }
  720. /**
  721. * batadv_sysfs_del_meshif() - Remove soft interface specific sysfs entries
  722. * @dev: netdev struct of the soft interface
  723. */
  724. void batadv_sysfs_del_meshif(struct net_device *dev)
  725. {
  726. struct batadv_priv *bat_priv = netdev_priv(dev);
  727. struct batadv_attribute **bat_attr;
  728. for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr)
  729. sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
  730. kobject_uevent(bat_priv->mesh_obj, KOBJ_REMOVE);
  731. kobject_del(bat_priv->mesh_obj);
  732. kobject_put(bat_priv->mesh_obj);
  733. bat_priv->mesh_obj = NULL;
  734. }
  735. /**
  736. * batadv_sysfs_add_vlan() - add all the needed sysfs objects for the new vlan
  737. * @dev: netdev of the mesh interface
  738. * @vlan: private data of the newly added VLAN interface
  739. *
  740. * Return: 0 on success and -ENOMEM if any of the structure allocations fails.
  741. */
  742. int batadv_sysfs_add_vlan(struct net_device *dev,
  743. struct batadv_softif_vlan *vlan)
  744. {
  745. char vlan_subdir[sizeof(BATADV_SYSFS_VLAN_SUBDIR_PREFIX) + 5];
  746. struct batadv_priv *bat_priv = netdev_priv(dev);
  747. struct batadv_attribute **bat_attr;
  748. int err;
  749. if (vlan->vid & BATADV_VLAN_HAS_TAG) {
  750. sprintf(vlan_subdir, BATADV_SYSFS_VLAN_SUBDIR_PREFIX "%hu",
  751. vlan->vid & VLAN_VID_MASK);
  752. vlan->kobj = kobject_create_and_add(vlan_subdir,
  753. bat_priv->mesh_obj);
  754. if (!vlan->kobj) {
  755. batadv_err(dev, "Can't add sysfs directory: %s/%s\n",
  756. dev->name, vlan_subdir);
  757. goto out;
  758. }
  759. } else {
  760. /* the untagged LAN uses the root folder to store its "VLAN
  761. * specific attributes"
  762. */
  763. vlan->kobj = bat_priv->mesh_obj;
  764. kobject_get(bat_priv->mesh_obj);
  765. }
  766. for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr) {
  767. err = sysfs_create_file(vlan->kobj,
  768. &((*bat_attr)->attr));
  769. if (err) {
  770. batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n",
  771. dev->name, vlan_subdir,
  772. ((*bat_attr)->attr).name);
  773. goto rem_attr;
  774. }
  775. }
  776. return 0;
  777. rem_attr:
  778. for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr)
  779. sysfs_remove_file(vlan->kobj, &((*bat_attr)->attr));
  780. if (vlan->kobj != bat_priv->mesh_obj) {
  781. kobject_uevent(vlan->kobj, KOBJ_REMOVE);
  782. kobject_del(vlan->kobj);
  783. }
  784. kobject_put(vlan->kobj);
  785. vlan->kobj = NULL;
  786. out:
  787. return -ENOMEM;
  788. }
  789. /**
  790. * batadv_sysfs_del_vlan() - remove all the sysfs objects for a given VLAN
  791. * @bat_priv: the bat priv with all the soft interface information
  792. * @vlan: the private data of the VLAN to destroy
  793. */
  794. void batadv_sysfs_del_vlan(struct batadv_priv *bat_priv,
  795. struct batadv_softif_vlan *vlan)
  796. {
  797. struct batadv_attribute **bat_attr;
  798. for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr)
  799. sysfs_remove_file(vlan->kobj, &((*bat_attr)->attr));
  800. if (vlan->kobj != bat_priv->mesh_obj) {
  801. kobject_uevent(vlan->kobj, KOBJ_REMOVE);
  802. kobject_del(vlan->kobj);
  803. }
  804. kobject_put(vlan->kobj);
  805. vlan->kobj = NULL;
  806. }
  807. static ssize_t batadv_show_mesh_iface(struct kobject *kobj,
  808. struct attribute *attr, char *buff)
  809. {
  810. struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
  811. struct batadv_hard_iface *hard_iface;
  812. ssize_t length;
  813. const char *ifname;
  814. batadv_sysfs_deprecated(attr);
  815. hard_iface = batadv_hardif_get_by_netdev(net_dev);
  816. if (!hard_iface)
  817. return 0;
  818. if (hard_iface->if_status == BATADV_IF_NOT_IN_USE)
  819. ifname = "none";
  820. else
  821. ifname = hard_iface->soft_iface->name;
  822. length = sprintf(buff, "%s\n", ifname);
  823. batadv_hardif_put(hard_iface);
  824. return length;
  825. }
  826. /**
  827. * batadv_store_mesh_iface_finish() - store new hardif mesh_iface state
  828. * @net_dev: netdevice to add/remove to/from batman-adv soft-interface
  829. * @ifname: name of soft-interface to modify
  830. *
  831. * Changes the parts of the hard+soft interface which can not be modified under
  832. * sysfs lock (to prevent deadlock situations).
  833. *
  834. * Return: 0 on success, 0 < on failure
  835. */
  836. static int batadv_store_mesh_iface_finish(struct net_device *net_dev,
  837. char ifname[IFNAMSIZ])
  838. {
  839. struct net *net = dev_net(net_dev);
  840. struct batadv_hard_iface *hard_iface;
  841. int status_tmp;
  842. int ret = 0;
  843. ASSERT_RTNL();
  844. hard_iface = batadv_hardif_get_by_netdev(net_dev);
  845. if (!hard_iface)
  846. return 0;
  847. if (strncmp(ifname, "none", 4) == 0)
  848. status_tmp = BATADV_IF_NOT_IN_USE;
  849. else
  850. status_tmp = BATADV_IF_I_WANT_YOU;
  851. if (hard_iface->if_status == status_tmp)
  852. goto out;
  853. if (hard_iface->soft_iface &&
  854. strncmp(hard_iface->soft_iface->name, ifname, IFNAMSIZ) == 0)
  855. goto out;
  856. if (status_tmp == BATADV_IF_NOT_IN_USE) {
  857. batadv_hardif_disable_interface(hard_iface,
  858. BATADV_IF_CLEANUP_AUTO);
  859. goto out;
  860. }
  861. /* if the interface already is in use */
  862. if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
  863. batadv_hardif_disable_interface(hard_iface,
  864. BATADV_IF_CLEANUP_AUTO);
  865. ret = batadv_hardif_enable_interface(hard_iface, net, ifname);
  866. out:
  867. batadv_hardif_put(hard_iface);
  868. return ret;
  869. }
  870. /**
  871. * batadv_store_mesh_iface_work() - store new hardif mesh_iface state
  872. * @work: work queue item
  873. *
  874. * Changes the parts of the hard+soft interface which can not be modified under
  875. * sysfs lock (to prevent deadlock situations).
  876. */
  877. static void batadv_store_mesh_iface_work(struct work_struct *work)
  878. {
  879. struct batadv_store_mesh_work *store_work;
  880. int ret;
  881. store_work = container_of(work, struct batadv_store_mesh_work, work);
  882. rtnl_lock();
  883. ret = batadv_store_mesh_iface_finish(store_work->net_dev,
  884. store_work->soft_iface_name);
  885. rtnl_unlock();
  886. if (ret < 0)
  887. pr_err("Failed to store new mesh_iface state %s for %s: %d\n",
  888. store_work->soft_iface_name, store_work->net_dev->name,
  889. ret);
  890. dev_put(store_work->net_dev);
  891. kfree(store_work);
  892. }
  893. static ssize_t batadv_store_mesh_iface(struct kobject *kobj,
  894. struct attribute *attr, char *buff,
  895. size_t count)
  896. {
  897. struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
  898. struct batadv_store_mesh_work *store_work;
  899. batadv_sysfs_deprecated(attr);
  900. if (buff[count - 1] == '\n')
  901. buff[count - 1] = '\0';
  902. if (strlen(buff) >= IFNAMSIZ) {
  903. pr_err("Invalid parameter for 'mesh_iface' setting received: interface name too long '%s'\n",
  904. buff);
  905. return -EINVAL;
  906. }
  907. store_work = kmalloc(sizeof(*store_work), GFP_KERNEL);
  908. if (!store_work)
  909. return -ENOMEM;
  910. dev_hold(net_dev);
  911. INIT_WORK(&store_work->work, batadv_store_mesh_iface_work);
  912. store_work->net_dev = net_dev;
  913. strscpy(store_work->soft_iface_name, buff,
  914. sizeof(store_work->soft_iface_name));
  915. queue_work(batadv_event_workqueue, &store_work->work);
  916. return count;
  917. }
  918. static ssize_t batadv_show_iface_status(struct kobject *kobj,
  919. struct attribute *attr, char *buff)
  920. {
  921. struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
  922. struct batadv_hard_iface *hard_iface;
  923. ssize_t length;
  924. batadv_sysfs_deprecated(attr);
  925. hard_iface = batadv_hardif_get_by_netdev(net_dev);
  926. if (!hard_iface)
  927. return 0;
  928. switch (hard_iface->if_status) {
  929. case BATADV_IF_TO_BE_REMOVED:
  930. length = sprintf(buff, "disabling\n");
  931. break;
  932. case BATADV_IF_INACTIVE:
  933. length = sprintf(buff, "inactive\n");
  934. break;
  935. case BATADV_IF_ACTIVE:
  936. length = sprintf(buff, "active\n");
  937. break;
  938. case BATADV_IF_TO_BE_ACTIVATED:
  939. length = sprintf(buff, "enabling\n");
  940. break;
  941. case BATADV_IF_NOT_IN_USE:
  942. default:
  943. length = sprintf(buff, "not in use\n");
  944. break;
  945. }
  946. batadv_hardif_put(hard_iface);
  947. return length;
  948. }
  949. #ifdef CONFIG_BATMAN_ADV_BATMAN_V
  950. /**
  951. * batadv_store_throughput_override() - parse and store throughput override
  952. * entered by the user
  953. * @kobj: kobject representing the private mesh sysfs directory
  954. * @attr: the batman-adv attribute the user is interacting with
  955. * @buff: the buffer containing the user data
  956. * @count: number of bytes in the buffer
  957. *
  958. * Return: 'count' on success or a negative error code in case of failure
  959. */
  960. static ssize_t batadv_store_throughput_override(struct kobject *kobj,
  961. struct attribute *attr,
  962. char *buff, size_t count)
  963. {
  964. struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
  965. struct batadv_hard_iface *hard_iface;
  966. struct batadv_priv *bat_priv;
  967. u32 tp_override;
  968. u32 old_tp_override;
  969. bool ret;
  970. batadv_sysfs_deprecated(attr);
  971. hard_iface = batadv_hardif_get_by_netdev(net_dev);
  972. if (!hard_iface)
  973. return -EINVAL;
  974. if (buff[count - 1] == '\n')
  975. buff[count - 1] = '\0';
  976. ret = batadv_parse_throughput(net_dev, buff, "throughput_override",
  977. &tp_override);
  978. if (!ret)
  979. goto out;
  980. old_tp_override = atomic_read(&hard_iface->bat_v.throughput_override);
  981. if (old_tp_override == tp_override)
  982. goto out;
  983. batadv_info(hard_iface->soft_iface,
  984. "%s: %s: Changing from: %u.%u MBit to: %u.%u MBit\n",
  985. "throughput_override", net_dev->name,
  986. old_tp_override / 10, old_tp_override % 10,
  987. tp_override / 10, tp_override % 10);
  988. atomic_set(&hard_iface->bat_v.throughput_override, tp_override);
  989. if (hard_iface->soft_iface) {
  990. bat_priv = netdev_priv(hard_iface->soft_iface);
  991. batadv_netlink_notify_hardif(bat_priv, hard_iface);
  992. }
  993. out:
  994. batadv_hardif_put(hard_iface);
  995. return count;
  996. }
  997. static ssize_t batadv_show_throughput_override(struct kobject *kobj,
  998. struct attribute *attr,
  999. char *buff)
  1000. {
  1001. struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
  1002. struct batadv_hard_iface *hard_iface;
  1003. u32 tp_override;
  1004. batadv_sysfs_deprecated(attr);
  1005. hard_iface = batadv_hardif_get_by_netdev(net_dev);
  1006. if (!hard_iface)
  1007. return -EINVAL;
  1008. tp_override = atomic_read(&hard_iface->bat_v.throughput_override);
  1009. batadv_hardif_put(hard_iface);
  1010. return sprintf(buff, "%u.%u MBit\n", tp_override / 10,
  1011. tp_override % 10);
  1012. }
  1013. #endif
  1014. static BATADV_ATTR(mesh_iface, 0644, batadv_show_mesh_iface,
  1015. batadv_store_mesh_iface);
  1016. static BATADV_ATTR(iface_status, 0444, batadv_show_iface_status, NULL);
  1017. #ifdef CONFIG_BATMAN_ADV_BATMAN_V
  1018. BATADV_ATTR_HIF_UINT(elp_interval, bat_v.elp_interval, 0644,
  1019. 2 * BATADV_JITTER, INT_MAX, NULL);
  1020. static BATADV_ATTR(throughput_override, 0644, batadv_show_throughput_override,
  1021. batadv_store_throughput_override);
  1022. #endif
  1023. static struct batadv_attribute *batadv_batman_attrs[] = {
  1024. &batadv_attr_mesh_iface,
  1025. &batadv_attr_iface_status,
  1026. #ifdef CONFIG_BATMAN_ADV_BATMAN_V
  1027. &batadv_attr_elp_interval,
  1028. &batadv_attr_throughput_override,
  1029. #endif
  1030. NULL,
  1031. };
  1032. /**
  1033. * batadv_sysfs_add_hardif() - Add hard interface specific sysfs entries
  1034. * @hardif_obj: address where to store the pointer to new sysfs folder
  1035. * @dev: netdev struct of the hard interface
  1036. *
  1037. * Return: 0 on success or negative error number in case of failure
  1038. */
  1039. int batadv_sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
  1040. {
  1041. struct kobject *hardif_kobject = &dev->dev.kobj;
  1042. struct batadv_attribute **bat_attr;
  1043. int err;
  1044. *hardif_obj = kobject_create_and_add(BATADV_SYSFS_IF_BAT_SUBDIR,
  1045. hardif_kobject);
  1046. if (!*hardif_obj) {
  1047. batadv_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
  1048. BATADV_SYSFS_IF_BAT_SUBDIR);
  1049. goto out;
  1050. }
  1051. for (bat_attr = batadv_batman_attrs; *bat_attr; ++bat_attr) {
  1052. err = sysfs_create_file(*hardif_obj, &((*bat_attr)->attr));
  1053. if (err) {
  1054. batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n",
  1055. dev->name, BATADV_SYSFS_IF_BAT_SUBDIR,
  1056. ((*bat_attr)->attr).name);
  1057. goto rem_attr;
  1058. }
  1059. }
  1060. return 0;
  1061. rem_attr:
  1062. for (bat_attr = batadv_batman_attrs; *bat_attr; ++bat_attr)
  1063. sysfs_remove_file(*hardif_obj, &((*bat_attr)->attr));
  1064. out:
  1065. return -ENOMEM;
  1066. }
  1067. /**
  1068. * batadv_sysfs_del_hardif() - Remove hard interface specific sysfs entries
  1069. * @hardif_obj: address to the pointer to which stores batman-adv sysfs folder
  1070. * of the hard interface
  1071. */
  1072. void batadv_sysfs_del_hardif(struct kobject **hardif_obj)
  1073. {
  1074. kobject_uevent(*hardif_obj, KOBJ_REMOVE);
  1075. kobject_del(*hardif_obj);
  1076. kobject_put(*hardif_obj);
  1077. *hardif_obj = NULL;
  1078. }