All of lore.kernel.org
 help / color / mirror / Atom feed
From: Zhu Yi <yi.zhu@intel.com>
To: netdev@vger.kernel.org
Subject: [PATCH 6/6] d80211: add sysfs interface for QoS functions
Date: Thu, 14 Dec 2006 12:03:02 +0800	[thread overview]
Message-ID: <20061214040302.GA10689@mail.intel.com> (raw)

The sysfs interface here is only a proof of concept. It provides a way for
the userspace applications to use the advanced QoS features supported by
d80211 stack. The finial solution should be switched to cfg80211.

Signed-off-by: Zhu Yi <yi.zhu@intel.com>

---

 net/d80211/ieee80211_i.h     |   13 ++
 net/d80211/ieee80211_sysfs.c |  245 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 258 insertions(+), 0 deletions(-)

83d49f70af1f38c152d8bd3abd69756ec087622e
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index d09f65e..7904033 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -20,6 +20,7 @@
 #include <linux/workqueue.h>
 #include <linux/types.h>
 #include <linux/spinlock.h>
+#include <net/d80211_mgmt.h>
 #include "ieee80211_key.h"
 #include "sta_info.h"
 
@@ -329,6 +330,7 @@ struct ieee80211_sub_if_data {
         int channel_use_raw;
 
 	struct attribute_group *sysfs_group;
+	struct attribute_group *sysfs_qos_group;
 };
 
 #define IEEE80211_DEV_TO_SUB_IF(dev) netdev_priv(dev)
@@ -702,6 +704,17 @@ struct sta_info * ieee80211_ibss_add_sta
 					 u8 *addr);
 int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason);
 int ieee80211_sta_disassociate(struct net_device *dev, u16 reason);
+void ieee80211_send_addts(struct net_device *dev,
+			  struct ieee802_11_elem_tspec *tspec);
+void wmm_send_addts(struct net_device *dev,
+		    struct ieee802_11_elem_tspec *tspec);
+void ieee80211_send_delts(struct net_device *dev, u8 tsid, u8 direction,
+			  u32 medium_time);
+void wmm_send_delts(struct net_device *dev, u8 tsid, u8 direction,
+		    u32 medium_time);
+void ieee80211_send_dls_req(struct net_device *dev, struct dls_info *dls);
+void ieee80211_send_dls_teardown(struct net_device *dev, u8 *mac, u16 reason);
+void dls_info_add(struct ieee80211_local *local, struct dls_info *dls);
 void dls_info_stop(struct ieee80211_local *local);
 int dls_link_status(struct ieee80211_local *local, u8 *addr);
 
diff --git a/net/d80211/ieee80211_sysfs.c b/net/d80211/ieee80211_sysfs.c
index 6a60077..31dc1f4 100644
--- a/net/d80211/ieee80211_sysfs.c
+++ b/net/d80211/ieee80211_sysfs.c
@@ -13,6 +13,7 @@
 #include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
 #include <net/d80211.h>
+#include <net/d80211_mgmt.h>
 #include "ieee80211_i.h"
 #include "ieee80211_rate.h"
 
@@ -21,6 +22,15 @@
 #define to_net_dev(class) \
 	container_of(class, struct net_device, class_dev)
 
+/* For sysfs and debug only */
+static struct ieee802_11_elem_tspec _tspec;
+static u8 _dls_mac[ETH_ALEN];
+
+#define TSID _tspec.ts_info.tsid
+#define TSDIR _tspec.ts_info.direction
+#define TSUP _tspec.ts_info.up
+
+
 static inline int rtnl_lock_local(struct ieee80211_local *local)
 {
 	rtnl_lock();
@@ -657,6 +667,230 @@ static struct class ieee80211_class = {
 #endif
 };
 
+
+/* QoS sysfs entries */
+static ssize_t show_ts_info(struct class_device *dev, char *buf)
+{
+	/* TSID, Direction, UP */
+	return sprintf(buf, "%u %u %u\n", TSID, TSDIR, TSUP);
+}
+
+static ssize_t store_ts_info(struct class_device *dev, const char *buf,
+			     size_t len)
+{
+	unsigned int id, index, up;
+
+	if (sscanf(buf, "%u, %u, %u", &id, &index, &up) != 3) {
+		printk(KERN_ERR "%s: sscanf error\n", __FUNCTION__);
+		return -EINVAL;
+	}
+	if (id < 8 || id > 15) {
+		printk(KERN_ERR "invalid tsid %d\n", id);
+		return -EINVAL;
+	}
+	if ((index != 0) && (index != 1) && (index != 3)) {
+		printk(KERN_ERR "invalid direction %d\n", index);
+		return -EINVAL;
+	}
+	if (up < 0 || up > 7) {
+		printk(KERN_ERR "invalid UP %d\n", up);
+		return -EINVAL;
+	}
+	TSID = id;
+	TSDIR = index;
+	TSUP = up;
+	return len;
+}
+
+static CLASS_DEVICE_ATTR(ts_info, S_IWUSR|S_IRUGO, show_ts_info, store_ts_info);
+
+static ssize_t show_tspec(struct class_device *dev, char *buf)
+{
+	/* Nominal MSDU, Max MSDU, Min int, Max int, Inact int,
+	 * susp int, start, min rate, mean rate, peak rate,
+	 * max burst, delay, min phy, surp band, medium time */
+	return sprintf(buf,"%hu %hu %u %u %u %u %u %u %u %u %u %u %u %hu %hu\n",
+		       _tspec.nominal_msdu_size,
+		       _tspec.max_msdu_size,
+		       _tspec.min_service_interval,
+		       _tspec.max_service_interval,
+		       _tspec.inactivity_interval,
+		       _tspec.suspension_interval,
+		       _tspec.service_start_time,
+		       _tspec.min_data_rate,
+		       _tspec.mean_data_rate,
+		       _tspec.peak_data_rate,
+		       _tspec.burst_size,
+		       _tspec.delay_bound,
+		       _tspec.min_phy_rate,
+		       _tspec.surplus_band_allow,
+		       _tspec.medium_time);
+}
+
+static ssize_t store_tspec(struct class_device *dev, const char *buf,
+			   size_t len)
+{
+	if (sscanf(buf, "%hu %hu %u %u %u %u %u %u %u %u %u %u %u %hu %hu",
+		   &_tspec.nominal_msdu_size,
+		   &_tspec.max_msdu_size,
+		   &_tspec.min_service_interval,
+		   &_tspec.max_service_interval,
+		   &_tspec.inactivity_interval,
+		   &_tspec.suspension_interval,
+		   &_tspec.service_start_time,
+		   &_tspec.min_data_rate,
+		   &_tspec.mean_data_rate,
+		   &_tspec.peak_data_rate,
+		   &_tspec.burst_size,
+		   &_tspec.delay_bound,
+		   &_tspec.min_phy_rate,
+		   &_tspec.surplus_band_allow,
+		   &_tspec.medium_time) != 15) {
+		printk(KERN_ERR "%s: sscanf error\n", __FUNCTION__);
+		return -EINVAL;
+	}
+	/* Set default TSPEC Values */
+	_tspec.ts_info.access_policy = WLAN_TSINFO_EDCA;
+	_tspec.ts_info.apsd = WLAN_TSINFO_PSB_LEGACY;
+
+	return len;
+}
+
+static CLASS_DEVICE_ATTR(tspec, S_IWUSR|S_IRUGO, show_tspec, store_tspec);
+
+static ssize_t store_addts(struct class_device *dev, const char *buf,
+			   size_t len)
+{
+	struct net_device *netdev;
+
+	netdev = to_net_dev(dev);
+	ieee80211_send_addts(netdev, &_tspec);
+	return len;
+}
+
+static CLASS_DEVICE_ATTR(addts, S_IWUSR, NULL, store_addts);
+
+static ssize_t store_addts_wmm(struct class_device *dev, const char *buf,
+			       size_t len)
+{
+	struct net_device *netdev;
+
+	netdev = to_net_dev(dev);
+	wmm_send_addts(netdev, &_tspec);
+	return len;
+}
+
+static CLASS_DEVICE_ATTR(addts_wmm, S_IWUSR, NULL, store_addts_wmm);
+
+static ssize_t store_delts(struct class_device *dev, const char *buf,
+			   size_t len)
+{
+	struct net_device *netdev;
+
+	netdev = to_net_dev(dev);
+	ieee80211_send_delts(netdev, TSID, TSDIR, _tspec.medium_time);
+	return len;
+}
+
+static CLASS_DEVICE_ATTR(delts, S_IWUSR, NULL, store_delts);
+
+static ssize_t store_delts_wmm(struct class_device *dev, const char *buf,
+			       size_t len)
+{
+	struct net_device *netdev;
+
+	netdev = to_net_dev(dev);
+	wmm_send_delts(netdev, TSID, TSDIR, _tspec.medium_time);
+	return len;
+}
+
+static CLASS_DEVICE_ATTR(delts_wmm, S_IWUSR, NULL, store_delts_wmm);
+
+static ssize_t show_dls_mac(struct class_device *dev, char *buf)
+{
+	return sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X\n",
+		       _dls_mac[0], _dls_mac[1], _dls_mac[2],
+		       _dls_mac[3], _dls_mac[4], _dls_mac[5]);
+}
+
+static ssize_t store_dls_mac(struct class_device *dev, const char *buf,
+			     size_t len)
+{
+	if (sscanf(buf, "%x:%x:%x:%x:%x:%x",
+		   (int *)&_dls_mac[0], (int *)&_dls_mac[1],
+		   (int *)&_dls_mac[2], (int *)&_dls_mac[3],
+		   (int *)&_dls_mac[4], (int *)&_dls_mac[5]) != 6) {
+		printk(KERN_ERR "%s: sscanf error\n", __FUNCTION__);
+		return -EINVAL;
+	}
+	return len;
+}
+
+static CLASS_DEVICE_ATTR(dls_mac, S_IWUSR|S_IRUGO, show_dls_mac, store_dls_mac);
+
+static ssize_t show_dls_op(struct class_device *dev, char *buf)
+{
+	return sprintf(buf, "DLS Operation: Setup = 1; Teardown = 2\n");
+}
+
+static ssize_t store_dls_op(struct class_device *dev, const char *buf,
+			    size_t len)
+{
+	struct ieee80211_local *local;
+	struct net_device *netdev;
+	struct dls_info *dls;
+	unsigned int opt;
+
+	netdev = to_net_dev(dev);
+	local = netdev->ieee80211_ptr;
+
+	if (sscanf(buf, "%u", &opt) != 1) {
+		printk(KERN_ERR "%s: sscanf error\n", __FUNCTION__);
+		return -EINVAL;
+	}
+	switch (opt) {
+	case 1:
+		dls = kzalloc(sizeof(struct dls_info), GFP_KERNEL);
+		if (!dls) {
+			printk(KERN_ERR "No memory to allocate dls_info\n");
+			return -ENOMEM;
+		}
+		atomic_set(&dls->refcnt, 1);
+		dls->status = DLS_STATUS_SETUP;
+		dls->timeout = 0;
+		memcpy(dls->addr, _dls_mac, ETH_ALEN);
+		dls_info_add(local, dls);
+		ieee80211_send_dls_req(netdev, dls);
+		break;
+	case 2:
+		ieee80211_send_dls_teardown(netdev, _dls_mac,
+					    WLAN_REASON_QSTA_NOT_USE);
+		break;
+	default:
+		printk(KERN_ERR "Unknown DLS Operation: %d\n", opt);
+		break;
+	}
+	return len;
+}
+
+static CLASS_DEVICE_ATTR(dls_op, S_IWUSR|S_IRUGO, show_dls_op, store_dls_op);
+
+static struct attribute *ieee80211_qos_attrs[] = {
+	&class_device_attr_ts_info.attr,
+	&class_device_attr_tspec.attr,
+	&class_device_attr_addts.attr,
+	&class_device_attr_addts_wmm.attr,
+	&class_device_attr_delts.attr,
+	&class_device_attr_delts_wmm.attr,
+	&class_device_attr_dls_mac.attr,
+	&class_device_attr_dls_op.attr,
+	NULL
+};
+	
+static struct attribute_group ieee80211_qos_group = {
+	.name = "qos",
+	.attrs = ieee80211_qos_attrs,
+};
 void ieee80211_dev_sysfs_init(struct ieee80211_local *local)
 {
 	local->class_dev.class = &ieee80211_class;
@@ -696,6 +930,10 @@ void ieee80211_dev_sysfs_del(struct ieee
 static void __ieee80211_remove_if_group(struct kobject *kobj,
 					struct ieee80211_sub_if_data *sdata)
 {
+	if (sdata->sysfs_qos_group) {
+		sysfs_remove_group(kobj, sdata->sysfs_qos_group);
+		sdata->sysfs_qos_group = NULL;
+	}
 	if (sdata->sysfs_group) {
 		sysfs_remove_group(kobj, sdata->sysfs_group);
 		sdata->sysfs_group = NULL;
@@ -718,6 +956,7 @@ static int ieee80211_add_if_group(struct
 	switch (sdata->type) {
 	case IEEE80211_IF_TYPE_STA:
 		sdata->sysfs_group = &ieee80211_sta_group;
+		sdata->sysfs_qos_group = &ieee80211_qos_group;
 		break;
 	case IEEE80211_IF_TYPE_AP:
 		sdata->sysfs_group = &ieee80211_ap_group;
@@ -737,6 +976,12 @@ static int ieee80211_add_if_group(struct
 	res = sysfs_create_group(kobj, sdata->sysfs_group);
 	if (res)
 		sdata->sysfs_group = NULL;
+	if (sdata->sysfs_qos_group) {
+		res = sysfs_create_group(kobj, sdata->sysfs_qos_group);
+		if (res)
+			sdata->sysfs_qos_group = NULL;
+	}
+
 out:
 	return res;
 }
-- 
1.2.6

             reply	other threads:[~2006-12-14  4:15 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-12-14  4:03 Zhu Yi [this message]
2006-12-14  4:43 ` [PATCH 6/6] d80211: add sysfs interface for QoS functions Stephen Hemminger
2006-12-14 11:23 ` Jiri Benc
2006-12-14 15:04   ` Johannes Berg
2006-12-15  3:27   ` Zhu Yi
2006-12-15  5:35 ` Simon Barber
2006-12-18  9:18   ` Zhu Yi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20061214040302.GA10689@mail.intel.com \
    --to=yi.zhu@intel.com \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.