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 <[EMAIL PROTECTED]>

---

 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
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to