Commit 9e8571af authored by James Ketrenos's avatar James Ketrenos Committed by Jeff Garzik

[PATCH] ieee80211: Add QoS (WME) support to the ieee80211 subsystem

tree a3ad796273e98036eb0e9fc063225070fa24508a
parent 1b9c0aeb377abf8e4a43a86cff42382f74ca0259
author Mohamed Abbas <mabbas@linux.intel.com> 1124447069 -0500
committer James Ketrenos <jketreno@linux.intel.com> 1127313435 -0500

Add QoS (WME) support to the ieee80211 subsystem.

NOTE: This requires drivers that use the ieee80211 hard_start_xmit
(ipw2100 and ipw2200) to add the priority parameter to their callback.
Signed-off-by: default avatarJames Ketrenos <jketreno@linux.intel.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent 2c0aa2a5
...@@ -92,6 +92,7 @@ ...@@ -92,6 +92,7 @@
#define IEEE80211_STYPE_CFACK 0x0050 #define IEEE80211_STYPE_CFACK 0x0050
#define IEEE80211_STYPE_CFPOLL 0x0060 #define IEEE80211_STYPE_CFPOLL 0x0060
#define IEEE80211_STYPE_CFACKPOLL 0x0070 #define IEEE80211_STYPE_CFACKPOLL 0x0070
#define IEEE80211_STYPE_QOS_DATA 0x0080
#define IEEE80211_SCTL_FRAG 0x000F #define IEEE80211_SCTL_FRAG 0x000F
#define IEEE80211_SCTL_SEQ 0xFFF0 #define IEEE80211_SCTL_SEQ 0xFFF0
...@@ -153,6 +154,7 @@ const char *escape_essid(const char *essid, u8 essid_len); ...@@ -153,6 +154,7 @@ const char *escape_essid(const char *essid, u8 essid_len);
#define IEEE80211_DL_TX (1<<8) #define IEEE80211_DL_TX (1<<8)
#define IEEE80211_DL_RX (1<<9) #define IEEE80211_DL_RX (1<<9)
#define IEEE80211_DL_QOS (1<<31)
#define IEEE80211_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a) #define IEEE80211_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a)
#define IEEE80211_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a) #define IEEE80211_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a)
...@@ -166,6 +168,7 @@ const char *escape_essid(const char *essid, u8 essid_len); ...@@ -166,6 +168,7 @@ const char *escape_essid(const char *essid, u8 essid_len);
#define IEEE80211_DEBUG_DROP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_DROP, f, ## a) #define IEEE80211_DEBUG_DROP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_DROP, f, ## a)
#define IEEE80211_DEBUG_TX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_TX, f, ## a) #define IEEE80211_DEBUG_TX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_TX, f, ## a)
#define IEEE80211_DEBUG_RX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a) #define IEEE80211_DEBUG_RX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a)
#define IEEE80211_DEBUG_QOS(f, a...) IEEE80211_DEBUG(IEEE80211_DL_QOS, f, ## a)
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/wireless.h> #include <linux/wireless.h>
#include <linux/if_arp.h> /* ARPHRD_ETHER */ #include <linux/if_arp.h> /* ARPHRD_ETHER */
...@@ -493,6 +496,7 @@ enum ieee80211_mfie { ...@@ -493,6 +496,7 @@ enum ieee80211_mfie {
MFIE_TYPE_RSN = 48, MFIE_TYPE_RSN = 48,
MFIE_TYPE_RATES_EX = 50, MFIE_TYPE_RATES_EX = 50,
MFIE_TYPE_GENERIC = 221, MFIE_TYPE_GENERIC = 221,
MFIE_TYPE_QOS_PARAMETER = 222,
}; };
/* Minimal header; can be used for passing 802.11 frames with sufficient /* Minimal header; can be used for passing 802.11 frames with sufficient
...@@ -540,6 +544,29 @@ struct ieee80211_hdr_4addr { ...@@ -540,6 +544,29 @@ struct ieee80211_hdr_4addr {
u8 payload[0]; u8 payload[0];
} __attribute__ ((packed)); } __attribute__ ((packed));
struct ieee80211_hdr_3addrqos {
u16 frame_ctl;
u16 duration_id;
u8 addr1[ETH_ALEN];
u8 addr2[ETH_ALEN];
u8 addr3[ETH_ALEN];
u16 seq_ctl;
u8 payload[0];
u16 qos_ctl;
} __attribute__ ((packed));
struct ieee80211_hdr_4addrqos {
u16 frame_ctl;
u16 duration_id;
u8 addr1[ETH_ALEN];
u8 addr2[ETH_ALEN];
u8 addr3[ETH_ALEN];
u16 seq_ctl;
u8 addr4[ETH_ALEN];
u8 payload[0];
u16 qos_ctl;
} __attribute__ ((packed));
struct ieee80211_info_element { struct ieee80211_info_element {
u8 id; u8 id;
u8 len; u8 len;
...@@ -641,9 +668,68 @@ struct ieee80211_txb { ...@@ -641,9 +668,68 @@ struct ieee80211_txb {
#define MAX_WPA_IE_LEN 64 #define MAX_WPA_IE_LEN 64
#define NETWORK_EMPTY_ESSID (1<<0) #define NETWORK_EMPTY_ESSID (1<<0)
#define NETWORK_HAS_OFDM (1<<1) #define NETWORK_HAS_OFDM (1<<1)
#define NETWORK_HAS_CCK (1<<2) #define NETWORK_HAS_CCK (1<<2)
/* QoS structure */
#define NETWORK_HAS_QOS_PARAMETERS (1<<3)
#define NETWORK_HAS_QOS_INFORMATION (1<<4)
#define NETWORK_HAS_QOS_MASK (NETWORK_HAS_QOS_PARAMETERS | NETWORK_HAS_QOS_INFORMATION)
#define QOS_QUEUE_NUM 4
#define QOS_OUI_LEN 3
#define QOS_OUI_TYPE 2
#define QOS_ELEMENT_ID 221
#define QOS_OUI_INFO_SUB_TYPE 0
#define QOS_OUI_PARAM_SUB_TYPE 1
#define QOS_VERSION_1 1
#define QOS_AIFSN_MIN_VALUE 2
struct ieee80211_qos_information_element {
u8 elementID;
u8 length;
u8 qui[QOS_OUI_LEN];
u8 qui_type;
u8 qui_subtype;
u8 version;
u8 ac_info;
} __attribute__ ((packed));
struct ieee80211_qos_ac_parameter {
u8 aci_aifsn;
u8 ecw_min_max;
u16 tx_op_limit;
} __attribute__ ((packed));
struct ieee80211_qos_parameter_info {
struct ieee80211_qos_information_element info_element;
u8 reserved;
struct ieee80211_qos_ac_parameter ac_params_record[QOS_QUEUE_NUM];
} __attribute__ ((packed));
struct ieee80211_qos_parameters {
u16 cw_min[QOS_QUEUE_NUM];
u16 cw_max[QOS_QUEUE_NUM];
u8 aifs[QOS_QUEUE_NUM];
u8 flag[QOS_QUEUE_NUM];
u16 tx_op_limit[QOS_QUEUE_NUM];
} __attribute__ ((packed));
struct ieee80211_qos_data {
struct ieee80211_qos_parameters parameters;
int active;
int supported;
u8 param_count;
u8 old_param_count;
};
struct ieee80211_tim_parameters {
u8 tim_count;
u8 tim_period;
} __attribute__ ((packed));
/*******************************************************/
struct ieee80211_network { struct ieee80211_network {
/* These entries are used to identify a unique network */ /* These entries are used to identify a unique network */
...@@ -653,6 +739,8 @@ struct ieee80211_network { ...@@ -653,6 +739,8 @@ struct ieee80211_network {
u8 ssid[IW_ESSID_MAX_SIZE + 1]; u8 ssid[IW_ESSID_MAX_SIZE + 1];
u8 ssid_len; u8 ssid_len;
struct ieee80211_qos_data qos_data;
/* These are network statistics */ /* These are network statistics */
struct ieee80211_rx_stats stats; struct ieee80211_rx_stats stats;
u16 capability; u16 capability;
...@@ -672,6 +760,7 @@ struct ieee80211_network { ...@@ -672,6 +760,7 @@ struct ieee80211_network {
size_t wpa_ie_len; size_t wpa_ie_len;
u8 rsn_ie[MAX_WPA_IE_LEN]; u8 rsn_ie[MAX_WPA_IE_LEN];
size_t rsn_ie_len; size_t rsn_ie_len;
struct ieee80211_tim_parameters tim;
struct list_head list; struct list_head list;
}; };
...@@ -769,10 +858,13 @@ struct ieee80211_device { ...@@ -769,10 +858,13 @@ struct ieee80211_device {
void (*set_security) (struct net_device * dev, void (*set_security) (struct net_device * dev,
struct ieee80211_security * sec); struct ieee80211_security * sec);
int (*hard_start_xmit) (struct ieee80211_txb * txb, int (*hard_start_xmit) (struct ieee80211_txb * txb,
struct net_device * dev); struct net_device * dev, int pri);
int (*reset_port) (struct net_device * dev); int (*reset_port) (struct net_device * dev);
int (*is_queue_full) (struct net_device * dev, int pri); int (*is_queue_full) (struct net_device * dev, int pri);
int (*handle_management) (struct net_device * dev,
struct ieee80211_network * network, u16 type);
/* Typical STA methods */ /* Typical STA methods */
int (*handle_auth) (struct net_device * dev, int (*handle_auth) (struct net_device * dev,
struct ieee80211_auth * auth); struct ieee80211_auth * auth);
...@@ -854,11 +946,14 @@ extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, ...@@ -854,11 +946,14 @@ extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee,
extern inline int ieee80211_get_hdrlen(u16 fc) extern inline int ieee80211_get_hdrlen(u16 fc)
{ {
int hdrlen = IEEE80211_3ADDR_LEN; int hdrlen = IEEE80211_3ADDR_LEN;
u16 stype = WLAN_FC_GET_STYPE(fc);
switch (WLAN_FC_GET_TYPE(fc)) { switch (WLAN_FC_GET_TYPE(fc)) {
case IEEE80211_FTYPE_DATA: case IEEE80211_FTYPE_DATA:
if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS)) if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))
hdrlen = IEEE80211_4ADDR_LEN; hdrlen = IEEE80211_4ADDR_LEN;
if (stype & IEEE80211_STYPE_QOS_DATA)
hdrlen += 2;
break; break;
case IEEE80211_FTYPE_CTL: case IEEE80211_FTYPE_CTL:
switch (WLAN_FC_GET_STYPE(fc)) { switch (WLAN_FC_GET_STYPE(fc)) {
......
This diff is collapsed.
...@@ -465,7 +465,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -465,7 +465,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
if (txb) { if (txb) {
int ret = (*ieee->hard_start_xmit) (txb, dev); int ret = (*ieee->hard_start_xmit) (txb, dev, priority);
if (ret == 0) { if (ret == 0) {
stats->tx_packets++; stats->tx_packets++;
stats->tx_bytes += txb->payload_size; stats->tx_bytes += txb->payload_size;
...@@ -500,6 +500,7 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee, ...@@ -500,6 +500,7 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee,
unsigned long flags; unsigned long flags;
struct net_device_stats *stats = &ieee->stats; struct net_device_stats *stats = &ieee->stats;
struct sk_buff *skb_frag; struct sk_buff *skb_frag;
int priority = -1;
spin_lock_irqsave(&ieee->lock, flags); spin_lock_irqsave(&ieee->lock, flags);
...@@ -540,7 +541,7 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee, ...@@ -540,7 +541,7 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee,
spin_unlock_irqrestore(&ieee->lock, flags); spin_unlock_irqrestore(&ieee->lock, flags);
if (txb) { if (txb) {
if ((*ieee->hard_start_xmit) (txb, ieee->dev) == 0) { if ((*ieee->hard_start_xmit) (txb, ieee->dev, priority) == 0) {
stats->tx_packets++; stats->tx_packets++;
stats->tx_bytes += txb->payload_size; stats->tx_bytes += txb->payload_size;
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment