Skip to contentSkip to conversation

mac80211: IEEE802.11e/WMM TS management and DLS support

PATCH In review Zhu Yi 1 participant 1 message May 25, 2007 mac80211

lore
Share & tools
lore

Zhu Yi

author
#0 lore raw

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       |   18 +-
 net/mac80211/ieee80211_i.h     |   53 +++
 net/mac80211/ieee80211_iface.c |    8 +
 net/mac80211/ieee80211_sta.c   |  792 +++++++++++++++++++++++++++++++++++++++-
 net/mac80211/sta_info.c        |   34 ++-
 net/mac80211/sta_info.h        |   10 +-
 net/mac80211/wme.c             |   38 ++-
 7 files changed, 931 insertions(+), 22 deletions(-)
net/mac80211/ieee80211.c +13 -5
index 805c49a..e903197 100644
@@ -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(local, skb->data) == 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,7 @@ 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);
 		skb_queue_purge(&sdata->u.sta.skb_queue);
 		if (!local->ops->hw_scan &&
 		    local->scan_dev == sdata->dev) {
net/mac80211/ieee80211_i.h +53 -0

95 lines not on this page · raw message

net/mac80211/ieee80211_iface.c +8 -0
index a8612a8..c5c8bab 100644
@@ -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,10 @@ 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;
+
 		msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev);
 		sdata->bss = &msdata->u.ap;
 		break;
net/mac80211/ieee80211_sta.c +787 -5

853 lines not on this page · raw message

net/mac80211/sta_info.c +30 -4
index ab7b1f0..3d21ea0 100644
@@ -33,7 +33,7 @@ static void sta_info_hash_add(struct ieee80211_local *local,
 
 /* Caller must hold local->sta_lock */
 static void sta_info_hash_del(struct ieee80211_local *local,
-			      struct sta_info *sta)
+			      struct sta_info *sta, int dls)
 {
 	struct sta_info *s;
 
@@ -41,15 +41,19 @@ static void sta_info_hash_del(struct ieee80211_local *local,
 	if (!s)
 		return;
 	if (memcmp(s->addr, sta->addr, ETH_ALEN) == 0) {
+		if (dls && !s->dls_sta)
+			return;
 		local->sta_hash[STA_HASH(sta->addr)] = s->hnext;
 		return;
 	}
 
 	while (s->hnext && memcmp(s->hnext->addr, sta->addr, ETH_ALEN) != 0)
 		s = s->hnext;
-	if (s->hnext)
+	if (s->hnext) {
+		if (dls && !s->hnext->dls_sta)
+			return;
 		s->hnext = s->hnext->hnext;
-	else
+	} else
 		printk(KERN_ERR "%s: could not remove STA " MAC_FMT " from "
 		       "hash table\n", local->mdev->name, MAC_ARG(sta->addr));
 }
@@ -78,6 +82,28 @@ struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr)
 }
 EXPORT_SYMBOL(sta_info_get);
 
+struct sta_info *dls_info_get(struct ieee80211_local *local, u8 *addr)
+{
+	struct sta_info *sta;
+
+	spin_lock_bh(&local->sta_lock);
+	sta = local->sta_hash[STA_HASH(addr)];
+	while (sta) {
+		if (memcmp(sta->addr, addr, ETH_ALEN) == 0) {
+			if (!sta->dls_sta) {
+				sta = NULL;
+				break;
+			}
+			__sta_info_get(sta);
+			break;
+		}
+		sta = sta->hnext;
+	}
+	spin_unlock_bh(&local->sta_lock);
+
+	return sta;
+}
+
 int sta_info_min_txrate_get(struct ieee80211_local *local)
 {
 	struct sta_info *sta;
@@ -218,7 +244,7 @@ static void sta_info_remove(struct sta_info *sta)
 	struct ieee80211_local *local = sta->local;
 	struct ieee80211_sub_if_data *sdata;
 
-	sta_info_hash_del(local, sta);
+	sta_info_hash_del(local, sta, 0);
 	list_del(&sta->list);
 	sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
 	if (sta->flags & WLAN_STA_PS) {
net/mac80211/sta_info.h +8 -2
index 6a067a0..3eb3649 100644
@@ -102,8 +102,14 @@ struct sta_info {
 #ifdef CONFIG_MAC80211_DEBUGFS
 	int debugfs_registered;
 #endif
-	int assoc_ap; /* whether this is an AP that we are
-		       * associated with as a client */
+	int assoc_ap:1; /* whether this is an AP that we are
+			 * associated with as a client */
+	int dls_sta:1; /* whether this stations is a DLS peer of us */
+
+#define DLS_STATUS_OK		0
+#define DLS_STATUS_NOLINK	1
+	int dls_status;
+	u32 dls_timeout;
 
 #ifdef CONFIG_HOSTAPD_WPA_TESTING
 	u32 wpa_trigger;
net/mac80211/wme.c +32 -6
index ef3b3b0..9ff35e8 100644
@@ -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;
 		}
 	}
Signature · 1 line
1.5.0.rc2.g73a2