Search Linux Wireless

[RFC/T] mac80211: Implementation of SIOCSIWRATE

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: mabbas@xxxxxxxxxxxxxxx

The WEXT ioctl SIOCSIWRATE is not implemented in mac80211. This patch
adds the missing routine. It supports the 'auto' keyword, fixed rates,
and the combination of 'auto' and a fixed rate to select an upper bound.

Signed-off-by: mabbas@xxxxxxxxxxxxxxx
Signed-off-by: Larry Finger <Larry.Finger@xxxxxxxxxxxx>
---

Index: wireless-dev/net/mac80211/ieee80211_ioctl.c
===================================================================
--- wireless-dev.orig/net/mac80211/ieee80211_ioctl.c
+++ wireless-dev/net/mac80211/ieee80211_ioctl.c
@@ -2013,6 +2013,54 @@ static int ieee80211_ioctl_giwscan(struc
 }
 
 
+static int ieee80211_ioctl_siwrate(struct net_device *dev,
+				  struct iw_request_info *info,
+				  struct iw_param *rate, char *extra)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_hw_mode *mode;
+	int i;
+	u32 target_rate = rate->value /100000;
+	u32 fixed = rate->fixed;
+	u32 supp = 0;
+	struct ieee80211_sub_if_data *sdata;
+	struct sta_info *sta = NULL;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	mode = local->oper_hw_mode;
+	if (sdata->type != IEEE80211_IF_TYPE_STA)
+		return -EOPNOTSUPP;
+	sta = sta_info_get(local, sdata->u.sta.bssid);
+	if (!sta)
+		return -ENODEV;
+	/* value = -1, fixed = 0 means auto only, so we should use
+	 * all rates offered by AP
+	 * value = X, fixed = 1 means only rate X
+	 * value = X, fixed = 0 means all rates lower equal X */
+	for (i=0; i< mode->num_rates; i++) {
+		struct ieee80211_rate *rates = &mode->rates[i];
+		int target = rates->rate;
+
+		if (mode->mode == MODE_ATHEROS_TURBO ||
+		    mode->mode == MODE_ATHEROS_TURBOG)
+			target *= 2;
+		if ((target_rate == target) && fixed) {
+			supp |= BIT(i);
+			sta->txrate = i;
+			break;
+		}
+		if ((!fixed && (target_rate >= target)) || (rate->value < 0)) {
+			supp |= BIT(i);
+			if (target_rate == target)
+				sta->txrate = i;
+		}
+	}
+	sdata->u.sta.restricted_tx_rates = supp;
+	sta->restricted_tx_rates = supp;
+	sta_info_put(sta);
+	return 0;
+};
+
 static int ieee80211_ioctl_giwrate(struct net_device *dev,
 				  struct iw_request_info *info,
 				  struct iw_param *rate, char *extra)
@@ -3159,7 +3207,7 @@ static const iw_handler ieee80211_handle
 	(iw_handler) NULL,				/* SIOCGIWNICKN */
 	(iw_handler) NULL,				/* -- hole -- */
 	(iw_handler) NULL,				/* -- hole -- */
-	(iw_handler) NULL,				/* SIOCSIWRATE */
+	(iw_handler) ieee80211_ioctl_siwrate,		/* SIOCSIWRATE */
 	(iw_handler) ieee80211_ioctl_giwrate,		/* SIOCGIWRATE */
 	(iw_handler) ieee80211_ioctl_siwrts,		/* SIOCSIWRTS */
 	(iw_handler) ieee80211_ioctl_giwrts,		/* SIOCGIWRTS */
Index: wireless-dev/net/mac80211/ieee80211_i.h
===================================================================
--- wireless-dev.orig/net/mac80211/ieee80211_i.h
+++ wireless-dev/net/mac80211/ieee80211_i.h
@@ -269,6 +269,7 @@ struct ieee80211_if_sta {
 	unsigned long ibss_join_req;
 	struct sk_buff *probe_resp; /* ProbeResp template for IBSS */
 	u32 supp_rates_bits;
+	u32 restricted_tx_rates; /* bitmap of user restricted tx rate */
 
 	int wmm_last_param_set;
 };
Index: wireless-dev/net/mac80211/ieee80211_sta.c
===================================================================
--- wireless-dev.orig/net/mac80211/ieee80211_sta.c
+++ wireless-dev/net/mac80211/ieee80211_sta.c
@@ -1255,7 +1255,7 @@ static void ieee80211_rx_mgmt_assoc_resp
 				rates |= BIT(j);
 	}
 	sta->supp_rates = rates;
-
+	sta->restricted_tx_rates = ifsta->restricted_tx_rates;
 	if (elems.ht_extra_param && elems.ht_cap_param && elems.wmm_param &&
 	    ifsta->ht_enabled && local->ops->conf_ht){
 		int rc;
@@ -1500,6 +1500,7 @@ static void ieee80211_rx_bss_info(struct
 			 * supported to avoid issues with TX rate ctrl. */
 			sta->supp_rates = sdata->u.sta.supp_rates_bits;
 		}
+		sta->restricted_tx_rates = sdata->u.sta.restricted_tx_rates;
 		if (sta->supp_rates != prev_rates) {
 			printk(KERN_DEBUG "%s: updated supp_rates set for "
 			       MAC_FMT " based on beacon info (0x%x & 0x%x -> "
@@ -3176,6 +3177,8 @@ struct sta_info * ieee80211_ibss_add_sta
 		return NULL;
 
 	sta->supp_rates = sdata->u.sta.supp_rates_bits;
+	/* restricted suup rate if the user specifies it */
+	sta->restricted_tx_rates= sdata->u.sta.restricted_tx_rates;
 
 	rate_control_rate_init(sta, local);
 
Index: wireless-dev/net/mac80211/rc80211_simple.c
===================================================================
--- wireless-dev.orig/net/mac80211/rc80211_simple.c
+++ wireless-dev/net/mac80211/rc80211_simple.c
@@ -38,6 +38,7 @@ static void rate_control_rate_inc(struct
 	struct ieee80211_hw_mode *mode;
 	int i = sta->txrate;
 	int maxrate;
+	u32 supp;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
 	if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
@@ -45,6 +46,9 @@ static void rate_control_rate_inc(struct
 		return;
 	}
 
+	supp = sta->supp_rates & sta->restricted_tx_rates;
+	if (supp == 0)
+		supp = sta->supp_rates;
 	mode = local->oper_hw_mode;
 	maxrate = sdata->bss ? sdata->bss->max_ratectrl_rateidx : -1;
 
@@ -53,7 +57,7 @@ static void rate_control_rate_inc(struct
 
 	while (i + 1 < mode->num_rates) {
 		i++;
-		if (sta->supp_rates & BIT(i) &&
+		if (supp & BIT(i) &&
 		    mode->rates[i].flags & IEEE80211_RATE_SUPPORTED &&
 		    (maxrate < 0 || i <= maxrate)) {
 			sta->txrate = i;
@@ -69,6 +73,7 @@ static void rate_control_rate_dec(struct
 	struct ieee80211_sub_if_data *sdata;
 	struct ieee80211_hw_mode *mode;
 	int i = sta->txrate;
+	u32 supp;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
 	if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
@@ -80,9 +85,12 @@ static void rate_control_rate_dec(struct
 	if (i > mode->num_rates)
 		i = mode->num_rates;
 
+	supp = sta->supp_rates & sta->restricted_tx_rates;
+	if (supp == 0)
+		supp = sta->supp_rates;
 	while (i > 0) {
 		i--;
-		if (sta->supp_rates & BIT(i) &&
+		if (supp & BIT(i) &&
 		    mode->rates[i].flags & IEEE80211_RATE_SUPPORTED) {
 			sta->txrate = i;
 			break;
@@ -234,6 +242,7 @@ rate_control_simple_get_rate(void *priv,
 	struct sta_info *sta;
 	int rateidx, nonerp_idx;
 	u16 fc;
+	u32 supp;
 
 	memset(extra, 0, sizeof(*extra));
 
@@ -261,11 +270,14 @@ rate_control_simple_get_rate(void *priv,
 		rateidx = mode->num_rates - 1;
 
 	sta->last_txrate = rateidx;
+	supp = sta->supp_rates & sta->restricted_tx_rates;
+	if (supp == 0)
+		supp = sta->supp_rates;
 	nonerp_idx = rateidx;
 	while (nonerp_idx > 0 &&
 	       ((mode->rates[nonerp_idx].flags & IEEE80211_RATE_ERP) ||
 		!(mode->rates[nonerp_idx].flags & IEEE80211_RATE_SUPPORTED) ||
-		!(sta->supp_rates & BIT(nonerp_idx))))
+		!(supp & BIT(nonerp_idx))))
 		nonerp_idx--;
 	extra->nonerp = &mode->rates[nonerp_idx];
 
@@ -281,14 +293,19 @@ static void rate_control_simple_rate_ini
 {
 	struct ieee80211_hw_mode *mode;
 	int i;
+	u32 supp;
+
 	sta->txrate = 0;
 	mode = local->oper_hw_mode;
 	/* TODO: what is a good starting rate for STA? About middle? Maybe not
 	 * the lowest or the highest rate.. Could consider using RSSI from
 	 * previous packets? Need to have IEEE 802.1X auth succeed immediately
 	 * after assoc.. */
+	supp = sta->supp_rates & sta->restricted_tx_rates;
+	if (supp == 0)
+		supp = sta->supp_rates;
 	for (i = 0; i < mode->num_rates; i++) {
-		if ((sta->supp_rates & BIT(i)) &&
+		if ((supp & BIT(i)) &&
 		    (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED))
 			sta->txrate = i;
 	}
Index: wireless-dev/net/mac80211/sta_info.h
===================================================================
--- wireless-dev.orig/net/mac80211/sta_info.h
+++ wireless-dev/net/mac80211/sta_info.h
@@ -58,6 +58,9 @@ struct sta_info {
 	unsigned int wep_weak_iv_count; /* number of RX frames with weak IV */
 
 	unsigned long last_rx;
+	u32 restricted_tx_rates; /* bitmap of user restricted tx rates in
+				  * u.sta.restricted_tx_rates, if 0 use all
+				  * available rates */
 	u32 supp_rates; /* bitmap of supported rates in local->curr_rates */
 	int txrate; /* index in local->curr_rates */
 	int last_txrate; /* last rate used to send a frame to this STA */
-
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux