diff options
Diffstat (limited to 'net/batman-adv/sysfs.c')
-rw-r--r-- | net/batman-adv/sysfs.c | 274 |
1 files changed, 189 insertions, 85 deletions
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c index 4114b961bc2c..6335433310af 100644 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c | |||
@@ -21,11 +21,12 @@ | |||
21 | #include "sysfs.h" | 21 | #include "sysfs.h" |
22 | #include "translation-table.h" | 22 | #include "translation-table.h" |
23 | #include "distributed-arp-table.h" | 23 | #include "distributed-arp-table.h" |
24 | #include "network-coding.h" | ||
24 | #include "originator.h" | 25 | #include "originator.h" |
25 | #include "hard-interface.h" | 26 | #include "hard-interface.h" |
27 | #include "soft-interface.h" | ||
26 | #include "gateway_common.h" | 28 | #include "gateway_common.h" |
27 | #include "gateway_client.h" | 29 | #include "gateway_client.h" |
28 | #include "vis.h" | ||
29 | 30 | ||
30 | static struct net_device *batadv_kobj_to_netdev(struct kobject *obj) | 31 | static struct net_device *batadv_kobj_to_netdev(struct kobject *obj) |
31 | { | 32 | { |
@@ -39,6 +40,53 @@ static struct batadv_priv *batadv_kobj_to_batpriv(struct kobject *obj) | |||
39 | return netdev_priv(net_dev); | 40 | return netdev_priv(net_dev); |
40 | } | 41 | } |
41 | 42 | ||
43 | /** | ||
44 | * batadv_vlan_kobj_to_batpriv - convert a vlan kobj in the associated batpriv | ||
45 | * @obj: kobject to covert | ||
46 | * | ||
47 | * Returns the associated batadv_priv struct. | ||
48 | */ | ||
49 | static struct batadv_priv *batadv_vlan_kobj_to_batpriv(struct kobject *obj) | ||
50 | { | ||
51 | /* VLAN specific attributes are located in the root sysfs folder if they | ||
52 | * refer to the untagged VLAN.. | ||
53 | */ | ||
54 | if (!strcmp(BATADV_SYSFS_IF_MESH_SUBDIR, obj->name)) | ||
55 | return batadv_kobj_to_batpriv(obj); | ||
56 | |||
57 | /* ..while the attributes for the tagged vlans are located in | ||
58 | * the in the corresponding "vlan%VID" subfolder | ||
59 | */ | ||
60 | return batadv_kobj_to_batpriv(obj->parent); | ||
61 | } | ||
62 | |||
63 | /** | ||
64 | * batadv_kobj_to_vlan - convert a kobj in the associated softif_vlan struct | ||
65 | * @obj: kobject to covert | ||
66 | * | ||
67 | * Returns the associated softif_vlan struct if found, NULL otherwise. | ||
68 | */ | ||
69 | static struct batadv_softif_vlan * | ||
70 | batadv_kobj_to_vlan(struct batadv_priv *bat_priv, struct kobject *obj) | ||
71 | { | ||
72 | struct batadv_softif_vlan *vlan_tmp, *vlan = NULL; | ||
73 | |||
74 | rcu_read_lock(); | ||
75 | hlist_for_each_entry_rcu(vlan_tmp, &bat_priv->softif_vlan_list, list) { | ||
76 | if (vlan_tmp->kobj != obj) | ||
77 | continue; | ||
78 | |||
79 | if (!atomic_inc_not_zero(&vlan_tmp->refcount)) | ||
80 | continue; | ||
81 | |||
82 | vlan = vlan_tmp; | ||
83 | break; | ||
84 | } | ||
85 | rcu_read_unlock(); | ||
86 | |||
87 | return vlan; | ||
88 | } | ||
89 | |||
42 | #define BATADV_UEV_TYPE_VAR "BATTYPE=" | 90 | #define BATADV_UEV_TYPE_VAR "BATTYPE=" |
43 | #define BATADV_UEV_ACTION_VAR "BATACTION=" | 91 | #define BATADV_UEV_ACTION_VAR "BATACTION=" |
44 | #define BATADV_UEV_DATA_VAR "BATDATA=" | 92 | #define BATADV_UEV_DATA_VAR "BATDATA=" |
@@ -53,6 +101,15 @@ static char *batadv_uev_type_str[] = { | |||
53 | "gw" | 101 | "gw" |
54 | }; | 102 | }; |
55 | 103 | ||
104 | /* Use this, if you have customized show and store functions for vlan attrs */ | ||
105 | #define BATADV_ATTR_VLAN(_name, _mode, _show, _store) \ | ||
106 | struct batadv_attribute batadv_attr_vlan_##_name = { \ | ||
107 | .attr = {.name = __stringify(_name), \ | ||
108 | .mode = _mode }, \ | ||
109 | .show = _show, \ | ||
110 | .store = _store, \ | ||
111 | }; | ||
112 | |||
56 | /* Use this, if you have customized show and store functions */ | 113 | /* Use this, if you have customized show and store functions */ |
57 | #define BATADV_ATTR(_name, _mode, _show, _store) \ | 114 | #define BATADV_ATTR(_name, _mode, _show, _store) \ |
58 | struct batadv_attribute batadv_attr_##_name = { \ | 115 | struct batadv_attribute batadv_attr_##_name = { \ |
@@ -122,6 +179,41 @@ ssize_t batadv_show_##_name(struct kobject *kobj, \ | |||
122 | static BATADV_ATTR(_name, _mode, batadv_show_##_name, \ | 179 | static BATADV_ATTR(_name, _mode, batadv_show_##_name, \ |
123 | batadv_store_##_name) | 180 | batadv_store_##_name) |
124 | 181 | ||
182 | #define BATADV_ATTR_VLAN_STORE_BOOL(_name, _post_func) \ | ||
183 | ssize_t batadv_store_vlan_##_name(struct kobject *kobj, \ | ||
184 | struct attribute *attr, char *buff, \ | ||
185 | size_t count) \ | ||
186 | { \ | ||
187 | struct batadv_priv *bat_priv = batadv_vlan_kobj_to_batpriv(kobj);\ | ||
188 | struct batadv_softif_vlan *vlan = batadv_kobj_to_vlan(bat_priv, \ | ||
189 | kobj); \ | ||
190 | size_t res = __batadv_store_bool_attr(buff, count, _post_func, \ | ||
191 | attr, &vlan->_name, \ | ||
192 | bat_priv->soft_iface); \ | ||
193 | batadv_softif_vlan_free_ref(vlan); \ | ||
194 | return res; \ | ||
195 | } | ||
196 | |||
197 | #define BATADV_ATTR_VLAN_SHOW_BOOL(_name) \ | ||
198 | ssize_t batadv_show_vlan_##_name(struct kobject *kobj, \ | ||
199 | struct attribute *attr, char *buff) \ | ||
200 | { \ | ||
201 | struct batadv_priv *bat_priv = batadv_vlan_kobj_to_batpriv(kobj);\ | ||
202 | struct batadv_softif_vlan *vlan = batadv_kobj_to_vlan(bat_priv, \ | ||
203 | kobj); \ | ||
204 | size_t res = sprintf(buff, "%s\n", \ | ||
205 | atomic_read(&vlan->_name) == 0 ? \ | ||
206 | "disabled" : "enabled"); \ | ||
207 | batadv_softif_vlan_free_ref(vlan); \ | ||
208 | return res; \ | ||
209 | } | ||
210 | |||
211 | /* Use this, if you are going to turn a [name] in the vlan struct on or off */ | ||
212 | #define BATADV_ATTR_VLAN_BOOL(_name, _mode, _post_func) \ | ||
213 | static BATADV_ATTR_VLAN_STORE_BOOL(_name, _post_func) \ | ||
214 | static BATADV_ATTR_VLAN_SHOW_BOOL(_name) \ | ||
215 | static BATADV_ATTR_VLAN(_name, _mode, batadv_show_vlan_##_name, \ | ||
216 | batadv_store_vlan_##_name) | ||
125 | 217 | ||
126 | static int batadv_store_bool_attr(char *buff, size_t count, | 218 | static int batadv_store_bool_attr(char *buff, size_t count, |
127 | struct net_device *net_dev, | 219 | struct net_device *net_dev, |
@@ -230,74 +322,6 @@ __batadv_store_uint_attr(const char *buff, size_t count, | |||
230 | return ret; | 322 | return ret; |
231 | } | 323 | } |
232 | 324 | ||
233 | static ssize_t batadv_show_vis_mode(struct kobject *kobj, | ||
234 | struct attribute *attr, char *buff) | ||
235 | { | ||
236 | struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); | ||
237 | int vis_mode = atomic_read(&bat_priv->vis_mode); | ||
238 | const char *mode; | ||
239 | |||
240 | if (vis_mode == BATADV_VIS_TYPE_CLIENT_UPDATE) | ||
241 | mode = "client"; | ||
242 | else | ||
243 | mode = "server"; | ||
244 | |||
245 | return sprintf(buff, "%s\n", mode); | ||
246 | } | ||
247 | |||
248 | static ssize_t batadv_store_vis_mode(struct kobject *kobj, | ||
249 | struct attribute *attr, char *buff, | ||
250 | size_t count) | ||
251 | { | ||
252 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); | ||
253 | struct batadv_priv *bat_priv = netdev_priv(net_dev); | ||
254 | unsigned long val; | ||
255 | int ret, vis_mode_tmp = -1; | ||
256 | const char *old_mode, *new_mode; | ||
257 | |||
258 | ret = kstrtoul(buff, 10, &val); | ||
259 | |||
260 | if (((count == 2) && (!ret) && | ||
261 | (val == BATADV_VIS_TYPE_CLIENT_UPDATE)) || | ||
262 | (strncmp(buff, "client", 6) == 0) || | ||
263 | (strncmp(buff, "off", 3) == 0)) | ||
264 | vis_mode_tmp = BATADV_VIS_TYPE_CLIENT_UPDATE; | ||
265 | |||
266 | if (((count == 2) && (!ret) && | ||
267 | (val == BATADV_VIS_TYPE_SERVER_SYNC)) || | ||
268 | (strncmp(buff, "server", 6) == 0)) | ||
269 | vis_mode_tmp = BATADV_VIS_TYPE_SERVER_SYNC; | ||
270 | |||
271 | if (vis_mode_tmp < 0) { | ||
272 | if (buff[count - 1] == '\n') | ||
273 | buff[count - 1] = '\0'; | ||
274 | |||
275 | batadv_info(net_dev, | ||
276 | "Invalid parameter for 'vis mode' setting received: %s\n", | ||
277 | buff); | ||
278 | return -EINVAL; | ||
279 | } | ||
280 | |||
281 | if (atomic_read(&bat_priv->vis_mode) == vis_mode_tmp) | ||
282 | return count; | ||
283 | |||
284 | if (atomic_read(&bat_priv->vis_mode) == BATADV_VIS_TYPE_CLIENT_UPDATE) | ||
285 | old_mode = "client"; | ||
286 | else | ||
287 | old_mode = "server"; | ||
288 | |||
289 | if (vis_mode_tmp == BATADV_VIS_TYPE_CLIENT_UPDATE) | ||
290 | new_mode = "client"; | ||
291 | else | ||
292 | new_mode = "server"; | ||
293 | |||
294 | batadv_info(net_dev, "Changing vis mode from: %s to: %s\n", old_mode, | ||
295 | new_mode); | ||
296 | |||
297 | atomic_set(&bat_priv->vis_mode, (unsigned int)vis_mode_tmp); | ||
298 | return count; | ||
299 | } | ||
300 | |||
301 | static ssize_t batadv_show_bat_algo(struct kobject *kobj, | 325 | static ssize_t batadv_show_bat_algo(struct kobject *kobj, |
302 | struct attribute *attr, char *buff) | 326 | struct attribute *attr, char *buff) |
303 | { | 327 | { |
@@ -390,6 +414,7 @@ static ssize_t batadv_store_gw_mode(struct kobject *kobj, | |||
390 | */ | 414 | */ |
391 | batadv_gw_check_client_stop(bat_priv); | 415 | batadv_gw_check_client_stop(bat_priv); |
392 | atomic_set(&bat_priv->gw_mode, (unsigned int)gw_mode_tmp); | 416 | atomic_set(&bat_priv->gw_mode, (unsigned int)gw_mode_tmp); |
417 | batadv_gw_tvlv_container_update(bat_priv); | ||
393 | return count; | 418 | return count; |
394 | } | 419 | } |
395 | 420 | ||
@@ -397,15 +422,13 @@ static ssize_t batadv_show_gw_bwidth(struct kobject *kobj, | |||
397 | struct attribute *attr, char *buff) | 422 | struct attribute *attr, char *buff) |
398 | { | 423 | { |
399 | struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); | 424 | struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); |
400 | int down, up; | 425 | uint32_t down, up; |
401 | int gw_bandwidth = atomic_read(&bat_priv->gw_bandwidth); | 426 | |
402 | 427 | down = atomic_read(&bat_priv->gw.bandwidth_down); | |
403 | batadv_gw_bandwidth_to_kbit(gw_bandwidth, &down, &up); | 428 | up = atomic_read(&bat_priv->gw.bandwidth_up); |
404 | return sprintf(buff, "%i%s/%i%s\n", | 429 | |
405 | (down > 2048 ? down / 1024 : down), | 430 | return sprintf(buff, "%u.%u/%u.%u MBit\n", down / 10, |
406 | (down > 2048 ? "MBit" : "KBit"), | 431 | down % 10, up / 10, up % 10); |
407 | (up > 2048 ? up / 1024 : up), | ||
408 | (up > 2048 ? "MBit" : "KBit")); | ||
409 | } | 432 | } |
410 | 433 | ||
411 | static ssize_t batadv_store_gw_bwidth(struct kobject *kobj, | 434 | static ssize_t batadv_store_gw_bwidth(struct kobject *kobj, |
@@ -426,12 +449,10 @@ BATADV_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL); | |||
426 | BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, NULL); | 449 | BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, NULL); |
427 | #endif | 450 | #endif |
428 | #ifdef CONFIG_BATMAN_ADV_DAT | 451 | #ifdef CONFIG_BATMAN_ADV_DAT |
429 | BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR, NULL); | 452 | BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR, |
453 | batadv_dat_status_update); | ||
430 | #endif | 454 | #endif |
431 | BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu); | 455 | BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu); |
432 | BATADV_ATTR_SIF_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL); | ||
433 | static BATADV_ATTR(vis_mode, S_IRUGO | S_IWUSR, batadv_show_vis_mode, | ||
434 | batadv_store_vis_mode); | ||
435 | static BATADV_ATTR(routing_algo, S_IRUGO, batadv_show_bat_algo, NULL); | 456 | static BATADV_ATTR(routing_algo, S_IRUGO, batadv_show_bat_algo, NULL); |
436 | static BATADV_ATTR(gw_mode, S_IRUGO | S_IWUSR, batadv_show_gw_mode, | 457 | static BATADV_ATTR(gw_mode, S_IRUGO | S_IWUSR, batadv_show_gw_mode, |
437 | batadv_store_gw_mode); | 458 | batadv_store_gw_mode); |
@@ -447,7 +468,8 @@ static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth, | |||
447 | BATADV_ATTR_SIF_UINT(log_level, S_IRUGO | S_IWUSR, 0, BATADV_DBG_ALL, NULL); | 468 | BATADV_ATTR_SIF_UINT(log_level, S_IRUGO | S_IWUSR, 0, BATADV_DBG_ALL, NULL); |
448 | #endif | 469 | #endif |
449 | #ifdef CONFIG_BATMAN_ADV_NC | 470 | #ifdef CONFIG_BATMAN_ADV_NC |
450 | BATADV_ATTR_SIF_BOOL(network_coding, S_IRUGO | S_IWUSR, NULL); | 471 | BATADV_ATTR_SIF_BOOL(network_coding, S_IRUGO | S_IWUSR, |
472 | batadv_nc_status_update); | ||
451 | #endif | 473 | #endif |
452 | 474 | ||
453 | static struct batadv_attribute *batadv_mesh_attrs[] = { | 475 | static struct batadv_attribute *batadv_mesh_attrs[] = { |
@@ -460,8 +482,6 @@ static struct batadv_attribute *batadv_mesh_attrs[] = { | |||
460 | &batadv_attr_distributed_arp_table, | 482 | &batadv_attr_distributed_arp_table, |
461 | #endif | 483 | #endif |
462 | &batadv_attr_fragmentation, | 484 | &batadv_attr_fragmentation, |
463 | &batadv_attr_ap_isolation, | ||
464 | &batadv_attr_vis_mode, | ||
465 | &batadv_attr_routing_algo, | 485 | &batadv_attr_routing_algo, |
466 | &batadv_attr_gw_mode, | 486 | &batadv_attr_gw_mode, |
467 | &batadv_attr_orig_interval, | 487 | &batadv_attr_orig_interval, |
@@ -477,6 +497,16 @@ static struct batadv_attribute *batadv_mesh_attrs[] = { | |||
477 | NULL, | 497 | NULL, |
478 | }; | 498 | }; |
479 | 499 | ||
500 | BATADV_ATTR_VLAN_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL); | ||
501 | |||
502 | /** | ||
503 | * batadv_vlan_attrs - array of vlan specific sysfs attributes | ||
504 | */ | ||
505 | static struct batadv_attribute *batadv_vlan_attrs[] = { | ||
506 | &batadv_attr_vlan_ap_isolation, | ||
507 | NULL, | ||
508 | }; | ||
509 | |||
480 | int batadv_sysfs_add_meshif(struct net_device *dev) | 510 | int batadv_sysfs_add_meshif(struct net_device *dev) |
481 | { | 511 | { |
482 | struct kobject *batif_kobject = &dev->dev.kobj; | 512 | struct kobject *batif_kobject = &dev->dev.kobj; |
@@ -527,6 +557,80 @@ void batadv_sysfs_del_meshif(struct net_device *dev) | |||
527 | bat_priv->mesh_obj = NULL; | 557 | bat_priv->mesh_obj = NULL; |
528 | } | 558 | } |
529 | 559 | ||
560 | /** | ||
561 | * batadv_sysfs_add_vlan - add all the needed sysfs objects for the new vlan | ||
562 | * @dev: netdev of the mesh interface | ||
563 | * @vlan: private data of the newly added VLAN interface | ||
564 | * | ||
565 | * Returns 0 on success and -ENOMEM if any of the structure allocations fails. | ||
566 | */ | ||
567 | int batadv_sysfs_add_vlan(struct net_device *dev, | ||
568 | struct batadv_softif_vlan *vlan) | ||
569 | { | ||
570 | char vlan_subdir[sizeof(BATADV_SYSFS_VLAN_SUBDIR_PREFIX) + 5]; | ||
571 | struct batadv_priv *bat_priv = netdev_priv(dev); | ||
572 | struct batadv_attribute **bat_attr; | ||
573 | int err; | ||
574 | |||
575 | if (vlan->vid & BATADV_VLAN_HAS_TAG) { | ||
576 | sprintf(vlan_subdir, BATADV_SYSFS_VLAN_SUBDIR_PREFIX "%hu", | ||
577 | vlan->vid & VLAN_VID_MASK); | ||
578 | |||
579 | vlan->kobj = kobject_create_and_add(vlan_subdir, | ||
580 | bat_priv->mesh_obj); | ||
581 | if (!vlan->kobj) { | ||
582 | batadv_err(dev, "Can't add sysfs directory: %s/%s\n", | ||
583 | dev->name, vlan_subdir); | ||
584 | goto out; | ||
585 | } | ||
586 | } else { | ||
587 | /* the untagged LAN uses the root folder to store its "VLAN | ||
588 | * specific attributes" | ||
589 | */ | ||
590 | vlan->kobj = bat_priv->mesh_obj; | ||
591 | kobject_get(bat_priv->mesh_obj); | ||
592 | } | ||
593 | |||
594 | for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr) { | ||
595 | err = sysfs_create_file(vlan->kobj, | ||
596 | &((*bat_attr)->attr)); | ||
597 | if (err) { | ||
598 | batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n", | ||
599 | dev->name, vlan_subdir, | ||
600 | ((*bat_attr)->attr).name); | ||
601 | goto rem_attr; | ||
602 | } | ||
603 | } | ||
604 | |||
605 | return 0; | ||
606 | |||
607 | rem_attr: | ||
608 | for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr) | ||
609 | sysfs_remove_file(vlan->kobj, &((*bat_attr)->attr)); | ||
610 | |||
611 | kobject_put(vlan->kobj); | ||
612 | vlan->kobj = NULL; | ||
613 | out: | ||
614 | return -ENOMEM; | ||
615 | } | ||
616 | |||
617 | /** | ||
618 | * batadv_sysfs_del_vlan - remove all the sysfs objects for a given VLAN | ||
619 | * @bat_priv: the bat priv with all the soft interface information | ||
620 | * @vlan: the private data of the VLAN to destroy | ||
621 | */ | ||
622 | void batadv_sysfs_del_vlan(struct batadv_priv *bat_priv, | ||
623 | struct batadv_softif_vlan *vlan) | ||
624 | { | ||
625 | struct batadv_attribute **bat_attr; | ||
626 | |||
627 | for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr) | ||
628 | sysfs_remove_file(vlan->kobj, &((*bat_attr)->attr)); | ||
629 | |||
630 | kobject_put(vlan->kobj); | ||
631 | vlan->kobj = NULL; | ||
632 | } | ||
633 | |||
530 | static ssize_t batadv_show_mesh_iface(struct kobject *kobj, | 634 | static ssize_t batadv_show_mesh_iface(struct kobject *kobj, |
531 | struct attribute *attr, char *buff) | 635 | struct attribute *attr, char *buff) |
532 | { | 636 | { |