2 * Copyright (C) 2010-2011 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 static struct net_device
*kobj_to_netdev(struct kobject
*obj
)
33 struct device
*dev
= container_of(obj
->parent
, struct device
, kobj
);
34 return to_net_dev(dev
);
37 static struct bat_priv
*kobj_to_batpriv(struct kobject
*obj
)
39 struct net_device
*net_dev
= kobj_to_netdev(obj
);
40 return netdev_priv(net_dev
);
43 #define UEV_TYPE_VAR "BATTYPE="
44 #define UEV_ACTION_VAR "BATACTION="
45 #define UEV_DATA_VAR "BATDATA="
47 static char *uev_action_str
[] = {
53 static char *uev_type_str
[] = {
57 /* Use this, if you have customized show and store functions */
58 #define BAT_ATTR(_name, _mode, _show, _store) \
59 struct bat_attribute bat_attr_##_name = { \
60 .attr = {.name = __stringify(_name), \
66 #define BAT_ATTR_STORE_BOOL(_name, _post_func) \
67 ssize_t store_##_name(struct kobject *kobj, struct attribute *attr, \
68 char *buff, size_t count) \
70 struct net_device *net_dev = kobj_to_netdev(kobj); \
71 struct bat_priv *bat_priv = netdev_priv(net_dev); \
72 return __store_bool_attr(buff, count, _post_func, attr, \
73 &bat_priv->_name, net_dev); \
76 #define BAT_ATTR_SHOW_BOOL(_name) \
77 ssize_t show_##_name(struct kobject *kobj, struct attribute *attr, \
80 struct bat_priv *bat_priv = kobj_to_batpriv(kobj); \
81 return sprintf(buff, "%s\n", \
82 atomic_read(&bat_priv->_name) == 0 ? \
83 "disabled" : "enabled"); \
86 /* Use this, if you are going to turn a [name] in bat_priv on or off */
87 #define BAT_ATTR_BOOL(_name, _mode, _post_func) \
88 static BAT_ATTR_STORE_BOOL(_name, _post_func) \
89 static BAT_ATTR_SHOW_BOOL(_name) \
90 static BAT_ATTR(_name, _mode, show_##_name, store_##_name)
93 #define BAT_ATTR_STORE_UINT(_name, _min, _max, _post_func) \
94 ssize_t store_##_name(struct kobject *kobj, struct attribute *attr, \
95 char *buff, size_t count) \
97 struct net_device *net_dev = kobj_to_netdev(kobj); \
98 struct bat_priv *bat_priv = netdev_priv(net_dev); \
99 return __store_uint_attr(buff, count, _min, _max, _post_func, \
100 attr, &bat_priv->_name, net_dev); \
103 #define BAT_ATTR_SHOW_UINT(_name) \
104 ssize_t show_##_name(struct kobject *kobj, struct attribute *attr, \
107 struct bat_priv *bat_priv = kobj_to_batpriv(kobj); \
108 return sprintf(buff, "%i\n", atomic_read(&bat_priv->_name)); \
111 /* Use this, if you are going to set [name] in bat_priv to unsigned integer
113 #define BAT_ATTR_UINT(_name, _mode, _min, _max, _post_func) \
114 static BAT_ATTR_STORE_UINT(_name, _min, _max, _post_func) \
115 static BAT_ATTR_SHOW_UINT(_name) \
116 static BAT_ATTR(_name, _mode, show_##_name, store_##_name)
119 static int store_bool_attr(char *buff
, size_t count
,
120 struct net_device
*net_dev
,
121 const char *attr_name
, atomic_t
*attr
)
125 if (buff
[count
- 1] == '\n')
126 buff
[count
- 1] = '\0';
128 if ((strncmp(buff
, "1", 2) == 0) ||
129 (strncmp(buff
, "enable", 7) == 0) ||
130 (strncmp(buff
, "enabled", 8) == 0))
133 if ((strncmp(buff
, "0", 2) == 0) ||
134 (strncmp(buff
, "disable", 8) == 0) ||
135 (strncmp(buff
, "disabled", 9) == 0))
140 "%s: Invalid parameter received: %s\n",
145 if (atomic_read(attr
) == enabled
)
148 bat_info(net_dev
, "%s: Changing from: %s to: %s\n", attr_name
,
149 atomic_read(attr
) == 1 ? "enabled" : "disabled",
150 enabled
== 1 ? "enabled" : "disabled");
152 atomic_set(attr
, (unsigned)enabled
);
156 static inline ssize_t
__store_bool_attr(char *buff
, size_t count
,
157 void (*post_func
)(struct net_device
*),
158 struct attribute
*attr
,
159 atomic_t
*attr_store
, struct net_device
*net_dev
)
163 ret
= store_bool_attr(buff
, count
, net_dev
, attr
->name
, attr_store
);
164 if (post_func
&& ret
)
170 static int store_uint_attr(const char *buff
, size_t count
,
171 struct net_device
*net_dev
, const char *attr_name
,
172 unsigned int min
, unsigned int max
, atomic_t
*attr
)
174 unsigned long uint_val
;
177 ret
= kstrtoul(buff
, 10, &uint_val
);
180 "%s: Invalid parameter received: %s\n",
185 if (uint_val
< min
) {
186 bat_info(net_dev
, "%s: Value is too small: %lu min: %u\n",
187 attr_name
, uint_val
, min
);
191 if (uint_val
> max
) {
192 bat_info(net_dev
, "%s: Value is too big: %lu max: %u\n",
193 attr_name
, uint_val
, max
);
197 if (atomic_read(attr
) == uint_val
)
200 bat_info(net_dev
, "%s: Changing from: %i to: %lu\n",
201 attr_name
, atomic_read(attr
), uint_val
);
203 atomic_set(attr
, uint_val
);
207 static inline ssize_t
__store_uint_attr(const char *buff
, size_t count
,
209 void (*post_func
)(struct net_device
*),
210 const struct attribute
*attr
,
211 atomic_t
*attr_store
, struct net_device
*net_dev
)
215 ret
= store_uint_attr(buff
, count
, net_dev
, attr
->name
,
216 min
, max
, attr_store
);
217 if (post_func
&& ret
)
223 static ssize_t
show_vis_mode(struct kobject
*kobj
, struct attribute
*attr
,
226 struct bat_priv
*bat_priv
= kobj_to_batpriv(kobj
);
227 int vis_mode
= atomic_read(&bat_priv
->vis_mode
);
229 return sprintf(buff
, "%s\n",
230 vis_mode
== VIS_TYPE_CLIENT_UPDATE
?
231 "client" : "server");
234 static ssize_t
store_vis_mode(struct kobject
*kobj
, struct attribute
*attr
,
235 char *buff
, size_t count
)
237 struct net_device
*net_dev
= kobj_to_netdev(kobj
);
238 struct bat_priv
*bat_priv
= netdev_priv(net_dev
);
240 int ret
, vis_mode_tmp
= -1;
242 ret
= kstrtoul(buff
, 10, &val
);
244 if (((count
== 2) && (!ret
) && (val
== VIS_TYPE_CLIENT_UPDATE
)) ||
245 (strncmp(buff
, "client", 6) == 0) ||
246 (strncmp(buff
, "off", 3) == 0))
247 vis_mode_tmp
= VIS_TYPE_CLIENT_UPDATE
;
249 if (((count
== 2) && (!ret
) && (val
== VIS_TYPE_SERVER_SYNC
)) ||
250 (strncmp(buff
, "server", 6) == 0))
251 vis_mode_tmp
= VIS_TYPE_SERVER_SYNC
;
253 if (vis_mode_tmp
< 0) {
254 if (buff
[count
- 1] == '\n')
255 buff
[count
- 1] = '\0';
258 "Invalid parameter for 'vis mode' setting received: "
263 if (atomic_read(&bat_priv
->vis_mode
) == vis_mode_tmp
)
266 bat_info(net_dev
, "Changing vis mode from: %s to: %s\n",
267 atomic_read(&bat_priv
->vis_mode
) == VIS_TYPE_CLIENT_UPDATE
?
268 "client" : "server", vis_mode_tmp
== VIS_TYPE_CLIENT_UPDATE
?
269 "client" : "server");
271 atomic_set(&bat_priv
->vis_mode
, (unsigned)vis_mode_tmp
);
275 static void post_gw_deselect(struct net_device
*net_dev
)
277 struct bat_priv
*bat_priv
= netdev_priv(net_dev
);
278 gw_deselect(bat_priv
);
281 static ssize_t
show_gw_mode(struct kobject
*kobj
, struct attribute
*attr
,
284 struct bat_priv
*bat_priv
= kobj_to_batpriv(kobj
);
287 switch (atomic_read(&bat_priv
->gw_mode
)) {
289 bytes_written
= sprintf(buff
, "%s\n", GW_MODE_CLIENT_NAME
);
292 bytes_written
= sprintf(buff
, "%s\n", GW_MODE_SERVER_NAME
);
295 bytes_written
= sprintf(buff
, "%s\n", GW_MODE_OFF_NAME
);
299 return bytes_written
;
302 static ssize_t
store_gw_mode(struct kobject
*kobj
, struct attribute
*attr
,
303 char *buff
, size_t count
)
305 struct net_device
*net_dev
= kobj_to_netdev(kobj
);
306 struct bat_priv
*bat_priv
= netdev_priv(net_dev
);
307 char *curr_gw_mode_str
;
308 int gw_mode_tmp
= -1;
310 if (buff
[count
- 1] == '\n')
311 buff
[count
- 1] = '\0';
313 if (strncmp(buff
, GW_MODE_OFF_NAME
, strlen(GW_MODE_OFF_NAME
)) == 0)
314 gw_mode_tmp
= GW_MODE_OFF
;
316 if (strncmp(buff
, GW_MODE_CLIENT_NAME
,
317 strlen(GW_MODE_CLIENT_NAME
)) == 0)
318 gw_mode_tmp
= GW_MODE_CLIENT
;
320 if (strncmp(buff
, GW_MODE_SERVER_NAME
,
321 strlen(GW_MODE_SERVER_NAME
)) == 0)
322 gw_mode_tmp
= GW_MODE_SERVER
;
324 if (gw_mode_tmp
< 0) {
326 "Invalid parameter for 'gw mode' setting received: "
331 if (atomic_read(&bat_priv
->gw_mode
) == gw_mode_tmp
)
334 switch (atomic_read(&bat_priv
->gw_mode
)) {
336 curr_gw_mode_str
= GW_MODE_CLIENT_NAME
;
339 curr_gw_mode_str
= GW_MODE_SERVER_NAME
;
342 curr_gw_mode_str
= GW_MODE_OFF_NAME
;
346 bat_info(net_dev
, "Changing gw mode from: %s to: %s\n",
347 curr_gw_mode_str
, buff
);
349 gw_deselect(bat_priv
);
350 atomic_set(&bat_priv
->gw_mode
, (unsigned)gw_mode_tmp
);
354 static ssize_t
show_gw_bwidth(struct kobject
*kobj
, struct attribute
*attr
,
357 struct bat_priv
*bat_priv
= kobj_to_batpriv(kobj
);
359 int gw_bandwidth
= atomic_read(&bat_priv
->gw_bandwidth
);
361 gw_bandwidth_to_kbit(gw_bandwidth
, &down
, &up
);
362 return sprintf(buff
, "%i%s/%i%s\n",
363 (down
> 2048 ? down
/ 1024 : down
),
364 (down
> 2048 ? "MBit" : "KBit"),
365 (up
> 2048 ? up
/ 1024 : up
),
366 (up
> 2048 ? "MBit" : "KBit"));
369 static ssize_t
store_gw_bwidth(struct kobject
*kobj
, struct attribute
*attr
,
370 char *buff
, size_t count
)
372 struct net_device
*net_dev
= kobj_to_netdev(kobj
);
374 if (buff
[count
- 1] == '\n')
375 buff
[count
- 1] = '\0';
377 return gw_bandwidth_set(net_dev
, buff
, count
);
380 BAT_ATTR_BOOL(aggregated_ogms
, S_IRUGO
| S_IWUSR
, NULL
);
381 BAT_ATTR_BOOL(bonding
, S_IRUGO
| S_IWUSR
, NULL
);
382 BAT_ATTR_BOOL(fragmentation
, S_IRUGO
| S_IWUSR
, update_min_mtu
);
383 BAT_ATTR_BOOL(ap_isolation
, S_IRUGO
| S_IWUSR
, NULL
);
384 static BAT_ATTR(vis_mode
, S_IRUGO
| S_IWUSR
, show_vis_mode
, store_vis_mode
);
385 static BAT_ATTR(gw_mode
, S_IRUGO
| S_IWUSR
, show_gw_mode
, store_gw_mode
);
386 BAT_ATTR_UINT(orig_interval
, S_IRUGO
| S_IWUSR
, 2 * JITTER
, INT_MAX
, NULL
);
387 BAT_ATTR_UINT(hop_penalty
, S_IRUGO
| S_IWUSR
, 0, TQ_MAX_VALUE
, NULL
);
388 BAT_ATTR_UINT(gw_sel_class
, S_IRUGO
| S_IWUSR
, 1, TQ_MAX_VALUE
,
390 static BAT_ATTR(gw_bandwidth
, S_IRUGO
| S_IWUSR
, show_gw_bwidth
,
392 #ifdef CONFIG_BATMAN_ADV_DEBUG
393 BAT_ATTR_UINT(log_level
, S_IRUGO
| S_IWUSR
, 0, 7, NULL
);
396 static struct bat_attribute
*mesh_attrs
[] = {
397 &bat_attr_aggregated_ogms
,
399 &bat_attr_fragmentation
,
400 &bat_attr_ap_isolation
,
403 &bat_attr_orig_interval
,
404 &bat_attr_hop_penalty
,
405 &bat_attr_gw_sel_class
,
406 &bat_attr_gw_bandwidth
,
407 #ifdef CONFIG_BATMAN_ADV_DEBUG
413 int sysfs_add_meshif(struct net_device
*dev
)
415 struct kobject
*batif_kobject
= &dev
->dev
.kobj
;
416 struct bat_priv
*bat_priv
= netdev_priv(dev
);
417 struct bat_attribute
**bat_attr
;
420 bat_priv
->mesh_obj
= kobject_create_and_add(SYSFS_IF_MESH_SUBDIR
,
422 if (!bat_priv
->mesh_obj
) {
423 bat_err(dev
, "Can't add sysfs directory: %s/%s\n", dev
->name
,
424 SYSFS_IF_MESH_SUBDIR
);
428 for (bat_attr
= mesh_attrs
; *bat_attr
; ++bat_attr
) {
429 err
= sysfs_create_file(bat_priv
->mesh_obj
,
430 &((*bat_attr
)->attr
));
432 bat_err(dev
, "Can't add sysfs file: %s/%s/%s\n",
433 dev
->name
, SYSFS_IF_MESH_SUBDIR
,
434 ((*bat_attr
)->attr
).name
);
442 for (bat_attr
= mesh_attrs
; *bat_attr
; ++bat_attr
)
443 sysfs_remove_file(bat_priv
->mesh_obj
, &((*bat_attr
)->attr
));
445 kobject_put(bat_priv
->mesh_obj
);
446 bat_priv
->mesh_obj
= NULL
;
451 void sysfs_del_meshif(struct net_device
*dev
)
453 struct bat_priv
*bat_priv
= netdev_priv(dev
);
454 struct bat_attribute
**bat_attr
;
456 for (bat_attr
= mesh_attrs
; *bat_attr
; ++bat_attr
)
457 sysfs_remove_file(bat_priv
->mesh_obj
, &((*bat_attr
)->attr
));
459 kobject_put(bat_priv
->mesh_obj
);
460 bat_priv
->mesh_obj
= NULL
;
463 static ssize_t
show_mesh_iface(struct kobject
*kobj
, struct attribute
*attr
,
466 struct net_device
*net_dev
= kobj_to_netdev(kobj
);
467 struct hard_iface
*hard_iface
= hardif_get_by_netdev(net_dev
);
473 length
= sprintf(buff
, "%s\n", hard_iface
->if_status
== IF_NOT_IN_USE
?
474 "none" : hard_iface
->soft_iface
->name
);
476 hardif_free_ref(hard_iface
);
481 static ssize_t
store_mesh_iface(struct kobject
*kobj
, struct attribute
*attr
,
482 char *buff
, size_t count
)
484 struct net_device
*net_dev
= kobj_to_netdev(kobj
);
485 struct hard_iface
*hard_iface
= hardif_get_by_netdev(net_dev
);
492 if (buff
[count
- 1] == '\n')
493 buff
[count
- 1] = '\0';
495 if (strlen(buff
) >= IFNAMSIZ
) {
496 pr_err("Invalid parameter for 'mesh_iface' setting received: "
497 "interface name too long '%s'\n", buff
);
498 hardif_free_ref(hard_iface
);
502 if (strncmp(buff
, "none", 4) == 0)
503 status_tmp
= IF_NOT_IN_USE
;
505 status_tmp
= IF_I_WANT_YOU
;
507 if (hard_iface
->if_status
== status_tmp
)
510 if ((hard_iface
->soft_iface
) &&
511 (strncmp(hard_iface
->soft_iface
->name
, buff
, IFNAMSIZ
) == 0))
514 if (!rtnl_trylock()) {
519 if (status_tmp
== IF_NOT_IN_USE
) {
520 hardif_disable_interface(hard_iface
);
524 /* if the interface already is in use */
525 if (hard_iface
->if_status
!= IF_NOT_IN_USE
)
526 hardif_disable_interface(hard_iface
);
528 ret
= hardif_enable_interface(hard_iface
, buff
);
533 hardif_free_ref(hard_iface
);
537 static ssize_t
show_iface_status(struct kobject
*kobj
, struct attribute
*attr
,
540 struct net_device
*net_dev
= kobj_to_netdev(kobj
);
541 struct hard_iface
*hard_iface
= hardif_get_by_netdev(net_dev
);
547 switch (hard_iface
->if_status
) {
548 case IF_TO_BE_REMOVED
:
549 length
= sprintf(buff
, "disabling\n");
552 length
= sprintf(buff
, "inactive\n");
555 length
= sprintf(buff
, "active\n");
557 case IF_TO_BE_ACTIVATED
:
558 length
= sprintf(buff
, "enabling\n");
562 length
= sprintf(buff
, "not in use\n");
566 hardif_free_ref(hard_iface
);
571 static BAT_ATTR(mesh_iface
, S_IRUGO
| S_IWUSR
,
572 show_mesh_iface
, store_mesh_iface
);
573 static BAT_ATTR(iface_status
, S_IRUGO
, show_iface_status
, NULL
);
575 static struct bat_attribute
*batman_attrs
[] = {
576 &bat_attr_mesh_iface
,
577 &bat_attr_iface_status
,
581 int sysfs_add_hardif(struct kobject
**hardif_obj
, struct net_device
*dev
)
583 struct kobject
*hardif_kobject
= &dev
->dev
.kobj
;
584 struct bat_attribute
**bat_attr
;
587 *hardif_obj
= kobject_create_and_add(SYSFS_IF_BAT_SUBDIR
,
591 bat_err(dev
, "Can't add sysfs directory: %s/%s\n", dev
->name
,
592 SYSFS_IF_BAT_SUBDIR
);
596 for (bat_attr
= batman_attrs
; *bat_attr
; ++bat_attr
) {
597 err
= sysfs_create_file(*hardif_obj
, &((*bat_attr
)->attr
));
599 bat_err(dev
, "Can't add sysfs file: %s/%s/%s\n",
600 dev
->name
, SYSFS_IF_BAT_SUBDIR
,
601 ((*bat_attr
)->attr
).name
);
609 for (bat_attr
= batman_attrs
; *bat_attr
; ++bat_attr
)
610 sysfs_remove_file(*hardif_obj
, &((*bat_attr
)->attr
));
615 void sysfs_del_hardif(struct kobject
**hardif_obj
)
617 kobject_put(*hardif_obj
);
621 int throw_uevent(struct bat_priv
*bat_priv
, enum uev_type type
,
622 enum uev_action action
, const char *data
)
625 struct hard_iface
*primary_if
= NULL
;
626 struct kobject
*bat_kobj
;
627 char *uevent_env
[4] = { NULL
, NULL
, NULL
, NULL
};
629 primary_if
= primary_if_get_selected(bat_priv
);
633 bat_kobj
= &primary_if
->soft_iface
->dev
.kobj
;
635 uevent_env
[0] = kmalloc(strlen(UEV_TYPE_VAR
) +
636 strlen(uev_type_str
[type
]) + 1,
641 sprintf(uevent_env
[0], "%s%s", UEV_TYPE_VAR
, uev_type_str
[type
]);
643 uevent_env
[1] = kmalloc(strlen(UEV_ACTION_VAR
) +
644 strlen(uev_action_str
[action
]) + 1,
649 sprintf(uevent_env
[1], "%s%s", UEV_ACTION_VAR
, uev_action_str
[action
]);
651 /* If the event is DEL, ignore the data field */
652 if (action
!= UEV_DEL
) {
653 uevent_env
[2] = kmalloc(strlen(UEV_DATA_VAR
) +
654 strlen(data
) + 1, GFP_ATOMIC
);
658 sprintf(uevent_env
[2], "%s%s", UEV_DATA_VAR
, data
);
661 ret
= kobject_uevent_env(bat_kobj
, KOBJ_CHANGE
, uevent_env
);
663 kfree(uevent_env
[0]);
664 kfree(uevent_env
[1]);
665 kfree(uevent_env
[2]);
668 hardif_free_ref(primary_if
);
671 bat_dbg(DBG_BATMAN
, bat_priv
, "Impossible to send "
672 "uevent for (%s,%s,%s) event (err: %d)\n",
673 uev_type_str
[type
], uev_action_str
[action
],
674 (action
== UEV_DEL
? "NULL" : data
), ret
);