iPXE
rc80211.c File Reference

Simple 802.11 rate-control algorithm. More...

#include <stdlib.h>
#include <ipxe/net80211.h>

Go to the source code of this file.

Data Structures

struct  rc80211_ctx
 A rate control context. More...

Macros

#define RC_PKT_OK   0x3
 Two-bit packet status indicator for a packet with no retries.
#define RC_PKT_RETRIED_ONCE   0x2
 Two-bit packet status indicator for a packet with one retry.
#define RC_PKT_RETRIED_MULTI   0x1
 Two-bit packet status indicator for a TX packet with multiple retries.
#define RC_PKT_FAILED   0x0
 Two-bit packet status indicator for a TX packet that was never ACKed.
#define RC_TX_FACTOR   4
 Number of times to weight TX packets more heavily than RX packets.
#define RC_TX_EMERG_FAIL   3
 Number of consecutive failed TX packets that cause an automatic rate drop.
#define RC_GOODNESS_MIN   85
 Minimum net goodness below which we will search for a better rate.
#define RC_GOODNESS_MAX   95
 Maximum net goodness above which we will try to increase our rate.
#define RC_UNCERTAINTY_THRESH   4
 Minimum (num RX + RC_TX_FACTOR * num TX) to use a certain rate.
#define TX   0
 TX direction.
#define RX   1
 RX direction.

Functions

 FILE_LICENCE (GPL2_OR_LATER)
 FILE_SECBOOT (FORBIDDEN)
struct rc80211_ctxrc80211_init (struct net80211_device *dev __unused)
 Initialize rate-control algorithm.
static int rc80211_calc_net_goodness (struct rc80211_ctx *ctx, int rate_idx)
 Calculate net goodness for a certain rate.
static int rc80211_pick_best (struct net80211_device *dev)
 Determine the best rate to switch to and return it.
static void rc80211_set_rate (struct net80211_device *dev, int rate_idx)
 Set 802.11 device rate.
static void rc80211_maybe_set_new (struct net80211_device *dev)
 Check rate-control state and change rate if necessary.
static void rc80211_update (struct net80211_device *dev, int direction, int rate_idx, int retries, int failed)
 Update rate-control state.
void rc80211_update_tx (struct net80211_device *dev, int retries, int rc)
 Update rate-control state for transmitted packet.
void rc80211_update_rx (struct net80211_device *dev, int retry, u16 rate)
 Update rate-control state for received packet.
void rc80211_free (struct rc80211_ctx *ctx)
 Free rate-control context.

Detailed Description

Simple 802.11 rate-control algorithm.

Definition in file rc80211.c.

Macro Definition Documentation

◆ RC_PKT_OK

#define RC_PKT_OK   0x3

Two-bit packet status indicator for a packet with no retries.

Definition at line 89 of file rc80211.c.

Referenced by rc80211_update().

◆ RC_PKT_RETRIED_ONCE

#define RC_PKT_RETRIED_ONCE   0x2

Two-bit packet status indicator for a packet with one retry.

Definition at line 92 of file rc80211.c.

Referenced by rc80211_update().

◆ RC_PKT_RETRIED_MULTI

#define RC_PKT_RETRIED_MULTI   0x1

Two-bit packet status indicator for a TX packet with multiple retries.

It is not possible to tell whether an RX packet had one or multiple retries; we rely instead on the fact that failed RX packets won't get to us at all, so if we receive a lot of RX packets on a certain rate it must be pretty good.

Definition at line 101 of file rc80211.c.

Referenced by rc80211_update().

◆ RC_PKT_FAILED

#define RC_PKT_FAILED   0x0

Two-bit packet status indicator for a TX packet that was never ACKed.

It is not possible to tell whether an RX packet was setn if it didn't get through to us, but if we don't see one we won't increase the goodness for its rate. This asymmetry is part of why TX packets are weighted much more heavily than RX.

Definition at line 110 of file rc80211.c.

Referenced by rc80211_update().

◆ RC_TX_FACTOR

#define RC_TX_FACTOR   4

Number of times to weight TX packets more heavily than RX packets.

Definition at line 113 of file rc80211.c.

Referenced by rc80211_calc_net_goodness().

◆ RC_TX_EMERG_FAIL

#define RC_TX_EMERG_FAIL   3

Number of consecutive failed TX packets that cause an automatic rate drop.

Definition at line 116 of file rc80211.c.

Referenced by rc80211_update_tx().

◆ RC_GOODNESS_MIN

#define RC_GOODNESS_MIN   85

Minimum net goodness below which we will search for a better rate.

Definition at line 119 of file rc80211.c.

Referenced by rc80211_maybe_set_new(), and rc80211_pick_best().

◆ RC_GOODNESS_MAX

#define RC_GOODNESS_MAX   95

Maximum net goodness above which we will try to increase our rate.

Definition at line 122 of file rc80211.c.

Referenced by rc80211_maybe_set_new().

◆ RC_UNCERTAINTY_THRESH

#define RC_UNCERTAINTY_THRESH   4

Minimum (num RX + RC_TX_FACTOR * num TX) to use a certain rate.

Definition at line 125 of file rc80211.c.

Referenced by rc80211_calc_net_goodness().

◆ TX

#define TX   0

TX direction.

Definition at line 128 of file rc80211.c.

Referenced by rc80211_calc_net_goodness(), and rc80211_update_tx().

◆ RX

#define RX   1

RX direction.

Definition at line 131 of file rc80211.c.

Referenced by rc80211_calc_net_goodness(), and rc80211_update_rx().

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER )

◆ FILE_SECBOOT()

FILE_SECBOOT ( FORBIDDEN )

◆ rc80211_init()

struct rc80211_ctx * rc80211_init ( struct net80211_device *dev __unused)

Initialize rate-control algorithm.

Parameters
dev802.11 device
Return values
ctxRate-control context, to be stored in dev->rctl

Definition at line 155 of file rc80211.c.

156{
157 struct rc80211_ctx *ret = zalloc ( sizeof ( *ret ) );
158 return ret;
159}
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
A rate control context.
Definition rc80211.c:135

References __unused, and zalloc().

Referenced by net80211_step_associate().

◆ rc80211_calc_net_goodness()

int rc80211_calc_net_goodness ( struct rc80211_ctx * ctx,
int rate_idx )
static

Calculate net goodness for a certain rate.

Parameters
ctxRate-control context
rate_idxIndex of rate to calculate net goodness for

Definition at line 167 of file rc80211.c.

169{
170 int sum[2], num[2], dir, pkt;
171
172 for ( dir = 0; dir < 2; dir++ ) {
173 u32 good = ctx->goodness[dir][rate_idx];
174
175 num[dir] = ctx->count[dir][rate_idx];
176 sum[dir] = 0;
177
178 for ( pkt = 0; pkt < num[dir]; pkt++ )
179 sum[dir] += ( good >> ( 2 * pkt ) ) & 0x3;
180 }
181
182 if ( ( num[TX] * RC_TX_FACTOR + num[RX] ) < RC_UNCERTAINTY_THRESH )
183 return -1;
184
185 return ( 33 * ( sum[TX] * RC_TX_FACTOR + sum[RX] ) /
186 ( num[TX] * RC_TX_FACTOR + num[RX] ) );
187}
struct golan_eq_context ctx
Definition CIB_PRM.h:0
uint32_t num
Definition multiboot.h:0
#define RC_UNCERTAINTY_THRESH
Minimum (num RX + RC_TX_FACTOR * num TX) to use a certain rate.
Definition rc80211.c:125
#define RC_TX_FACTOR
Number of times to weight TX packets more heavily than RX packets.
Definition rc80211.c:113
#define RX
RX direction.
Definition rc80211.c:131
#define TX
TX direction.
Definition rc80211.c:128
#define u32
Definition vga.h:21

References ctx, num, RC_TX_FACTOR, RC_UNCERTAINTY_THRESH, RX, TX, and u32.

Referenced by rc80211_maybe_set_new(), and rc80211_pick_best().

◆ rc80211_pick_best()

int rc80211_pick_best ( struct net80211_device * dev)
static

Determine the best rate to switch to and return it.

Parameters
dev802.11 device
Return values
rate_idxIndex of the best rate to switch to

Definition at line 195 of file rc80211.c.

196{
197 struct rc80211_ctx *ctx = dev->rctl;
198 int best_net_good = 0, best_rate = -1, i;
199
200 for ( i = 0; i < dev->nr_rates; i++ ) {
201 int net_good = rc80211_calc_net_goodness ( ctx, i );
202
203 if ( net_good > best_net_good ||
204 ( best_net_good > RC_GOODNESS_MIN &&
205 net_good > RC_GOODNESS_MIN ) ) {
206 best_net_good = net_good;
207 best_rate = i;
208 }
209 }
210
211 if ( best_rate >= 0 ) {
212 int old_good = rc80211_calc_net_goodness ( ctx, dev->rate );
213 if ( old_good != best_net_good )
214 DBGC ( ctx, "802.11 RC %p switching from goodness "
215 "%d to %d\n", ctx, old_good, best_net_good );
216
217 ctx->started = 1;
218 return best_rate;
219 }
220
221 return dev->rate;
222}
#define DBGC(...)
Definition compiler.h:505
static int rc80211_calc_net_goodness(struct rc80211_ctx *ctx, int rate_idx)
Calculate net goodness for a certain rate.
Definition rc80211.c:167
#define RC_GOODNESS_MIN
Minimum net goodness below which we will search for a better rate.
Definition rc80211.c:119
struct rc80211_ctx * rctl
Rate control state.
Definition net80211.h:989
u8 rate
The rate currently in use, as an index into the rates array.
Definition net80211.h:824
u8 nr_rates
The number of transmission rates in the rates array.
Definition net80211.h:821

References ctx, DBGC, net80211_device::nr_rates, net80211_device::rate, rc80211_calc_net_goodness(), RC_GOODNESS_MIN, and net80211_device::rctl.

Referenced by rc80211_maybe_set_new().

◆ rc80211_set_rate()

void rc80211_set_rate ( struct net80211_device * dev,
int rate_idx )
inlinestatic

Set 802.11 device rate.

Parameters
dev802.11 device
rate_idxIndex of rate to switch to

This is a thin wrapper around net80211_set_rate_idx to insert a debugging message where appropriate.

Definition at line 233 of file rc80211.c.

235{
236 DBGC ( dev->rctl, "802.11 RC %p changing rate %d->%d Mbps\n", dev->rctl,
237 dev->rates[dev->rate] / 10, dev->rates[rate_idx] / 10 );
238
239 net80211_set_rate_idx ( dev, rate_idx );
240}
void net80211_set_rate_idx(struct net80211_device *dev, int rate)
Set data transmission rate for 802.11 device.
Definition net80211.c:2001
u16 rates[NET80211_MAX_RATES]
A list of all possible TX rates we might use.
Definition net80211.h:818

References DBGC, net80211_set_rate_idx(), net80211_device::rate, net80211_device::rates, and net80211_device::rctl.

Referenced by rc80211_maybe_set_new(), and rc80211_update_tx().

◆ rc80211_maybe_set_new()

void rc80211_maybe_set_new ( struct net80211_device * dev)
static

Check rate-control state and change rate if necessary.

Parameters
dev802.11 device

Definition at line 247 of file rc80211.c.

248{
249 struct rc80211_ctx *ctx = dev->rctl;
250 int net_good;
251
252 net_good = rc80211_calc_net_goodness ( ctx, dev->rate );
253
254 if ( ! ctx->started ) {
255 rc80211_set_rate ( dev, rc80211_pick_best ( dev ) );
256 return;
257 }
258
259 if ( net_good < 0 ) /* insufficient data */
260 return;
261
262 if ( net_good > RC_GOODNESS_MAX && dev->rate + 1 < dev->nr_rates ) {
263 int higher = rc80211_calc_net_goodness ( ctx, dev->rate + 1 );
264 if ( higher > net_good || higher < 0 )
265 rc80211_set_rate ( dev, dev->rate + 1 );
266 else
267 rc80211_set_rate ( dev, rc80211_pick_best ( dev ) );
268 }
269
270 if ( net_good < RC_GOODNESS_MIN ) {
271 rc80211_set_rate ( dev, rc80211_pick_best ( dev ) );
272 }
273}
static void rc80211_set_rate(struct net80211_device *dev, int rate_idx)
Set 802.11 device rate.
Definition rc80211.c:233
static int rc80211_pick_best(struct net80211_device *dev)
Determine the best rate to switch to and return it.
Definition rc80211.c:195
#define RC_GOODNESS_MAX
Maximum net goodness above which we will try to increase our rate.
Definition rc80211.c:122

References ctx, net80211_device::nr_rates, net80211_device::rate, rc80211_calc_net_goodness(), rc80211_pick_best(), rc80211_set_rate(), RC_GOODNESS_MAX, RC_GOODNESS_MIN, and net80211_device::rctl.

Referenced by rc80211_update().

◆ rc80211_update()

void rc80211_update ( struct net80211_device * dev,
int direction,
int rate_idx,
int retries,
int failed )
static

Update rate-control state.

Parameters
dev802.11 device
directionOne of the direction constants TX or RX
rate_idxIndex of rate at which packet was sent or received
retriesNumber of times packet was retried before success
failedIf nonzero, the packet failed to get through

Definition at line 284 of file rc80211.c.

286{
287 struct rc80211_ctx *ctx = dev->rctl;
288 u32 goodness = ctx->goodness[direction][rate_idx];
289
290 if ( ctx->count[direction][rate_idx] < 16 )
291 ctx->count[direction][rate_idx]++;
292
293 goodness <<= 2;
294 if ( failed )
296 else if ( retries > 1 )
298 else if ( retries )
300 else
302
303 ctx->goodness[direction][rate_idx] = goodness;
304
305 ctx->packets++;
306
307 rc80211_maybe_set_new ( dev );
308}
uint8_t direction
Direction.
Definition ena.h:3
#define RC_PKT_FAILED
Two-bit packet status indicator for a TX packet that was never ACKed.
Definition rc80211.c:110
#define RC_PKT_OK
Two-bit packet status indicator for a packet with no retries.
Definition rc80211.c:89
#define RC_PKT_RETRIED_MULTI
Two-bit packet status indicator for a TX packet with multiple retries.
Definition rc80211.c:101
#define RC_PKT_RETRIED_ONCE
Two-bit packet status indicator for a packet with one retry.
Definition rc80211.c:92
static void rc80211_maybe_set_new(struct net80211_device *dev)
Check rate-control state and change rate if necessary.
Definition rc80211.c:247
u32 goodness[2][NET80211_MAX_RATES]
Goodness state for each rate, TX and RX.
Definition rc80211.c:137

References ctx, direction, rc80211_ctx::goodness, rc80211_maybe_set_new(), RC_PKT_FAILED, RC_PKT_OK, RC_PKT_RETRIED_MULTI, RC_PKT_RETRIED_ONCE, net80211_device::rctl, and u32.

Referenced by rc80211_update_rx(), and rc80211_update_tx().

◆ rc80211_update_tx()

void rc80211_update_tx ( struct net80211_device * dev,
int retries,
int rc )

Update rate-control state for transmitted packet.

Parameters
dev802.11 device
retriesNumber of times packet was transmitted before success
rcReturn status code for transmission

Definition at line 317 of file rc80211.c.

318{
319 struct rc80211_ctx *ctx = dev->rctl;
320
321 if ( ! ctx->started )
322 return;
323
324 rc80211_update ( dev, TX, dev->rate, retries, rc );
325
326 /* Check if the last RC_TX_EMERG_FAIL packets have all failed */
327 if ( ! ( ctx->goodness[TX][dev->rate] &
328 ( ( 1 << ( 2 * RC_TX_EMERG_FAIL ) ) - 1 ) ) ) {
329 if ( dev->rate == 0 )
330 DBGC ( dev->rctl, "802.11 RC %p saw %d consecutive "
331 "failed TX, but cannot lower rate any further\n",
332 dev->rctl, RC_TX_EMERG_FAIL );
333 else {
334 DBGC ( dev->rctl, "802.11 RC %p lowering rate (%d->%d "
335 "Mbps) due to %d consecutive TX failures\n",
336 dev->rctl, dev->rates[dev->rate] / 10,
337 dev->rates[dev->rate - 1] / 10,
339
340 rc80211_set_rate ( dev, dev->rate - 1 );
341 }
342 }
343}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
static void rc80211_update(struct net80211_device *dev, int direction, int rate_idx, int retries, int failed)
Update rate-control state.
Definition rc80211.c:284
#define RC_TX_EMERG_FAIL
Number of consecutive failed TX packets that cause an automatic rate drop.
Definition rc80211.c:116

References ctx, DBGC, net80211_device::rate, net80211_device::rates, rc, rc80211_set_rate(), rc80211_update(), RC_TX_EMERG_FAIL, net80211_device::rctl, and TX.

Referenced by net80211_tx_complete().

◆ rc80211_update_rx()

void rc80211_update_rx ( struct net80211_device * dev,
int retry,
u16 rate )

Update rate-control state for received packet.

Parameters
dev802.11 device
retryWhether the received packet had been retransmitted
rateRate at which packet was received, in 100 kbps units

Definition at line 352 of file rc80211.c.

353{
354 int ridx;
355
356 for ( ridx = 0; ridx < dev->nr_rates && dev->rates[ridx] != rate;
357 ridx++ )
358 ;
359 if ( ridx >= dev->nr_rates )
360 return; /* couldn't find the rate */
361
362 rc80211_update ( dev, RX, ridx, retry, 0 );
363}

References net80211_device::nr_rates, net80211_device::rates, rc80211_update(), RX, and u16.

Referenced by net80211_rx().

◆ rc80211_free()

void rc80211_free ( struct rc80211_ctx * ctx)

Free rate-control context.

Parameters
ctxRate-control context

Definition at line 370 of file rc80211.c.

371{
372 free ( ctx );
373}
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55

References ctx, and free.

Referenced by net80211_free().