aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntonio Quartulli <antonio@open-mesh.com>2013-07-02 05:04:35 -0400
committerAntonio Quartulli <antonio@meshcoding.com>2013-10-19 11:28:42 -0400
commit90f4435da43191025712fdcf6b0dc09c018456e9 (patch)
tree6c74c3ad0053e06e3488282f1c39a2af38e88876
parent5d2c05b213377694a2aa8ce1ed9b23f7c39b0569 (diff)
batman-adv: add sysfs framework for VLAN
Each VLAN can now have its own set of attributes which are exported through a new subfolder in the sysfs tree. Each VLAN created on top of a soft_iface will have its own subfolder. The subfolder is named "vlan%VID" and it is created inside the "mesh" sysfs folder belonging to batman-adv. Attributes corresponding to the untagged LAN are stored in the root sysfs folder as before. This patch also creates all the needed macros and data structures to easily handle new VLAN spacific attributes. Signed-off-by: Antonio Quartulli <antonio@open-mesh.com> Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
-rw-r--r--net/batman-adv/soft-interface.c15
-rw-r--r--net/batman-adv/soft-interface.h3
-rw-r--r--net/batman-adv/sysfs.c173
-rw-r--r--net/batman-adv/sysfs.h10
4 files changed, 198 insertions, 3 deletions
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 936b83bb02de..f74200c7e553 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -398,7 +398,7 @@ out:
398 * possibly free it 398 * possibly free it
399 * @softif_vlan: the vlan object to release 399 * @softif_vlan: the vlan object to release
400 */ 400 */
401static void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *softif_vlan) 401void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *softif_vlan)
402{ 402{
403 if (atomic_dec_and_test(&softif_vlan->refcount)) 403 if (atomic_dec_and_test(&softif_vlan->refcount))
404 kfree_rcu(softif_vlan, rcu); 404 kfree_rcu(softif_vlan, rcu);
@@ -412,8 +412,8 @@ static void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *softif_vlan)
412 * Returns the private data of the vlan matching the vid passed as argument or 412 * Returns the private data of the vlan matching the vid passed as argument or
413 * NULL otherwise. The refcounter of the returned object is incremented by 1. 413 * NULL otherwise. The refcounter of the returned object is incremented by 1.
414 */ 414 */
415static struct batadv_softif_vlan * 415struct batadv_softif_vlan *batadv_softif_vlan_get(struct batadv_priv *bat_priv,
416batadv_softif_vlan_get(struct batadv_priv *bat_priv, unsigned short vid) 416 unsigned short vid)
417{ 417{
418 struct batadv_softif_vlan *vlan_tmp, *vlan = NULL; 418 struct batadv_softif_vlan *vlan_tmp, *vlan = NULL;
419 419
@@ -443,6 +443,7 @@ batadv_softif_vlan_get(struct batadv_priv *bat_priv, unsigned short vid)
443int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid) 443int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid)
444{ 444{
445 struct batadv_softif_vlan *vlan; 445 struct batadv_softif_vlan *vlan;
446 int err;
446 447
447 vlan = batadv_softif_vlan_get(bat_priv, vid); 448 vlan = batadv_softif_vlan_get(bat_priv, vid);
448 if (vlan) { 449 if (vlan) {
@@ -457,6 +458,12 @@ int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid)
457 vlan->vid = vid; 458 vlan->vid = vid;
458 atomic_set(&vlan->refcount, 1); 459 atomic_set(&vlan->refcount, 1);
459 460
461 err = batadv_sysfs_add_vlan(bat_priv->soft_iface, vlan);
462 if (err) {
463 kfree(vlan);
464 return err;
465 }
466
460 /* add a new TT local entry. This one will be marked with the NOPURGE 467 /* add a new TT local entry. This one will be marked with the NOPURGE
461 * flag 468 * flag
462 */ 469 */
@@ -483,6 +490,8 @@ static void batadv_softif_destroy_vlan(struct batadv_priv *bat_priv,
483 hlist_del_rcu(&vlan->list); 490 hlist_del_rcu(&vlan->list);
484 spin_unlock_bh(&bat_priv->softif_vlan_list_lock); 491 spin_unlock_bh(&bat_priv->softif_vlan_list_lock);
485 492
493 batadv_sysfs_del_vlan(bat_priv, vlan);
494
486 /* explicitly remove the associated TT local entry because it is marked 495 /* explicitly remove the associated TT local entry because it is marked
487 * with the NOPURGE flag 496 * with the NOPURGE flag
488 */ 497 */
diff --git a/net/batman-adv/soft-interface.h b/net/batman-adv/soft-interface.h
index 16d9be6df647..06fc91ff5a02 100644
--- a/net/batman-adv/soft-interface.h
+++ b/net/batman-adv/soft-interface.h
@@ -29,5 +29,8 @@ void batadv_softif_destroy_sysfs(struct net_device *soft_iface);
29int batadv_softif_is_valid(const struct net_device *net_dev); 29int batadv_softif_is_valid(const struct net_device *net_dev);
30extern struct rtnl_link_ops batadv_link_ops; 30extern struct rtnl_link_ops batadv_link_ops;
31int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid); 31int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid);
32void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *softif_vlan);
33struct batadv_softif_vlan *batadv_softif_vlan_get(struct batadv_priv *bat_priv,
34 unsigned short vid);
32 35
33#endif /* _NET_BATMAN_ADV_SOFT_INTERFACE_H_ */ 36#endif /* _NET_BATMAN_ADV_SOFT_INTERFACE_H_ */
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c
index 869eb46329cb..f419d218890d 100644
--- a/net/batman-adv/sysfs.c
+++ b/net/batman-adv/sysfs.c
@@ -24,6 +24,7 @@
24#include "network-coding.h" 24#include "network-coding.h"
25#include "originator.h" 25#include "originator.h"
26#include "hard-interface.h" 26#include "hard-interface.h"
27#include "soft-interface.h"
27#include "gateway_common.h" 28#include "gateway_common.h"
28#include "gateway_client.h" 29#include "gateway_client.h"
29 30
@@ -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 */
49static 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 */
69static struct batadv_softif_vlan *
70batadv_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) \
106struct 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) \
58struct batadv_attribute batadv_attr_##_name = { \ 115struct 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) \
183ssize_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) \
198ssize_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
126static int batadv_store_bool_attr(char *buff, size_t count, 218static int batadv_store_bool_attr(char *buff, size_t count,
127 struct net_device *net_dev, 219 struct net_device *net_dev,
@@ -407,6 +499,13 @@ static struct batadv_attribute *batadv_mesh_attrs[] = {
407 NULL, 499 NULL,
408}; 500};
409 501
502/**
503 * batadv_vlan_attrs - array of vlan specific sysfs attributes
504 */
505static struct batadv_attribute *batadv_vlan_attrs[] = {
506 NULL,
507};
508
410int batadv_sysfs_add_meshif(struct net_device *dev) 509int batadv_sysfs_add_meshif(struct net_device *dev)
411{ 510{
412 struct kobject *batif_kobject = &dev->dev.kobj; 511 struct kobject *batif_kobject = &dev->dev.kobj;
@@ -457,6 +556,80 @@ void batadv_sysfs_del_meshif(struct net_device *dev)
457 bat_priv->mesh_obj = NULL; 556 bat_priv->mesh_obj = NULL;
458} 557}
459 558
559/**
560 * batadv_sysfs_add_vlan - add all the needed sysfs objects for the new vlan
561 * @dev: netdev of the mesh interface
562 * @vlan: private data of the newly added VLAN interface
563 *
564 * Returns 0 on success and -ENOMEM if any of the structure allocations fails.
565 */
566int batadv_sysfs_add_vlan(struct net_device *dev,
567 struct batadv_softif_vlan *vlan)
568{
569 char vlan_subdir[sizeof(BATADV_SYSFS_VLAN_SUBDIR_PREFIX) + 5];
570 struct batadv_priv *bat_priv = netdev_priv(dev);
571 struct batadv_attribute **bat_attr;
572 int err;
573
574 if (vlan->vid & BATADV_VLAN_HAS_TAG) {
575 sprintf(vlan_subdir, BATADV_SYSFS_VLAN_SUBDIR_PREFIX "%hu",
576 vlan->vid & VLAN_VID_MASK);
577
578 vlan->kobj = kobject_create_and_add(vlan_subdir,
579 bat_priv->mesh_obj);
580 if (!vlan->kobj) {
581 batadv_err(dev, "Can't add sysfs directory: %s/%s\n",
582 dev->name, vlan_subdir);
583 goto out;
584 }
585 } else {
586 /* the untagged LAN uses the root folder to store its "VLAN
587 * specific attributes"
588 */
589 vlan->kobj = bat_priv->mesh_obj;
590 kobject_get(bat_priv->mesh_obj);
591 }
592
593 for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr) {
594 err = sysfs_create_file(vlan->kobj,
595 &((*bat_attr)->attr));
596 if (err) {
597 batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n",
598 dev->name, vlan_subdir,
599 ((*bat_attr)->attr).name);
600 goto rem_attr;
601 }
602 }
603
604 return 0;
605
606rem_attr:
607 for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr)
608 sysfs_remove_file(vlan->kobj, &((*bat_attr)->attr));
609
610 kobject_put(vlan->kobj);
611 vlan->kobj = NULL;
612out:
613 return -ENOMEM;
614}
615
616/**
617 * batadv_sysfs_del_vlan - remove all the sysfs objects for a given VLAN
618 * @bat_priv: the bat priv with all the soft interface information
619 * @vlan: the private data of the VLAN to destroy
620 */
621void batadv_sysfs_del_vlan(struct batadv_priv *bat_priv,
622 struct batadv_softif_vlan *vlan)
623{
624 struct batadv_attribute **bat_attr;
625
626 for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr)
627 sysfs_remove_file(vlan->kobj, &((*bat_attr)->attr));
628
629 kobject_put(vlan->kobj);
630 vlan->kobj = NULL;
631}
632
460static ssize_t batadv_show_mesh_iface(struct kobject *kobj, 633static ssize_t batadv_show_mesh_iface(struct kobject *kobj,
461 struct attribute *attr, char *buff) 634 struct attribute *attr, char *buff)
462{ 635{
diff --git a/net/batman-adv/sysfs.h b/net/batman-adv/sysfs.h
index 479acf4c16f4..c7d725de50ad 100644
--- a/net/batman-adv/sysfs.h
+++ b/net/batman-adv/sysfs.h
@@ -22,6 +22,12 @@
22 22
23#define BATADV_SYSFS_IF_MESH_SUBDIR "mesh" 23#define BATADV_SYSFS_IF_MESH_SUBDIR "mesh"
24#define BATADV_SYSFS_IF_BAT_SUBDIR "batman_adv" 24#define BATADV_SYSFS_IF_BAT_SUBDIR "batman_adv"
25/**
26 * BATADV_SYSFS_VLAN_SUBDIR_PREFIX - prefix of the subfolder that will be
27 * created in the sysfs hierarchy for each VLAN interface. The subfolder will
28 * be named "BATADV_SYSFS_VLAN_SUBDIR_PREFIX%vid".
29 */
30#define BATADV_SYSFS_VLAN_SUBDIR_PREFIX "vlan"
25 31
26struct batadv_attribute { 32struct batadv_attribute {
27 struct attribute attr; 33 struct attribute attr;
@@ -36,6 +42,10 @@ void batadv_sysfs_del_meshif(struct net_device *dev);
36int batadv_sysfs_add_hardif(struct kobject **hardif_obj, 42int batadv_sysfs_add_hardif(struct kobject **hardif_obj,
37 struct net_device *dev); 43 struct net_device *dev);
38void batadv_sysfs_del_hardif(struct kobject **hardif_obj); 44void batadv_sysfs_del_hardif(struct kobject **hardif_obj);
45int batadv_sysfs_add_vlan(struct net_device *dev,
46 struct batadv_softif_vlan *vlan);
47void batadv_sysfs_del_vlan(struct batadv_priv *bat_priv,
48 struct batadv_softif_vlan *vlan);
39int batadv_throw_uevent(struct batadv_priv *bat_priv, enum batadv_uev_type type, 49int batadv_throw_uevent(struct batadv_priv *bat_priv, enum batadv_uev_type type,
40 enum batadv_uev_action action, const char *data); 50 enum batadv_uev_action action, const char *data);
41 51