【Atheros】NIC駆動速度調整アルゴリズムの概要

7375 ワード

私はNIC駆動をして、最も主要な内容は速度調整アルゴリズムを設計して改善することで、802.11プロトコルクラスタの新しい標準がますます多くなるにつれて、速度がますます高くなって、変調符号化方式もますます多くなって、一般的に言えば、速度が高ければ高いほどパケットを失う可能性があって、速度が低いほど安定して、これは全体の状況で、しかし必然的な法則ではありませんて、だから、固定レートだけで送信するのは明らかに適切ではありません.これはレート調整アルゴリズムが自分で調整する必要があります.信号が良い場合は、高レートで送信します.チャネルの状況が悪い場合は、低レートで送信します.atheros駆動では、2つのオプションのレート調整アルゴリズムが提供されています.ath 9 kとminstrelです.minstrelのほうがいいです.後でminstrelとath 9 kの2つのアルゴリズムをそれぞれソースコードに基づいて解読します.この文章では、重要な構造体だけを紹介し、レート調整アルゴリズムのタスクを引き出します.
ネットワークプログラミングに触れた友人はsocketに慣れていないが、データリンク層にはsk_という対応する構造体がある.buff、一般的にskbと表記され、skbにはcontrolというドメインがあります.buffer、すなわちskb->cbは、48バイトの長さのメモリ領域であり、この領域の設計は、プロトコルスタックの各層にプライベートなデータを格納するためであり、パケットが異なる層間で伝達される場合、例えばネットワーク層からリンク層に伝送された後、このドメインのデータは役に立たず、安心してリンク層に新しいデータを書き込むことができる.リンク層は、このパケットを物理層に渡して送信する場合、このパケットを20 MHzで送信するか40 MHzで送信するか、どのレートで送信するか、送信に失敗して再送する必要がある場合、最大何回再送するかなどのパラメータを指定する必要があります.これらの情報はskb->cbに格納され、格納されたフォーマットです.次の構造体に従って保存されます.
struct ieee80211_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 */

                unsigned long jiffies;

            };

            /* NB: vif can be NULL for injected frames */

            struct ieee80211_vif *vif;

            struct ieee80211_key_conf *hw_key;

            struct ieee80211_sta *sta;

        } control;

        struct {

            struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES];

            u8 ampdu_ack_len;

            int ack_signal;

            u8 ampdu_len;

            /* 15 bytes free */

        } status;

        struct {

            struct ieee80211_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 *)];

    };

};

このうち、多くのフィールドの意味は心配する必要はありません.unionの一部(赤いunion)に注目するだけです.このメモリ領域はcontrolやstatusなどでアクセスできます.このcontrolやstatusが注目のポイントです.
彼らのコアは同じフィールドです.私は赤いieee 80211をマークしています.tx_rate:
struct ieee80211_tx_rate {

    s8 idx;

    u8 count;

    u8 flags;

} __packed;

この構造体は1つのレートを代表して、フィールド名を見ると明らかになった:レート番号、送信回数と1つのフラグビット(識別帯域幅、SGI/LGIなど)、ネットカードはマルチレート再送をサポートする可能性があり、まずあるレートで送信し、何度も失敗したら2番目のレートで送信する.そのため、下位層は発注過程でieee 80211_が必要である.tx_rateの配列、レート調整アルゴリズムのタスクは、前の構造体のこのフィールドを埋めて最下位に渡すことです.
struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES];

前の構造体tx_に戻りますinfoは、主にcontrolとstatusの2つの部分を含むunionを持っています.control部分は送信中に使用され、レート調整アルゴリズムは次のようになります.
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;

これにより,送信時にパケットを0,1,2の3つのレートで送信が成功するまで最大2,4,8回送信することを指定した.では、送信が完了した後、送信が成功したかどうか、最後にどのレートで送信に成功したかなどの情報を知る必要があります.したがって、この構造体はまた下位層に返されます.この場合、statusを通じて以前に設定されたこれらのデータにアクセスすることができます.ただし、各項目のcountドメインは下位層に書き換えられています.以前は、各レートの最大送信回数がいくらだったかを示していましたが、今では各レートの実際の送信回数がいくらになったかを示しています.
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

これはレート0が4回発せられたことを意味し、最終的には失敗し、レート1が1回発せば成功し、もちろんレート2は使われず、0回発せられた.
レート調整アルゴリズムのタスクは、送信中にtx_をinfo->control.ratesで埋めて、送信が終わったらtx_に従いますinfo->status.ratesはレートの調整をします.
この2つのアルゴリズムについて、MinstrelAth9kの順に説明します.