2 * Copyright (C) 2010 B.A.T.M.A.N. contributors:
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.
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.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 #include "bat_sysfs.h"
24 #include "translation-table.h"
25 #include "originator.h"
26 #include "hard-interface.h"
27 #include "gateway_common.h"
28 #include "gateway_client.h"
31 #define to_dev(obj) container_of(obj, struct device, kobj)
32 #define kobj_to_netdev(obj) to_net_dev(to_dev(obj->parent))
33 #define kobj_to_batpriv(obj) netdev_priv(kobj_to_netdev(obj))
35 /* Use this, if you have customized show and store functions */
36 #define BAT_ATTR(_name, _mode, _show, _store) \
37 struct bat_attribute bat_attr_##_name = { \
38 .attr = {.name = __stringify(_name), \
44 #define BAT_ATTR_STORE_BOOL(_name, _post_func) \
45 ssize_t store_##_name(struct kobject *kobj, struct attribute *attr, \
46 char *buff, size_t count) \
48 struct net_device *net_dev = kobj_to_netdev(kobj); \
49 struct bat_priv *bat_priv = netdev_priv(net_dev); \
50 return __store_bool_attr(buff, count, _post_func, attr, \
51 &bat_priv->_name, net_dev); \
54 #define BAT_ATTR_SHOW_BOOL(_name) \
55 ssize_t show_##_name(struct kobject *kobj, struct attribute *attr, \
58 struct bat_priv *bat_priv = kobj_to_batpriv(kobj); \
59 return sprintf(buff, "%s\n", \
60 atomic_read(&bat_priv->_name) == 0 ? \
61 "disabled" : "enabled"); \
64 /* Use this, if you are going to turn a [name] in bat_priv on or off */
65 #define BAT_ATTR_BOOL(_name, _mode, _post_func) \
66 static BAT_ATTR_STORE_BOOL(_name, _post_func) \
67 static BAT_ATTR_SHOW_BOOL(_name) \
68 static BAT_ATTR(_name, _mode, show_##_name, store_##_name)
71 #define BAT_ATTR_STORE_UINT(_name, _min, _max, _post_func) \
72 ssize_t store_##_name(struct kobject *kobj, struct attribute *attr, \
73 char *buff, size_t count) \
75 struct net_device *net_dev = kobj_to_netdev(kobj); \
76 struct bat_priv *bat_priv = netdev_priv(net_dev); \
77 return __store_uint_attr(buff, count, _min, _max, _post_func, \
78 attr, &bat_priv->_name, net_dev); \
81 #define BAT_ATTR_SHOW_UINT(_name) \
82 ssize_t show_##_name(struct kobject *kobj, struct attribute *attr, \
85 struct bat_priv *bat_priv = kobj_to_batpriv(kobj); \
86 return sprintf(buff, "%i\n", atomic_read(&bat_priv->_name)); \
89 /* Use this, if you are going to set [name] in bat_priv to unsigned integer
91 #define BAT_ATTR_UINT(_name, _mode, _min, _max, _post_func) \
92 static BAT_ATTR_STORE_UINT(_name, _min, _max, _post_func) \
93 static BAT_ATTR_SHOW_UINT(_name) \
94 static BAT_ATTR(_name, _mode, show_##_name, store_##_name)
97 static int store_bool_attr(char *buff
, size_t count
,
98 struct net_device
*net_dev
,
99 char *attr_name
, atomic_t
*attr
)
103 if (buff
[count
- 1] == '\n')
104 buff
[count
- 1] = '\0';
106 if ((strncmp(buff
, "1", 2) == 0) ||
107 (strncmp(buff
, "enable", 7) == 0) ||
108 (strncmp(buff
, "enabled", 8) == 0))
111 if ((strncmp(buff
, "0", 2) == 0) ||
112 (strncmp(buff
, "disable", 8) == 0) ||
113 (strncmp(buff
, "disabled", 9) == 0))
118 "%s: Invalid parameter received: %s\n",
123 if (atomic_read(attr
) == enabled
)
126 bat_info(net_dev
, "%s: Changing from: %s to: %s\n", attr_name
,
127 atomic_read(attr
) == 1 ? "enabled" : "disabled",
128 enabled
== 1 ? "enabled" : "disabled");
130 atomic_set(attr
, (unsigned)enabled
);
134 static inline ssize_t
__store_bool_attr(char *buff
, size_t count
,
135 void (*post_func
)(struct net_device
*),
136 struct attribute
*attr
,
137 atomic_t
*attr_store
, struct net_device
*net_dev
)
141 ret
= store_bool_attr(buff
, count
, net_dev
, (char *)attr
->name
,
143 if (post_func
&& ret
)
149 static int store_uint_attr(char *buff
, size_t count
,
150 struct net_device
*net_dev
, char *attr_name
,
151 unsigned int min
, unsigned int max
, atomic_t
*attr
)
153 unsigned long uint_val
;
156 ret
= strict_strtoul(buff
, 10, &uint_val
);
159 "%s: Invalid parameter received: %s\n",
164 if (uint_val
< min
) {
165 bat_info(net_dev
, "%s: Value is too small: %lu min: %u\n",
166 attr_name
, uint_val
, min
);
170 if (uint_val
> max
) {
171 bat_info(net_dev
, "%s: Value is too big: %lu max: %u\n",
172 attr_name
, uint_val
, max
);
176 if (atomic_read(attr
) == uint_val
)
179 bat_info(net_dev
, "%s: Changing from: %i to: %lu\n",
180 attr_name
, atomic_read(attr
), uint_val
);
182 atomic_set(attr
, uint_val
);
186 static inline ssize_t
__store_uint_attr(char *buff
, size_t count
,
188 void (*post_func
)(struct net_device
*),
189 struct attribute
*attr
,
190 atomic_t
*attr_store
, struct net_device
*net_dev
)
194 ret
= store_uint_attr(buff
, count
, net_dev
, (char *)attr
->name
,
195 min
, max
, attr_store
);
196 if (post_func
&& ret
)
202 static ssize_t
show_vis_mode(struct kobject
*kobj
, struct attribute
*attr
,
205 struct bat_priv
*bat_priv
= kobj_to_batpriv(kobj
);
206 int vis_mode
= atomic_read(&bat_priv
->vis_mode
);
208 return sprintf(buff
, "%s\n",
209 vis_mode
== VIS_TYPE_CLIENT_UPDATE
?
210 "client" : "server");
213 static ssize_t
store_vis_mode(struct kobject
*kobj
, struct attribute
*attr
,
214 char *buff
, size_t count
)
216 struct net_device
*net_dev
= kobj_to_netdev(kobj
);
217 struct bat_priv
*bat_priv
= netdev_priv(net_dev
);
219 int ret
, vis_mode_tmp
= -1;
221 ret
= strict_strtoul(buff
, 10, &val
);
223 if (((count
== 2) && (!ret
) && (val
== VIS_TYPE_CLIENT_UPDATE
)) ||
224 (strncmp(buff
, "client", 6) == 0) ||
225 (strncmp(buff
, "off", 3) == 0))
226 vis_mode_tmp
= VIS_TYPE_CLIENT_UPDATE
;
228 if (((count
== 2) && (!ret
) && (val
== VIS_TYPE_SERVER_SYNC
)) ||
229 (strncmp(buff
, "server", 6) == 0))
230 vis_mode_tmp
= VIS_TYPE_SERVER_SYNC
;
232 if (vis_mode_tmp
< 0) {
233 if (buff
[count
- 1] == '\n')
234 buff
[count
- 1] = '\0';
237 "Invalid parameter for 'vis mode' setting received: "
242 if (atomic_read(&bat_priv
->vis_mode
) == vis_mode_tmp
)
245 bat_info(net_dev
, "Changing vis mode from: %s to: %s\n",
246 atomic_read(&bat_priv
->vis_mode
) == VIS_TYPE_CLIENT_UPDATE
?
247 "client" : "server", vis_mode_tmp
== VIS_TYPE_CLIENT_UPDATE
?
248 "client" : "server");
250 atomic_set(&bat_priv
->vis_mode
, (unsigned)vis_mode_tmp
);
254 static void post_gw_deselect(struct net_device
*net_dev
)
256 struct bat_priv
*bat_priv
= netdev_priv(net_dev
);
257 gw_deselect(bat_priv
);
260 static ssize_t
show_gw_mode(struct kobject
*kobj
, struct attribute
*attr
,
263 struct bat_priv
*bat_priv
= kobj_to_batpriv(kobj
);
266 switch (atomic_read(&bat_priv
->gw_mode
)) {
268 bytes_written
= sprintf(buff
, "%s\n", GW_MODE_CLIENT_NAME
);
271 bytes_written
= sprintf(buff
, "%s\n", GW_MODE_SERVER_NAME
);
274 bytes_written
= sprintf(buff
, "%s\n", GW_MODE_OFF_NAME
);
278 return bytes_written
;
281 static ssize_t
store_gw_mode(struct kobject
*kobj
, struct attribute
*attr
,
282 char *buff
, size_t count
)
284 struct net_device
*net_dev
= kobj_to_netdev(kobj
);
285 struct bat_priv
*bat_priv
= netdev_priv(net_dev
);
286 char *curr_gw_mode_str
;
287 int gw_mode_tmp
= -1;
289 if (buff
[count
- 1] == '\n')
290 buff
[count
- 1] = '\0';
292 if (strncmp(buff
, GW_MODE_OFF_NAME
, strlen(GW_MODE_OFF_NAME
)) == 0)
293 gw_mode_tmp
= GW_MODE_OFF
;
295 if (strncmp(buff
, GW_MODE_CLIENT_NAME
,
296 strlen(GW_MODE_CLIENT_NAME
)) == 0)
297 gw_mode_tmp
= GW_MODE_CLIENT
;
299 if (strncmp(buff
, GW_MODE_SERVER_NAME
,
300 strlen(GW_MODE_SERVER_NAME
)) == 0)
301 gw_mode_tmp
= GW_MODE_SERVER
;
303 if (gw_mode_tmp
< 0) {
305 "Invalid parameter for 'gw mode' setting received: "
310 if (atomic_read(&bat_priv
->gw_mode
) == gw_mode_tmp
)
313 switch (atomic_read(&bat_priv
->gw_mode
)) {
315 curr_gw_mode_str
= GW_MODE_CLIENT_NAME
;
318 curr_gw_mode_str
= GW_MODE_SERVER_NAME
;
321 curr_gw_mode_str
= GW_MODE_OFF_NAME
;
325 bat_info(net_dev
, "Changing gw mode from: %s to: %s\n",
326 curr_gw_mode_str
, buff
);
328 gw_deselect(bat_priv
);
329 atomic_set(&bat_priv
->gw_mode
, (unsigned)gw_mode_tmp
);
333 static ssize_t
show_gw_bwidth(struct kobject
*kobj
, struct attribute
*attr
,
336 struct bat_priv
*bat_priv
= kobj_to_batpriv(kobj
);
338 int gw_bandwidth
= atomic_read(&bat_priv
->gw_bandwidth
);
340 gw_bandwidth_to_kbit(gw_bandwidth
, &down
, &up
);
341 return sprintf(buff
, "%i%s/%i%s\n",
342 (down
> 2048 ? down
/ 1024 : down
),
343 (down
> 2048 ? "MBit" : "KBit"),
344 (up
> 2048 ? up
/ 1024 : up
),
345 (up
> 2048 ? "MBit" : "KBit"));
348 static ssize_t
store_gw_bwidth(struct kobject
*kobj
, struct attribute
*attr
,
349 char *buff
, size_t count
)
351 struct net_device
*net_dev
= kobj_to_netdev(kobj
);
353 if (buff
[count
- 1] == '\n')
354 buff
[count
- 1] = '\0';
356 return gw_bandwidth_set(net_dev
, buff
, count
);
359 BAT_ATTR_BOOL(aggregated_ogms
, S_IRUGO
| S_IWUSR
, NULL
);
360 BAT_ATTR_BOOL(bonding
, S_IRUGO
| S_IWUSR
, NULL
);
361 BAT_ATTR_BOOL(fragmentation
, S_IRUGO
| S_IWUSR
, update_min_mtu
);
362 static BAT_ATTR(vis_mode
, S_IRUGO
| S_IWUSR
, show_vis_mode
, store_vis_mode
);
363 static BAT_ATTR(gw_mode
, S_IRUGO
| S_IWUSR
, show_gw_mode
, store_gw_mode
);
364 BAT_ATTR_UINT(orig_interval
, S_IRUGO
| S_IWUSR
, 2 * JITTER
, INT_MAX
, NULL
);
365 BAT_ATTR_UINT(hop_penalty
, S_IRUGO
| S_IWUSR
, 0, TQ_MAX_VALUE
, NULL
);
366 BAT_ATTR_UINT(gw_sel_class
, S_IRUGO
| S_IWUSR
, 1, TQ_MAX_VALUE
,
368 static BAT_ATTR(gw_bandwidth
, S_IRUGO
| S_IWUSR
, show_gw_bwidth
,
370 #ifdef CONFIG_BATMAN_ADV_DEBUG
371 BAT_ATTR_UINT(log_level
, S_IRUGO
| S_IWUSR
, 0, 3, NULL
);
374 static struct bat_attribute
*mesh_attrs
[] = {
375 &bat_attr_aggregated_ogms
,
377 &bat_attr_fragmentation
,
380 &bat_attr_orig_interval
,
381 &bat_attr_hop_penalty
,
382 &bat_attr_gw_sel_class
,
383 &bat_attr_gw_bandwidth
,
384 #ifdef CONFIG_BATMAN_ADV_DEBUG
390 int sysfs_add_meshif(struct net_device
*dev
)
392 struct kobject
*batif_kobject
= &dev
->dev
.kobj
;
393 struct bat_priv
*bat_priv
= netdev_priv(dev
);
394 struct bat_attribute
**bat_attr
;
397 bat_priv
->mesh_obj
= kobject_create_and_add(SYSFS_IF_MESH_SUBDIR
,
399 if (!bat_priv
->mesh_obj
) {
400 bat_err(dev
, "Can't add sysfs directory: %s/%s\n", dev
->name
,
401 SYSFS_IF_MESH_SUBDIR
);
405 for (bat_attr
= mesh_attrs
; *bat_attr
; ++bat_attr
) {
406 err
= sysfs_create_file(bat_priv
->mesh_obj
,
407 &((*bat_attr
)->attr
));
409 bat_err(dev
, "Can't add sysfs file: %s/%s/%s\n",
410 dev
->name
, SYSFS_IF_MESH_SUBDIR
,
411 ((*bat_attr
)->attr
).name
);
419 for (bat_attr
= mesh_attrs
; *bat_attr
; ++bat_attr
)
420 sysfs_remove_file(bat_priv
->mesh_obj
, &((*bat_attr
)->attr
));
422 kobject_put(bat_priv
->mesh_obj
);
423 bat_priv
->mesh_obj
= NULL
;
428 void sysfs_del_meshif(struct net_device
*dev
)
430 struct bat_priv
*bat_priv
= netdev_priv(dev
);
431 struct bat_attribute
**bat_attr
;
433 for (bat_attr
= mesh_attrs
; *bat_attr
; ++bat_attr
)
434 sysfs_remove_file(bat_priv
->mesh_obj
, &((*bat_attr
)->attr
));
436 kobject_put(bat_priv
->mesh_obj
);
437 bat_priv
->mesh_obj
= NULL
;
440 static ssize_t
show_mesh_iface(struct kobject
*kobj
, struct attribute
*attr
,
443 struct net_device
*net_dev
= kobj_to_netdev(kobj
);
444 struct batman_if
*batman_if
= get_batman_if_by_netdev(net_dev
);
450 length
= sprintf(buff
, "%s\n", batman_if
->if_status
== IF_NOT_IN_USE
?
451 "none" : batman_if
->soft_iface
->name
);
453 kref_put(&batman_if
->refcount
, hardif_free_ref
);
458 static ssize_t
store_mesh_iface(struct kobject
*kobj
, struct attribute
*attr
,
459 char *buff
, size_t count
)
461 struct net_device
*net_dev
= kobj_to_netdev(kobj
);
462 struct batman_if
*batman_if
= get_batman_if_by_netdev(net_dev
);
469 if (buff
[count
- 1] == '\n')
470 buff
[count
- 1] = '\0';
472 if (strlen(buff
) >= IFNAMSIZ
) {
473 pr_err("Invalid parameter for 'mesh_iface' setting received: "
474 "interface name too long '%s'\n", buff
);
475 kref_put(&batman_if
->refcount
, hardif_free_ref
);
479 if (strncmp(buff
, "none", 4) == 0)
480 status_tmp
= IF_NOT_IN_USE
;
482 status_tmp
= IF_I_WANT_YOU
;
484 if ((batman_if
->if_status
== status_tmp
) || ((batman_if
->soft_iface
) &&
485 (strncmp(batman_if
->soft_iface
->name
, buff
, IFNAMSIZ
) == 0))) {
486 kref_put(&batman_if
->refcount
, hardif_free_ref
);
490 if (status_tmp
== IF_NOT_IN_USE
) {
492 hardif_disable_interface(batman_if
);
494 kref_put(&batman_if
->refcount
, hardif_free_ref
);
498 /* if the interface already is in use */
499 if (batman_if
->if_status
!= IF_NOT_IN_USE
) {
501 hardif_disable_interface(batman_if
);
505 ret
= hardif_enable_interface(batman_if
, buff
);
506 kref_put(&batman_if
->refcount
, hardif_free_ref
);
511 static ssize_t
show_iface_status(struct kobject
*kobj
, struct attribute
*attr
,
514 struct net_device
*net_dev
= kobj_to_netdev(kobj
);
515 struct batman_if
*batman_if
= get_batman_if_by_netdev(net_dev
);
521 switch (batman_if
->if_status
) {
522 case IF_TO_BE_REMOVED
:
523 length
= sprintf(buff
, "disabling\n");
526 length
= sprintf(buff
, "inactive\n");
529 length
= sprintf(buff
, "active\n");
531 case IF_TO_BE_ACTIVATED
:
532 length
= sprintf(buff
, "enabling\n");
536 length
= sprintf(buff
, "not in use\n");
540 kref_put(&batman_if
->refcount
, hardif_free_ref
);
545 static BAT_ATTR(mesh_iface
, S_IRUGO
| S_IWUSR
,
546 show_mesh_iface
, store_mesh_iface
);
547 static BAT_ATTR(iface_status
, S_IRUGO
, show_iface_status
, NULL
);
549 static struct bat_attribute
*batman_attrs
[] = {
550 &bat_attr_mesh_iface
,
551 &bat_attr_iface_status
,
555 int sysfs_add_hardif(struct kobject
**hardif_obj
, struct net_device
*dev
)
557 struct kobject
*hardif_kobject
= &dev
->dev
.kobj
;
558 struct bat_attribute
**bat_attr
;
561 *hardif_obj
= kobject_create_and_add(SYSFS_IF_BAT_SUBDIR
,
565 bat_err(dev
, "Can't add sysfs directory: %s/%s\n", dev
->name
,
566 SYSFS_IF_BAT_SUBDIR
);
570 for (bat_attr
= batman_attrs
; *bat_attr
; ++bat_attr
) {
571 err
= sysfs_create_file(*hardif_obj
, &((*bat_attr
)->attr
));
573 bat_err(dev
, "Can't add sysfs file: %s/%s/%s\n",
574 dev
->name
, SYSFS_IF_BAT_SUBDIR
,
575 ((*bat_attr
)->attr
).name
);
583 for (bat_attr
= batman_attrs
; *bat_attr
; ++bat_attr
)
584 sysfs_remove_file(*hardif_obj
, &((*bat_attr
)->attr
));
589 void sysfs_del_hardif(struct kobject
**hardif_obj
)
591 kobject_put(*hardif_obj
);