I do the network card driver, the main content is to design and improve the rate adjustment algorithm, With the new standard of 802.11 protocol cluster more and more, the rate is more and more high, modulation coding method is also more and more, generally speaking, the higher the rate is more likely to drop packets, the lower the rate is more stable, this is the overall situation, but not necessarily the law, so, only with a fixed rate to send is obviously inappropriate, this requires the rate Time, the use of high-speed transmission, the channel is not good, switching to a low rate to send, Atheros driver provides two optional rate adjustment algorithm, ath9k and Minstrel, of which minstrel better, I will be in the back according to the source code interpretation minstrel and ath9k These two algorithms, this article, only introduce an important structure, so as to elicit the task of rate adjustment algorithm.
Contact Network programming Friends will not be unfamiliar with the socket, in the data link layer, there is a corresponding structure, called Sk_buff, generally recorded as a skb,skb in a domain called Control_buffer, that is, SKB->CB, is a 48-byte memory area, this area is designed to store some private data in each layer of the protocol stack, when the packets are passed between different layers, such as from the network layer to the link layer, the data of this domain is useless, can safely be written to the new data by the link layer, Link layer in the data packet to the physical layer to send, you need to specify a number of parameters, such as the packet to use 20MHZ or 40MHz to send, with which rate to send, if the transmission failed to be re-transmitted, the maximum number of retransmissions and so on, the information is stored in the skb-> CB, stored in the format, according to the following structure of the body to save:
structIeee80211_tx_info {/*Common Information*/U32 flags; U8 Band; U8 Antenna_sel_tx; U16 ack_frame_id; Union { struct{Union {/*Rate Control*/ struct { struct ieee80211_tx_rate rates[ieee80211_tx_max_rates]; S8 Rts_cts_rate_idx; }; /*Only needed before rate control*/unsignedLongjiffies; }; /*Nb:vif can is NULL for injected frames*/ structIEEE80211_VIF *vif; structieee80211_key_conf *Hw_key; structIeee80211_sta *STA; } control; struct { structIeee80211_tx_rate Rates[ieee80211_tx_max_rates]; U8 Ampdu_ack_len; intack_signal; U8 Ampdu_len; /*bytes Free*/} status; struct { structieee80211_tx_rate driver_rates[ieee80211_tx_max_rates]; void*rate_driver_data[ieee80211_tx_info_rate_driver_data_size/sizeof(void*)]; }; void*driver_data[ieee80211_tx_info_driver_data_size/sizeof(void*)]; };};
Where the meaning of many fields does not need to worry about, just focus on the part of the Union (the Red Union), this memory area can be accessed through control and status, this control and status is our focus!
Their core is the same field: my Red ieee80211_tx_rate:
struct ieee80211_tx_rate { s8 idx; U8 Count; U8 flags;} __packed;
This structure represents a rate, see the field name is obvious: the rate number, the number of times and a flag bit (identity bandwidth, SGI/LGI, etc.), the network card may support multi-rate retransmission, that is, a certain rate of transmission, if a few times failed to change the second rate of hair, so, the underlying in the contract process, A ieee80211_tx_rate array is required, and the task of the rate-tuning algorithm is to fill the field in front of the structure with the underlying:
struct ieee80211_tx_rate rates[ieee80211_tx_max_rates];
Back to the previous structure Tx_info, which has a union, which consists mainly of control and status two parts, the control part is used during the transmission process, the rate adjustment algorithm will:
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB (SKB); struct ieee80211_tx_rate *rates = tx_info->control.rates;rates[0].idx=0; rates[0].count=2; rates[0].flags=zzz0;rates[1].idx=1; rates[1].count=4; rates[1].flags=zzz1;rates[2].idx=2; rates[2].count=8; rates[2].flags=zzz2;
In this way, I have specified that the packet is sent with 0, 1, and 2 of the three rates sent up to 2, 4, 8 times until it is successfully sent. After sending it, we need to know if the send is successful or not, and finally which rate sends the successful message. So this structure will be returned to us at the bottom, at this point, we can access the previous set of data through the status, but the Count field of each item is rewritten at the bottom, before it represents the maximum number of times each rate is sent, and now becomes the actual number of times per rate.
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB (SKB); struct ieee80211_tx_rate *rates = tx_info->status.rates; // Rates[0].count = = 4 // Rates[1].count = = 1 // Rates[2].count = = 0
This represents a rate of 0 sent 4 times, eventually failed, the rate of 1 sent 1 times to succeed, of course, the rate of 2 is not used, sent 0 times.
Therefore, the task of the rate adjustment algorithm is to fill the tx_info->control.rates in the sending process, and so on after the sending end according to Tx_info->status.rates to do the rate adjustment.
The following two algorithms are described in turn: Minstrel, ath9k.
Overview of driver rate tuning algorithm for "Atheros" network card