linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Setting MCS rate on injected packets does not work properly (with patches)
@ 2010-08-08 19:24 Daniel Haid
  2010-08-09 16:09 ` Björn Smedman
       [not found] ` <201008092149.14462.d.haid@gogi.tv>
  0 siblings, 2 replies; 4+ messages in thread
From: Daniel Haid @ 2010-08-08 19:24 UTC (permalink / raw)
  To: linux-wireless

Hello,

I have applied some old patches that were posted here,
that allow to set the rate via the radiotap header for
injected packets.

Additionally I had to comment out the call
to ieee80211_tx_h_rate_ctrl in net/mac80211/tx.c
for anything to work.

I have patched two stations. My problem is as follows:

When I use hostapd on one station and enable HT I get
rates of about 60MBit/s.

But when I inject packets manually and I set the MCS index
the MCS index gets reported properly at the other station.
However no matter what index I choose, I never get rates
higher than 10MBit/s  (I wrote a program that reads monitor
mode packets with libpcap and sends them to a tun device
and everything that comes from the tun device is injected
with libpcap - then I measured the rate for UDP packets sent
trough this connection).

Is there anything that has to be set up first for MCS mode to
work properly? What else can I do?

Thank you.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Setting MCS rate on injected packets does not work properly (with patches)
  2010-08-08 19:24 Setting MCS rate on injected packets does not work properly (with patches) Daniel Haid
@ 2010-08-09 16:09 ` Björn Smedman
  2010-08-10 16:58   ` Luis R. Rodriguez
       [not found] ` <201008092149.14462.d.haid@gogi.tv>
  1 sibling, 1 reply; 4+ messages in thread
From: Björn Smedman @ 2010-08-09 16:09 UTC (permalink / raw)
  To: Daniel Haid; +Cc: linux-wireless

On Sun, Aug 8, 2010 at 9:24 PM, Daniel Haid <d.haid@gogi.tv> wrote:
> Hello,

> When I use hostapd on one station and enable HT I get
> rates of about 60MBit/s.
>
> But when I inject packets manually and I set the MCS index
> the MCS index gets reported properly at the other station.
> However no matter what index I choose, I never get rates
> higher than 10MBit/s  (I wrote a program that reads monitor
> mode packets with libpcap and sends them to a tun device
> and everything that comes from the tun device is injected
> with libpcap - then I measured the rate for UDP packets sent
> trough this connection).

One reason for this is aggregation: injected packets are not
aggregated. Depending on your setup that could be the whole
explanation.

Also, a single fixed MCS index in the first slot of the tx control
rates array will not perform as well as e.g. minstrel_ht, especially
not if your radio environment is noisy.

10 Mbit/s sounds a bit slow though if you say you can get 60 in ap -
sta mode. Perhaps you are cpu limited?

/Björn

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Setting MCS rate on injected packets (includes patch)
       [not found]   ` <AANLkTik_78KB4QV210TbTxFRveL-e7yPwsxL-DEizRcX@mail.gmail.com>
@ 2010-08-10 14:48     ` Daniel Haid
  0 siblings, 0 replies; 4+ messages in thread
From: Daniel Haid @ 2010-08-10 14:48 UTC (permalink / raw)
  To: linux-wireless; +Cc: Björn Smedman

I have still not been able to successfully inject packets with a
throughput >10Mbits/s. I have included the patch that I used.
I have combined two old patches that I found on this list.

Please tell me if this can even work in principle, or if I have
to make any changes.

I am injecting packets with libpcap and use the following headers:

static const uint8_t radiotap_header[] = {
        0x00, 0x00, // <-- radiotap version
        0x0e, 0x00, // <- radiotap header length
        0x06, 0x00, 0x0b, 0x00, // <-- bitmap
        0x00, // <-- flags
        0x00, // <-- rate
        0x00, // <-- rts retries
        0x01, // <-- data retries
        0x02, 0x01 // <-- mcs index, flags 1=40MHz 2=shortgi
};

static const uint8_t ieee_header[] = {
        0x88, 0x00, 0x00, 0x00,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
        0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
        0x00, 0x00,

        0x00, 0x00,
        0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00
};

I also tried different MCS indexes, and using the real mac-adresses instead, but never
am I able to get more than 10MBits/s throughput.

diff -ru a/Documentation/networking/mac80211-injection.txt b/Documentation/networking/mac80211-injection.txt
--- a/Documentation/networking/mac80211-injection.txt	2010-08-09 23:30:51.375120261 +0200
+++ b/Documentation/networking/mac80211-injection.txt	2010-08-09 23:56:11.470652572 +0200
@@ -23,6 +23,17 @@
    IEEE80211_RADIOTAP_F_FRAG: frame will be fragmented if longer than the
 			      current fragmentation threshold.
 
+ * IEEE80211_RADIOTAP_RATE: Transmit rate will be set to the requested value if
+			    it's available.  Rate control will not be used for
+			    the frame.
+
+ * IEEE80211_RADIOTAP_DATA_RETRIES: Retry count will be set to the requested
+				    value.  This parameter can only be used in
+				    conjunction with IEEE80211_RADIOTAP_RATE.
+
+ * IEEE80211_RADIOTAP_RATE_MCS: Transmit rate will be set to the requested MCS
+                                index.  Rate control will not be used for the
+                                frame.
 
 The injection code can also skip all other currently defined radiotap fields
 facilitating replay of captured radiotap headers directly.
diff -ru a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h
--- a/include/net/ieee80211_radiotap.h	2010-08-09 23:29:56.819125364 +0200
+++ b/include/net/ieee80211_radiotap.h	2010-08-09 23:11:33.962618255 +0200
@@ -174,6 +174,11 @@
  *
  *     Number of rts retries a transmitted frame used.
  *
+ * IEEE80211_RADIOTAP_RATE_MCS       2 x u8          data, bitmap
+ *
+ *     First byte is the MCS index of the rate,
+ *     second one has flags about channel width and guard interval
+ *
  * IEEE80211_RADIOTAP_DATA_RETRIES      u8           data
  *
  *     Number of unicast retries a transmitted frame used.
@@ -198,6 +203,7 @@
 	IEEE80211_RADIOTAP_TX_FLAGS = 15,
 	IEEE80211_RADIOTAP_RTS_RETRIES = 16,
 	IEEE80211_RADIOTAP_DATA_RETRIES = 17,
+	IEEE80211_RADIOTAP_RATE_MCS = 19,
 
 	/* valid in every it_present bitmap, even vendor namespaces */
 	IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
@@ -245,6 +251,10 @@
 #define IEEE80211_RADIOTAP_F_TX_CTS	0x0002	/* used cts 'protection' */
 #define IEEE80211_RADIOTAP_F_TX_RTS	0x0004	/* used rts/cts handshake */
 
+/* For IEEE80211_RADIOTAP_RATE_MCS */
+#define IEEE80211_RADIOTAP_RATE_MCS_40MHZ	0x01 /* 40 MHz channel width */
+#define IEEE80211_RADIOTAP_RATE_MCS_SHORT_GI	0x02 /* short guard interval */
+
 /* Ugly macro to convert literal channel numbers into their mhz equivalents
  * There are certianly some conditions that will break this (like feeding it '30')
  * but they shouldn't arise since nothing talks on channel 30. */
diff -ru a/include/net/mac80211.h b/include/net/mac80211.h
--- a/include/net/mac80211.h	2010-08-09 23:29:57.398627648 +0200
+++ b/include/net/mac80211.h	2010-08-09 23:59:45.182646922 +0200
@@ -287,6 +287,7 @@
  * @IEEE80211_TX_CTL_LDPC: tells the driver to use LDPC for this frame
  * @IEEE80211_TX_CTL_STBC: Enables Space-Time Block Coding (STBC) for this
  *	frame and selects the maximum number of streams that it can use.
+ * @IEEE80211_TX_CTL_RC_BYPASS: Don't use rate control on the frame.
  */
 enum mac80211_tx_control_flags {
 	IEEE80211_TX_CTL_REQ_TX_STATUS		= BIT(0),
@@ -313,6 +314,7 @@
 	IEEE80211_TX_CTL_LDPC			= BIT(22),
 	IEEE80211_TX_CTL_STBC			= BIT(23) | BIT(24),
 #define IEEE80211_TX_CTL_STBC_SHIFT		23
+	IEEE80211_TX_CTL_RC_BYPASS                 = BIT(25),
 };
 
 /**
@@ -1929,7 +1931,7 @@
  * The TX headroom reserved by mac80211 for its own tx_status functions.
  * This is enough for the radiotap header.
  */
-#define IEEE80211_TX_STATUS_HEADROOM	13
+#define IEEE80211_TX_STATUS_HEADROOM	14
 
 /**
  * ieee80211_tx_status - transmit status callback
diff -ru a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
--- a/net/mac80211/ieee80211_i.h	2010-08-09 23:26:40.731120745 +0200
+++ b/net/mac80211/ieee80211_i.h	2010-08-09 23:13:27.235118320 +0200
@@ -1084,6 +1084,7 @@
 	u8 padding_for_rate;
 	__le16 tx_flags;
 	u8 data_retries;
+	u8 mcs; /*HT rates*/
 } __attribute__ ((packed));
 
 
diff -ru a/net/mac80211/rx.c b/net/mac80211/rx.c
--- a/net/mac80211/rx.c	2010-08-09 23:26:40.694618415 +0200
+++ b/net/mac80211/rx.c	2010-08-09 23:13:27.270630234 +0200
@@ -81,7 +81,8 @@
 		len += 8;
 	if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
 		len += 1;
-
+	if (status->flag & RX_FLAG_HT)
+		len += 2;
 	if (len & 1) /* padding for RX_FLAGS if necessary */
 		len++;
 
@@ -137,19 +138,11 @@
 	pos++;
 
 	/* IEEE80211_RADIOTAP_RATE */
-	if (status->flag & RX_FLAG_HT) {
-		/*
-		 * TODO: add following information into radiotap header once
-		 * suitable fields are defined for it:
-		 * - MCS index (status->rate_idx)
-		 * - HT40 (status->flag & RX_FLAG_40MHZ)
-		 * - short-GI (status->flag & RX_FLAG_SHORT_GI)
-		 */
+	rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
+	if (status->flag & RX_FLAG_HT)
 		*pos = 0;
-	} else {
-		rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
+	else
 		*pos = rate->bitrate / 5;
-	}
 	pos++;
 
 	/* IEEE80211_RADIOTAP_CHANNEL */
@@ -193,6 +186,20 @@
 		rx_flags |= IEEE80211_RADIOTAP_F_RX_BADPLCP;
 	put_unaligned_le16(rx_flags, pos);
 	pos += 2;
+
+	/* IEEE80211_RADIOTAP_RATE_MCS */
+	if (status->flag & RX_FLAG_HT) {
+		rthdr->it_present |=
+			cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE_MCS);
+		*pos = status->rate_idx;
+		pos++;
+		*pos = 0;
+		if (status->flag & RX_FLAG_40MHZ)
+			*pos |= IEEE80211_RADIOTAP_RATE_MCS_40MHZ;
+		if (status->flag & RX_FLAG_SHORT_GI)
+			*pos |= IEEE80211_RADIOTAP_RATE_MCS_SHORT_GI;
+		pos++;
+	}
 }
 
 /*
diff -ru a/net/mac80211/status.c b/net/mac80211/status.c
--- a/net/mac80211/status.c	2010-08-09 23:26:40.714691704 +0200
+++ b/net/mac80211/status.c	2010-08-09 23:13:26.422694046 +0200
@@ -352,6 +352,16 @@
 	    !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS))
 		rthdr->rate = sband->bitrates[
 				info->status.rates[0].idx].bitrate / 5;
+	/* HT rates */
+	if (info->status.rates[0].flags & IEEE80211_TX_RC_MCS) {
+		rthdr->hdr.it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE_MCS);
+		rthdr->rate = 0;
+		rthdr->mcs = info->status.rates[0].idx;
+		if (info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+			rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_RATE_MCS_40MHZ);
+		if (info->status.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)
+			rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_RATE_MCS_SHORT_GI);
+	}
 
 	/* for now report the total retry_count */
 	rthdr->data_retries = retry_count;
diff -ru a/net/mac80211/tx.c b/net/mac80211/tx.c
--- a/net/mac80211/tx.c	2010-08-09 23:26:40.558625717 +0200
+++ b/net/mac80211/tx.c	2010-08-09 23:58:17.347120109 +0200
@@ -1068,6 +1068,49 @@
 				tx->flags |= IEEE80211_TX_FRAGMENTED;
 			break;
 
+		case IEEE80211_RADIOTAP_RATE: {
+			info->control.rates[0].idx = 0;
+			if (*iterator.this_arg) {
+				int i;
+				for (i = 0; i < sband->n_bitrates; i++)
+					if (sband->bitrates[i].bitrate <=
+						*iterator.this_arg * 5) {
+						info->control.rates[0].idx = i;
+						break;
+					}
+			}
+			info->flags |= IEEE80211_TX_CTL_RC_BYPASS;
+			info->control.rates[0].flags = 0;
+			info->control.rates[1].idx = -1;
+			info->control.rates[2].idx = -1;
+			info->control.rates[3].idx = -1;
+			info->control.rates[4].idx = -1;
+			break;
+		}
+
+		case IEEE80211_RADIOTAP_DATA_RETRIES:
+			info->control.rates[0].count = *iterator.this_arg;
+			break;
+
+		case IEEE80211_RADIOTAP_RATE_MCS: {
+			u8 flags;
+			if (info->control.rates[0].idx)
+				break;
+			flags = *(iterator.this_arg + 1);
+			info->control.rates[0].idx = *iterator.this_arg;
+
+			info->flags |= IEEE80211_TX_CTL_RC_BYPASS;
+			info->control.rates[0].flags |=
+				IEEE80211_TX_RC_MCS;
+			if (flags & IEEE80211_RADIOTAP_RATE_MCS_40MHZ)
+				info->control.rates[0].flags |=
+				IEEE80211_TX_RC_40_MHZ_WIDTH;
+			if (flags & IEEE80211_RADIOTAP_RATE_MCS_SHORT_GI)
+				info->control.rates[0].flags |=
+				IEEE80211_TX_RC_SHORT_GI;
+			break;
+		}
+
 		/*
 		 * Please update the file
 		 * Documentation/networking/mac80211-injection.txt
@@ -1314,7 +1357,8 @@
 	CALL_TXH(ieee80211_tx_h_ps_buf);
 	CALL_TXH(ieee80211_tx_h_select_key);
 	CALL_TXH(ieee80211_tx_h_sta);
-	if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL))
+	if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) &&
+	    !(info->flags & IEEE80211_TX_CTL_RC_BYPASS))
 		CALL_TXH(ieee80211_tx_h_rate_ctrl);
 
 	if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION))
diff -ru a/net/wireless/radiotap.c b/net/wireless/radiotap.c
--- a/net/wireless/radiotap.c	2010-08-09 23:26:28.263132773 +0200
+++ b/net/wireless/radiotap.c	2010-08-09 23:12:46.366644666 +0200
@@ -39,6 +39,7 @@
 	[IEEE80211_RADIOTAP_TX_FLAGS] = { .align = 2, .size = 2, },
 	[IEEE80211_RADIOTAP_RTS_RETRIES] = { .align = 1, .size = 1, },
 	[IEEE80211_RADIOTAP_DATA_RETRIES] = { .align = 1, .size = 1, },
+	[IEEE80211_RADIOTAP_RATE_MCS] = { .align = 1, .size = 2, }
 	/*
 	 * add more here as they are defined in radiotap.h
 	 */

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Setting MCS rate on injected packets does not work properly (with patches)
  2010-08-09 16:09 ` Björn Smedman
@ 2010-08-10 16:58   ` Luis R. Rodriguez
  0 siblings, 0 replies; 4+ messages in thread
From: Luis R. Rodriguez @ 2010-08-10 16:58 UTC (permalink / raw)
  To: Björn Smedman; +Cc: Daniel Haid, linux-wireless

2010/8/9 Björn Smedman <bjorn.smedman@venatech.se>:
> On Sun, Aug 8, 2010 at 9:24 PM, Daniel Haid <d.haid@gogi.tv> wrote:
>> Hello,
>
>> When I use hostapd on one station and enable HT I get
>> rates of about 60MBit/s.
>>
>> But when I inject packets manually and I set the MCS index
>> the MCS index gets reported properly at the other station.
>> However no matter what index I choose, I never get rates
>> higher than 10MBit/s  (I wrote a program that reads monitor
>> mode packets with libpcap and sends them to a tun device
>> and everything that comes from the tun device is injected
>> with libpcap - then I measured the rate for UDP packets sent
>> trough this connection).
>
> One reason for this is aggregation: injected packets are not
> aggregated. Depending on your setup that could be the whole
> explanation.

You don't need to use aggregation for all frames, aggregation is just
one technique that you can use for 802.11n, ath9k is an example driver
that chooses to always use aggregation though.

> Also, a single fixed MCS index in the first slot of the tx control
> rates array will not perform as well as e.g. minstrel_ht, especially
> not if your radio environment is noisy.

You might want to look at how the passed rate gets mapped to a
hardware rate on the driver you are using.

  Luis

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2010-08-10 16:58 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-08-08 19:24 Setting MCS rate on injected packets does not work properly (with patches) Daniel Haid
2010-08-09 16:09 ` Björn Smedman
2010-08-10 16:58   ` Luis R. Rodriguez
     [not found] ` <201008092149.14462.d.haid@gogi.tv>
     [not found]   ` <AANLkTik_78KB4QV210TbTxFRveL-e7yPwsxL-DEizRcX@mail.gmail.com>
2010-08-10 14:48     ` Setting MCS rate on injected packets (includes patch) Daniel Haid

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).