2022-10-22 21:39:17

by Bitterblue Smith

[permalink] [raw]
Subject: How to use the rate control in mac80211?

Hi!

What does a driver (rtl8xxxu) need to do to make the rate control work?

I thought it's like this:
1) don't set HAS_RATE_CONTROL
2) tell the chip to use the rate from tx_info->control.rates[0]
3) report if the frame was acked or not

But it's not that easy. I'm always getting MCS0. Currently rtl8xxxu
doesn't ask the chip for TX reports and always sets IEEE80211_TX_STAT_ACK.
I thought this would get me MCS7 for all data frames, but it doesn't.

The rc_stats file from debugfs looks like this after using the connection for a while:

best ____________rate__________ ____statistics___ _____last____ ______sum-of________
mode guard # rate [name idx airtime max_tp] [avg(tp) avg(prob)] [retry|suc|att] [#success | #attempts]
HT20 LGI 1 ABCDPS MCS0 0 1477 5.6 0.0 0.0 1 0 0 0 0
HT20 LGI 1 S MCS1 1 738 10.6 0.0 0.0 0 0 0 0 0
HT20 LGI 1 MCS2 2 492 14.9 0.0 0.0 0 0 0 0 0
HT20 LGI 1 MCS3 3 369 18.8 0.0 0.0 0 0 0 0 0
HT20 LGI 1 S MCS4 4 246 25.4 0.0 0.0 0 0 0 0 0
HT20 LGI 1 MCS5 5 185 30.7 0.0 0.0 0 0 0 0 0
HT20 LGI 1 MCS6 6 164 33.0 0.0 0.0 0 0 0 0 0
HT20 LGI 1 MCS7 7 148 35.1 0.0 0.0 0 0 0 0 0
HT20 SGI 1 S MCS0 64 1329 6.2 0.0 0.0 0 0 0 0 0
HT20 SGI 1 MCS1 65 665 11.6 0.0 0.0 0 0 0 0 0
HT20 SGI 1 MCS2 66 443 16.3 0.0 0.0 0 0 0 0 0
HT20 SGI 1 MCS3 67 332 20.4 0.0 0.0 0 0 0 0 0
HT20 SGI 1 S MCS4 68 222 27.2 0.0 0.0 0 0 0 0 0
HT20 SGI 1 MCS5 69 166 32.8 0.0 0.0 0 0 0 0 0
HT20 SGI 1 MCS6 70 148 35.1 0.0 0.0 0 0 0 0 0
HT20 SGI 1 MCS7 71 133 37.3 0.0 0.0 0 0 0 0 0
HT40 LGI 1 S MCS0 128 711 10.9 0.0 0.0 0 0 0 0 0
HT40 LGI 1 MCS1 129 356 19.4 0.0 0.0 0 0 0 0 0
HT40 LGI 1 MCS2 130 237 26.0 0.0 0.0 0 0 0 0 0
HT40 LGI 1 MCS3 131 178 31.4 0.0 0.0 0 0 0 0 0
HT40 LGI 1 S MCS4 132 119 39.6 0.0 0.0 0 0 0 0 0
HT40 LGI 1 MCS5 133 89 45.6 0.0 0.0 0 0 0 0 0
HT40 LGI 1 MCS6 134 79 48.0 0.0 0.0 0 0 0 0 0
HT40 LGI 1 MCS7 135 71 50.2 0.0 0.0 0 0 0 0 0
HT40 SGI 1 S MCS0 192 640 12.0 0.0 0.0 0 0 0 0 0
HT40 SGI 1 MCS1 193 320 21.0 0.0 0.0 0 0 0 0 0
HT40 SGI 1 MCS2 194 214 27.9 0.0 0.0 0 0 0 0 0
HT40 SGI 1 MCS3 195 160 33.5 0.0 0.0 0 0 0 0 0
HT40 SGI 1 MCS4 196 107 41.8 0.0 0.0 0 0 0 0 0
HT40 SGI 1 MCS5 197 80 47.8 0.0 0.0 0 0 0 0 0
HT40 SGI 1 MCS6 198 71 50.1 0.0 0.0 0 0 0 0 0
HT40 SGI 1 MCS7 199 64 52.2 0.0 0.0 0 0 0 0 0

Total packet count:: ideal 4 lookaround 1
Average # of aggregated frames per A-MPDU: 1.0

It looks like the rate control algorithm is not getting any information. (Also, why are no CCK rates listed? With mt7601u there are CCK rates too.)

What to do?


2022-10-23 16:08:52

by Johannes Berg

[permalink] [raw]
Subject: Re: How to use the rate control in mac80211?

Hi,

> I thought it's like this:
> 1) don't set HAS_RATE_CONTROL

yes

> 2) tell the chip to use the rate from tx_info->control.rates[0]

I'd prefer you didn't, that's also very limited :-)

> 3) report if the frame was acked or not

Kind of.

It'd be better if new drivers used sta_rate_tbl_update method, so it'd
be something like

1) don't set HAS_RATE_CONTROL
2) implement sta_rate_tbl_update(), using the table of rates given
there to instruct the device to transmit frames at those rates
3) on TX success/failure, fill in a struct ieee80211_rate_status array 
that indicates which rates were used and how many times until the
eventual success or failure; this is in struct ieee80211_tx_status
3) alternatively, fill in the tx_info rates array the same way and
report it that way, but that's less flexible


johannes

2022-10-24 02:16:30

by Ping-Ke Shih

[permalink] [raw]
Subject: RE: How to use the rate control in mac80211?


> -----Original Message-----
> From: Bitterblue Smith <[email protected]>
> Sent: Sunday, October 23, 2022 5:24 AM
> To: [email protected]
> Subject: How to use the rate control in mac80211?
>
> Hi!
>
> What does a driver (rtl8xxxu) need to do to make the rate control work?
>
> I thought it's like this:
> 1) don't set HAS_RATE_CONTROL
> 2) tell the chip to use the rate from tx_info->control.rates[0]
> 3) report if the frame was acked or not
>
> But it's not that easy. I'm always getting MCS0. Currently rtl8xxxu
> doesn't ask the chip for TX reports and always sets IEEE80211_TX_STAT_ACK.
> I thought this would get me MCS7 for all data frames, but it doesn't.

I don't dig rate control of mac80211, but I think it is hard to support this
by Realtek chip, because the item 3 you listed.

Realtek WiFi chip only reports TX status for specific packets, because bus
bandwidth is limited, so reduce these reports to have better performance.
And, firmware has implemented rate control called rate adaptive (RA), and
using firmware RA is expected.

If you really want to control rate by driver, you can refer to implementation
of management frame below:

if (ieee80211_is_mgmt(hdr->frame_control)) {
tx_desc->txdw5 = cpu_to_le32(rate);
tx_desc->txdw4 |= cpu_to_le32(TXDESC32_USE_DRIVER_RATE);
tx_desc->txdw5 |= cpu_to_le32(6 << TXDESC32_RETRY_LIMIT_SHIFT);
tx_desc->txdw5 |= cpu_to_le32(TXDESC32_RETRY_LIMIT_ENABLE);
}

Another thing is that retry rate is decided by hardware by another register
settings, but I'm not familiar with them, because I always use RA mentioned
above. Maybe, you still can use *default* settings of retry rate that could
work but not always good in all situations.

Ping-Ke

2022-10-24 15:23:12

by Bitterblue Smith

[permalink] [raw]
Subject: Re: How to use the rate control in mac80211?

On 23/10/2022 18:53, Johannes Berg wrote:
> Hi,
>
>> I thought it's like this:
>> 1) don't set HAS_RATE_CONTROL
>
> yes
>
>> 2) tell the chip to use the rate from tx_info->control.rates[0]
>
> I'd prefer you didn't, that's also very limited :-)
>
>> 3) report if the frame was acked or not
>
> Kind of.
>
> It'd be better if new drivers used sta_rate_tbl_update method, so it'd
> be something like
>
> 1) don't set HAS_RATE_CONTROL
> 2) implement sta_rate_tbl_update(), using the table of rates given
> there to instruct the device to transmit frames at those rates
> 3) on TX success/failure, fill in a struct ieee80211_rate_status array 
> that indicates which rates were used and how many times until the
> eventual success or failure; this is in struct ieee80211_tx_status
> 3) alternatively, fill in the tx_info rates array the same way and
> report it that way, but that's less flexible
>
>
> johannes

I got it to work! But I had to use tx_info->control.rates[0] when
IEEE80211_TX_CTL_RATE_CTRL_PROBE is set, otherwise the rate table only
contains MCS0.

2022-10-24 21:15:12

by Bitterblue Smith

[permalink] [raw]
Subject: Re: How to use the rate control in mac80211?

On 24/10/2022 05:13, Ping-Ke Shih wrote:
>
>> -----Original Message-----
>> From: Bitterblue Smith <[email protected]>
>> Sent: Sunday, October 23, 2022 5:24 AM
>> To: [email protected]
>> Subject: How to use the rate control in mac80211?
>>
>> Hi!
>>
>> What does a driver (rtl8xxxu) need to do to make the rate control work?
>>
>> I thought it's like this:
>> 1) don't set HAS_RATE_CONTROL
>> 2) tell the chip to use the rate from tx_info->control.rates[0]
>> 3) report if the frame was acked or not
>>
>> But it's not that easy. I'm always getting MCS0. Currently rtl8xxxu
>> doesn't ask the chip for TX reports and always sets IEEE80211_TX_STAT_ACK.
>> I thought this would get me MCS7 for all data frames, but it doesn't.
>
> I don't dig rate control of mac80211, but I think it is hard to support this
> by Realtek chip, because the item 3 you listed.
>
> Realtek WiFi chip only reports TX status for specific packets, because bus
> bandwidth is limited, so reduce these reports to have better performance.
> And, firmware has implemented rate control called rate adaptive (RA), and
> using firmware RA is expected.
>
> If you really want to control rate by driver, you can refer to implementation
> of management frame below:
>
> if (ieee80211_is_mgmt(hdr->frame_control)) {
> tx_desc->txdw5 = cpu_to_le32(rate);
> tx_desc->txdw4 |= cpu_to_le32(TXDESC32_USE_DRIVER_RATE);
> tx_desc->txdw5 |= cpu_to_le32(6 << TXDESC32_RETRY_LIMIT_SHIFT);
> tx_desc->txdw5 |= cpu_to_le32(TXDESC32_RETRY_LIMIT_ENABLE);
> }
>
> Another thing is that retry rate is decided by hardware by another register
> settings, but I'm not familiar with them, because I always use RA mentioned
> above. Maybe, you still can use *default* settings of retry rate that could
> work but not always good in all situations.
>
> Ping-Ke
>
Normally, we use the firmware rate control, but RTL8188EU doesn't have it:
https://github.com/lwfinger/rtl8188eu/blob/c4908ca4caf861d858c4d9e8452a2ad5c88cf2ba/rtl8188eu_xmit.c#L349
https://github.com/lwfinger/rtl8188eu/blob/c4908ca4caf861d858c4d9e8452a2ad5c88cf2ba/hal8188erateadaptive.c

(I guess they used the space in the firmware on the IOL stuff and the rate
control code didn't fit?)

Maybe we don't need to ask for TX reports for every data frame?

2022-10-25 02:38:13

by Ping-Ke Shih

[permalink] [raw]
Subject: RE: How to use the rate control in mac80211?


> -----Original Message-----
> From: Bitterblue Smith <[email protected]>
> Sent: Monday, October 24, 2022 10:25 PM
> To: Ping-Ke Shih <[email protected]>; [email protected]
> Subject: Re: How to use the rate control in mac80211?
>
> On 24/10/2022 05:13, Ping-Ke Shih wrote:
> >
> >> -----Original Message-----
> >> From: Bitterblue Smith <[email protected]>
> >> Sent: Sunday, October 23, 2022 5:24 AM
> >> To: [email protected]
> >> Subject: How to use the rate control in mac80211?
> >>
> >> Hi!
> >>
> >> What does a driver (rtl8xxxu) need to do to make the rate control work?
> >>
> >> I thought it's like this:
> >> 1) don't set HAS_RATE_CONTROL
> >> 2) tell the chip to use the rate from tx_info->control.rates[0]
> >> 3) report if the frame was acked or not
> >>
> >> But it's not that easy. I'm always getting MCS0. Currently rtl8xxxu
> >> doesn't ask the chip for TX reports and always sets IEEE80211_TX_STAT_ACK.
> >> I thought this would get me MCS7 for all data frames, but it doesn't.
> >
> > I don't dig rate control of mac80211, but I think it is hard to support this
> > by Realtek chip, because the item 3 you listed.
> >
> > Realtek WiFi chip only reports TX status for specific packets, because bus
> > bandwidth is limited, so reduce these reports to have better performance.
> > And, firmware has implemented rate control called rate adaptive (RA), and
> > using firmware RA is expected.
> >
> > If you really want to control rate by driver, you can refer to implementation
> > of management frame below:
> >
> > if (ieee80211_is_mgmt(hdr->frame_control)) {
> > tx_desc->txdw5 = cpu_to_le32(rate);
> > tx_desc->txdw4 |= cpu_to_le32(TXDESC32_USE_DRIVER_RATE);
> > tx_desc->txdw5 |= cpu_to_le32(6 << TXDESC32_RETRY_LIMIT_SHIFT);
> > tx_desc->txdw5 |= cpu_to_le32(TXDESC32_RETRY_LIMIT_ENABLE);
> > }
> >
> > Another thing is that retry rate is decided by hardware by another register
> > settings, but I'm not familiar with them, because I always use RA mentioned
> > above. Maybe, you still can use *default* settings of retry rate that could
> > work but not always good in all situations.
> >
> > Ping-Ke
> >
> Normally, we use the firmware rate control, but RTL8188EU doesn't have it:
> https://github.com/lwfinger/rtl8188eu/blob/c4908ca4caf861d858c4d9e8452a2ad5c88cf2ba/rtl8188eu_xmit.c#L
> 349
> https://github.com/lwfinger/rtl8188eu/blob/c4908ca4caf861d858c4d9e8452a2ad5c88cf2ba/hal8188erateadapti
> ve.c

You are right. The RTL8188EU does different thing from other chips.

Firmware collects TX status and send TX_REPORT2 events to driver, and
then driver can use it to decide rate. Another thing is to set maximum
mac_id to tell firmware how many entries driver needs.

rtw_write8(adapter, REG_TX_RPT_CTRL + 1, maxMacid + 1);

>
> (I guess they used the space in the firmware on the IOL stuff and the rate
> control code didn't fit?)
>
> Maybe we don't need to ask for TX reports for every data frame?

Maybe, we can ask TX report per 10 or 100 packets, but I don't know if
this can get positive result.

Ping-Ke