mac80211: IEEE802.11e/WMM TS management and DLS support
PATCH 2/3 mac80211: IEEE802.11e/WMM TS management and DLS support
This patch adds IEEE802.11e/WMM Traffic Stream (TS) Management and Direct Link Setup (DLS) non-AP QSTA mode support for mac80211.
--
net/mac80211/ieee80211.c +14 -5
@@ -1557,11 +1557,18 @@ static int ieee80211_subif_start_xmit(struct sk_buff *skb,memcpy (hdr.addr4, skb->data +ETH_ALEN ,ETH_ALEN ); hdrlen =30 ; }else if (sdata->type ==IEEE80211_IF_TYPE_STA ) { - fc |=IEEE80211_FCTL_TODS ; -/* BSSID SA DA */ -memcpy (hdr.addr1, sdata->u.sta.bssid,ETH_ALEN ); -memcpy (hdr.addr2, skb->data +ETH_ALEN ,ETH_ALEN ); -memcpy (hdr.addr3, skb->data,ETH_ALEN ); +if (dls_link_status (&sdata->u.sta, hdr.addr1) ==DLS_STATUS_OK ){ +/* DA SA BSSID */ +memcpy (hdr.addr1, skb->data,ETH_ALEN ); +memcpy (hdr.addr2, skb->data +ETH_ALEN ,ETH_ALEN ); +memcpy (hdr.addr3, sdata->u.sta.bssid,ETH_ALEN ); + }else { + fc |=IEEE80211_FCTL_TODS ; +/* BSSID SA DA */ +memcpy (hdr.addr1, sdata->u.sta.bssid,ETH_ALEN ); +memcpy (hdr.addr2, skb->data +ETH_ALEN ,ETH_ALEN ); +memcpy (hdr.addr3, skb->data,ETH_ALEN ); + } hdrlen =24 ; }else if (sdata->type ==IEEE80211_IF_TYPE_IBSS ) {/* DA SA BSSID */
@@ -2281,6 +2288,8 @@ static void ieee80211_if_shutdown(struct net_device *dev)case IEEE80211_IF_TYPE_IBSS : sdata->u.sta.state =IEEE80211_DISABLED ;del_timer_sync (&sdata->u.sta.timer); +del_timer_sync (&sdata->u.sta.admit_timer); +dls_info_stop (&sdata->u.sta);skb_queue_purge (&sdata->u.sta.skb_queue);if (!local->ops->hw_scan && local->scan_dev == sdata->dev) {
net/mac80211/ieee80211_i.h +67 -0
109 lines not on this page · raw message
net/mac80211/ieee80211_iface.c +9 -0
@@ -182,6 +182,10 @@ void ieee80211_if_set_type(struct net_device *dev, int type) (unsigned long) sdata);skb_queue_head_init (&ifsta->skb_queue); +init_timer (&ifsta->admit_timer); + ifsta->admit_timer.data = (unsigned long ) dev; + ifsta->admit_timer.function = ieee80211_admit_refresh; + ifsta->capab =WLAN_CAPABILITY_ESS ; ifsta->auth_algs =IEEE80211_AUTH_ALG_OPEN |IEEE80211_AUTH_ALG_SHARED_KEY ;
@@ -191,6 +195,11 @@ void ieee80211_if_set_type(struct net_device *dev, int type) ifsta->auto_channel_sel =1 ; ifsta->auto_bssid_sel =1 ; +/* Initialize non-AP QSTA QoS Params */ + ifsta->dot11EDCAAveragingPeriod =5 ; + ifsta->MPDUExchangeTime =0 ; +spin_lock_init (&ifsta->dls_lock); + msdata =IEEE80211_DEV_TO_SUB_IF (sdata->local->mdev); sdata->bss = &msdata->u.ap;break ;
net/mac80211/ieee80211_sta.c +893 -5
959 lines not on this page · raw message
net/mac80211/wme.c +32 -6
@@ -166,11 +166,13 @@ static inline int wme_downgrade_ac(struct sk_buff *skb)static inline int classify80211 (struct sk_buff *skb,struct Qdisc *qd) {struct ieee80211_local *local =wdev_priv (qd->dev->ieee80211_ptr); +struct ieee80211_sub_if_data *sdata =IEEE80211_DEV_TO_SUB_IF (qd->dev); +struct ieee80211_if_sta *ifsta = &sdata->u.sta;struct ieee80211_tx_packet_data *pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;unsigned short fc =le16_to_cpu (hdr->frame_control); -int qos; +int qos, tsid, dir;const int ieee802_1d_to_ac[8 ] = {2 ,3 ,3 ,2 ,1 ,1 ,0 ,0 };/* see if frame is data or non data frame */
@@ -197,14 +199,38 @@ static inline int classify80211(struct sk_buff *skb, struct Qdisc *qd) }/* use the data classifier to determine what 802.1d tag the -* data frame has */ +* data frame has */ skb->priority =classify_1d (skb, qd); + tsid =8 + skb->priority; + +/* FIXME: only uplink needs to be checked for Tx */ + dir =STA_TS_UPLINK ; + +if ((sdata->type ==IEEE80211_IF_TYPE_STA ) && + (local->wmm_acm &BIT (skb->priority))) { +switch (ifsta->ts_data[tsid][dir].status) { +case TS_STATUS_ACTIVE : +/* if TS Management is enabled, update used_time */ + ifsta->ts_data[tsid][dir].used_time_usec += + ifsta->MPDUExchangeTime; +break ; +case TS_STATUS_THROTTLING : +/* if admitted time is used up, refuse to send more */ +if (net_ratelimit ()) +printk (KERN_DEBUG "QoS packet throttling\n" ); +break ; +default : +break ; + } + } -/* incase we are a client verify acm is not set for this ac */ -while (unlikely (local->wmm_acm &BIT (skb->priority))) { +/* in case we are a client verify acm is not set for this ac */ +while ((local->wmm_acm &BIT (skb->priority)) && + !((sdata->type ==IEEE80211_IF_TYPE_STA ) && + (ifsta->ts_data[skb->priority +EDCA_TSID_MIN ][dir].status + ==TS_STATUS_ACTIVE ))) {if (wme_downgrade_ac (skb)) { -/* No AC with lower priority has acm=0, -* drop packet. */ +/* No AC with lower priority has acm=0, drop packet. */ return -1 ; } }
net/mac80211/ieee80211_i.h struct ieee80211_tx_stored_packet { · line 210
Quoted 12 lines · Zhu Yi
net/mac80211/ieee80211_i.h +12
-0+#define DLS_STATUS_OK 0 +#define DLS_STATUS_NOLINK 1 +#define DLS_STATUS_SETUP 2 +struct dls_info { +atomic_t refcnt; +int status; +u8 addr[ETH_ALEN ]; +struct dls_info *hnext;/* next entry in hash table list */ +u32 timeout; +u32 supp_rates; +}; +
The dls_info code looks like it was copied from the sta_info code and modified to store what you need. No good.
Instead, you should modify struct sta_info to hold the information necessary. This also allows the rate control to work properly. AFAICT, mac80211 will send all frames in DLS at the lowest rate because this code does not set up a sta_info for its destination. An appropriate sta_info entry is also necessary to be able to set up encryption properly. (of course, user space can also set up a sta_info entry after setting up a DLS entry and make things work correctly.. but that's dumb)
There is also a need for some way to notify the low level driver that it should not attempt any power management after a direct link is established (or that it should, once all DLS links are torn down). This callback/hook is also necessary to configure PS in hardware correctly in general and get rid of the management frame sniffing that iwlwifi is currently doing to achieve this.
Quoted 1 line
+ if (
dls_link_status(&sdata->u.sta, hdr.addr1)== DLS_STATUS_OK){
How is this line suppose to work? I don't see hdr.addr1 initialized at any point before this.
-Michael Wu
Quoted 4 lines · Michael Wu
The
dls_infocode looks like it was copied from thesta_infocode and modified to store what you need. No good.Instead, you should modify struct
sta_infoto hold the information necessary.
OK.
Quoted 3 lines
Quoted 1 line
+ if (
dls_link_status(&sdata->u.sta, hdr.addr1)== DLS_STATUS_OK){How is this line suppose to work? I don't see hdr.addr1 initialized at any point before this.
DLS must be setup before it can be used. The addr1 is inserted into the dls hash table when the QSTA received a successful DLS response or accepted a DLS request.
Thanks,
-yi
Quoted 9 lines · Zhu Yi
Quoted 4 lines
Quoted 1 line
+ if (
dls_link_status(&sdata->u.sta, hdr.addr1)== DLS_STATUS_OK){How is this line suppose to work? I don't see hdr.addr1 initialized at any point before this.
DLS must be setup before it can be used. The addr1 is inserted into the dls hash table when the QSTA received a successful DLS response or accepted a DLS request.
AFAICT, dls_link_status uses the second argument to look up the dls entry for the destination address. At this point, hdr.addr1 is not initialized to anything, so something is wrong here.
-Michael Wu
Quoted 3 lines · Michael Wu
AFAICT,
dls_link_statususes the second argument to look up the dls entry for the destination address. At this point, hdr.addr1 is not initialized to anything, so something is wrong here.
You are right. It should be
dls_link_status(&sdata->u.sta, skb->data);
Thanks,
-yi