0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux內(nèi)核網(wǎng)絡(luò)擁塞控制算法的實(shí)現(xiàn)框架(二)

麥辣雞腿堡 ? 來(lái)源:技術(shù)簡(jiǎn)說(shuō) ? 作者:董旭 ? 2023-07-28 11:34 ? 次閱讀

從上面的概念中可以得知,擁塞窗口可以間接反映網(wǎng)絡(luò)的狀況,進(jìn)而去限制發(fā)送窗口的大小。擁塞窗口作為網(wǎng)絡(luò)擁塞控制中核心變量之一,對(duì)網(wǎng)絡(luò)擁塞控制起到關(guān)鍵作用。在Linux內(nèi)核中,關(guān)于網(wǎng)絡(luò)的核心結(jié)構(gòu)體在:[Linux內(nèi)核網(wǎng)絡(luò)基礎(chǔ)-TCP相關(guān)的幾個(gè)關(guān)鍵結(jié)構(gòu)體-小記](méi)中進(jìn)行了介紹,如下圖是四個(gè)核心結(jié)構(gòu)體,四個(gè)結(jié)構(gòu)的關(guān)系具有面向?qū)ο蟮奶卣?,通過(guò)層層繼承,實(shí)現(xiàn)了類的復(fù)用;內(nèi)核中網(wǎng)絡(luò)相關(guān)的很多函數(shù),參數(shù)往往都是struct sock,函數(shù)內(nèi)部依照不同的業(yè)務(wù)邏輯,將struct sock轉(zhuǎn)換為不同的業(yè)務(wù)結(jié)構(gòu)。

圖片

struct tcp_sockstruct inet_connection_sock結(jié)構(gòu)體的基礎(chǔ)上繼承而來(lái),在struct inet_connection_sock上增加了一些tcp協(xié)議相關(guān)的字段,如滑動(dòng)窗口協(xié)議,擁塞算法等一些TCP專有的屬性。由于這種繼承關(guān)系,可以互相轉(zhuǎn)換,如下舉例兩種轉(zhuǎn)換方式,第一種是struct sock轉(zhuǎn)換為struct tcp_sock,第二種是struct sock轉(zhuǎn)換成struct inet_connection_sock。。下面將struct tcp_sock展開(kāi)可以看到與網(wǎng)絡(luò)擁塞控制相關(guān)的字段。

static inline struct tcp_sock *tcp_sk(const struct sock *sk)
{
 return (struct tcp_sock *)sk;
}
static inline struct inet_connection_sock *inet_csk(const struct sock *sk)
{
 return (struct inet_connection_sock *)sk;
}

struct tcp_sock中定義的關(guān)于網(wǎng)絡(luò)擁塞控制相關(guān)的字段如下所示:

struct tcp_sock {//在 inet_connection_sock  基礎(chǔ)上增加了 滑動(dòng)窗口 擁塞控制算法等tcp 專有 屬性
    __be32    pred_flags;/*首部預(yù)測(cè)標(biāo)志 在接收到 syn 跟新窗口 等時(shí)設(shè)置此標(biāo)志 ,
    此標(biāo)志和時(shí)間戳 序號(hào)等 用于判斷執(zhí)行 快速還是慢速路徑*/

    u64    bytes_received;    /* RFC4898 tcpEStatsAppHCThruOctetsReceived
                 * sum(delta(rcv_nxt)), or how many bytes
                 * were acked.
                 */
    u32    segs_in;    /* RFC4898 tcpEStatsPerfSegsIn
                 * total number of segments in.
                 */
     u32    rcv_nxt;    /* What we want to receive next  等待接收的下一個(gè)序列號(hào)    */
    u32    copied_seq;    /* Head of yet unread data        */

/* rcv_nxt on last window update sent最早接收但沒(méi)有確認(rèn)的序號(hào), 也就是接收窗口的左端,
        在發(fā)送ack的時(shí)候, rcv_nxt更新 因此rcv_wup 更新比rcv_nxt 滯后一些  */
    u32    rcv_wup;    

    u32    snd_nxt;    /* Next sequence we send 等待發(fā)送的下一個(gè)序列號(hào)        */
    u32    segs_out;    /* RFC4898 tcpEStatsPerfSegsOut
                 * The total number of segments sent.
                 */
    u64    bytes_acked;    /* RFC4898 tcpEStatsAppHCThruOctetsAcked
                 * sum(delta(snd_una)), or how many bytes
                 * were acked.
                 */
    struct u64_stats_sync syncp; /* protects 64bit vars (cf tcp_get_info()) */

     u32    snd_una;    /* First byte we want an ack for  最早一個(gè)未被確認(rèn)的序號(hào)    */
     u32    snd_sml;    /* Last byte of the most recently transmitted small packet  最近發(fā)送一個(gè)小于mss的最后 一個(gè)字節(jié)序列號(hào)
    在成功發(fā)送, 如果報(bào)文小于mss,跟新這個(gè)字段 主要用來(lái)判斷是否啟用 nagle 算法*/
    u32    rcv_tstamp;    /* timestamp of last received ACK (for keepalives)  最近一次收到ack的時(shí)間 用于 tcp ?;?/
    u32    lsndtime;    /* timestamp of last sent data packet (for restart window) 最近一次發(fā)送 數(shù)據(jù)包時(shí)間*/
    u32    last_oow_ack_time;  /* timestamp of last out-of-window ACK */

    u32    tsoffset;    /* timestamp offset */

    struct list_head tsq_node; /* anchor in tsq_tasklet.head list */
    unsigned long    tsq_flags;

    /* Data for direct copy to user cp 數(shù)據(jù)到用戶進(jìn)程的控制塊 有用戶緩存以及其長(zhǎng)度 prequeue 隊(duì)列 其內(nèi)存*/
    struct {
        struct sk_buff_head    prequeue // tcp 段 緩沖到此隊(duì)列 知道進(jìn)程主動(dòng)讀取才真正的處理;
        struct task_struct    *task;
        struct msghdr        *msg;
        int            memory;// prequeue 當(dāng)前消耗的內(nèi)存
        int            len;// 用戶緩存中 當(dāng)前可以使用的緩存大小 
    } ucopy;

    u32    snd_wl1;    /* Sequence for window update記錄跟新發(fā)送窗口的那個(gè)ack 段號(hào) 用來(lái)判斷是否 需要跟新窗口
    如果后續(xù)收到ack大于snd_wll 則表示需要更新 窗口*/
    u32    snd_wnd;    /* The window we expect to receive 接收方 提供的窗口大小 也就是發(fā)送方窗口大小    */
    u32    max_window;    /* Maximal window ever seen from peer 接收方通告的最大窗口    */
    u32    mss_cache;    /* Cached effective mss, not including SACKS  發(fā)送方當(dāng)前有效的mss*/

    u32    window_clamp;    /* Maximal window to advertise 滑動(dòng)窗口最大值        */
    u32    rcv_ssthresh;    /* Current window clamp  當(dāng)前接收窗口的閾值            */
    ......
     u32    snd_ssthresh;    /* Slow start size threshold 擁塞控制 滿啟動(dòng)閾值        */
     u32    snd_cwnd;    /* Sending congestion window    當(dāng)前擁塞窗口大小  ---發(fā)送的擁塞窗口    */
    u32    snd_cwnd_cnt;    /* Linear increase counter    自從上次調(diào)整擁塞窗口后 到目前位置接收到的
    總ack段數(shù) 如果該字段為0  表示調(diào)整擁塞窗口但是沒(méi)有收到ack,調(diào)整擁塞窗口之后 收到ack段就回讓
    snd_cwnd_cnt 加1 */
    u32    snd_cwnd_clamp; /* Do not allow snd_cwnd to grow above this  snd_cwnd  的最大值*/
    u32    snd_cwnd_used;//記錄已經(jīng)從隊(duì)列發(fā)送而沒(méi)有被ack的段數(shù)
    u32    snd_cwnd_stamp;//記錄最近一次檢驗(yàn)cwnd 的時(shí)間;     擁塞期間 每次會(huì)檢驗(yàn)cwnd而調(diào)節(jié)擁塞窗口 ,
    //在非擁塞期間,為了防止應(yīng)用層序造成擁塞窗口失效  因此在發(fā)送后 有必要檢測(cè)cwnd
    u32    prior_cwnd;    /* Congestion window at start of Recovery.在進(jìn)入 Recovery 狀態(tài)時(shí)的擁塞窗口 */
    u32    prr_delivered;    /* Number of newly delivered packets to在恢復(fù)階段給接收者新發(fā)送包的數(shù)量
                 * receiver in Recovery. */
    u32    prr_out;    /* Total number of pkts sent during Recovery.在恢復(fù)階段一共發(fā)送的包的數(shù)量 */

     u32    rcv_wnd;    /* Current receiver window 當(dāng)前接收窗口的大小        */
    u32    write_seq;    /* Tail(+1) of data held in tcp send buffer   已加入發(fā)送隊(duì)列中的最后一個(gè)字節(jié)序號(hào)*/
    u32    notsent_lowat;    /* TCP_NOTSENT_LOWAT */
    u32    pushed_seq;    /* Last pushed seq, required to talk to windows */
    u32    lost_out;    /* Lost packets丟失的數(shù)據(jù)報(bào)            */
    u32    sacked_out;    /* SACK'd packets啟用 SACK 時(shí),通過(guò) SACK 的 TCP 選項(xiàng)標(biāo)識(shí)已接收到的段的數(shù)量。
                 不啟用 SACK 時(shí),標(biāo)識(shí)接收到的重復(fù)確認(rèn)的次數(shù),該值在接收到確認(rèn)新數(shù)據(jù)段時(shí)被清除。            */
    u32    fackets_out;    /* FACK'd packets    FACK'd packets 記錄 SND.UNA 與 (SACK 選項(xiàng)中目前接收方收到的段中最高序號(hào)段) 之間的段數(shù)。FACK
            用 SACK 選項(xiàng)來(lái)計(jì)算丟失在網(wǎng)絡(luò)中上的段數(shù)  lost_out=fackets_out-sacked_out  left_out=fackets_out        */

    /* from STCP, retrans queue hinting */
    struct sk_buff* lost_skb_hint; /*在重傳隊(duì)列中, 緩存下次要標(biāo)志的段*/
    struct sk_buff *retransmit_skb_hint;/* 表示將要重傳的起始包*/

    /* OOO segments go in this list. Note that socket lock must be held,
     * as we do not use sk_buff_head lock.
     */
    struct sk_buff_head    out_of_order_queue;

    /* SACKs data, these 2 need to be together (see tcp_options_write) */
    struct tcp_sack_block duplicate_sack[1]; /* D-SACK block */
    struct tcp_sack_block selective_acks[4]; /* The SACKS themselves*/

    struct tcp_sack_block recv_sack_cache[4];

    struct sk_buff *highest_sack;   /* skb just after the highest
                     * skb with SACKed bit set
                     * (validity guaranteed only if
                     * sacked_out > 0)
                     */

    int     lost_cnt_hint;/* 已經(jīng)標(biāo)志了多少個(gè)段 */
    u32     retransmit_high;    /* L-bits may be on up to this seqno  表示將要重傳的起始包 */

    u32    prior_ssthresh; /* ssthresh saved at recovery start表示前一個(gè)snd_ssthresh得大小    */
    u32    high_seq;    /* snd_nxt at onset of congestion擁塞開(kāi)始時(shí),snd_nxt的大----開(kāi)始擁塞的時(shí)候下一個(gè)要發(fā)送的序號(hào)字節(jié)*/

    u32    retrans_stamp;    /* Timestamp of the last retransmit,
                 * also used in SYN-SENT to remember stamp of
                 * the first SYN. */
    u32    undo_marker;    /* snd_una upon a new recovery episode. 在使用 F-RTO 算法進(jìn)行發(fā)送超時(shí)處理,或進(jìn)入 Recovery 進(jìn)行重傳,
                    或進(jìn)入 Loss 開(kāi)始慢啟動(dòng)時(shí),記錄當(dāng)時(shí) SND.UNA, 標(biāo)記重傳起始點(diǎn)。它是檢測(cè)是否可以進(jìn)行擁塞控制撤銷的條件之一,一般在完成
                    擁塞撤銷操作或進(jìn)入擁塞控制 Loss 狀態(tài)后會(huì)清零。*/
    int    undo_retrans;    /* number of undoable retransmissions. 在恢復(fù)擁塞控制之前可進(jìn)行撤銷的重傳段數(shù)。
                    在進(jìn)入 FTRO 算法或 擁塞狀態(tài) Loss 時(shí),清零,在重傳時(shí)計(jì)數(shù),是檢測(cè)是否可以進(jìn)行擁塞撤銷的條件之一。*/
    u32    total_retrans;    /* Total retransmits for entire connection */

    u32    urg_seq;    /* Seq of received urgent pointer  緊急數(shù)據(jù)的序號(hào) 所在段的序號(hào)和緊急指針相加獲得*/
    unsigned int        keepalive_time;      /* time before keep alive takes place */
    unsigned int        keepalive_intvl;  /* time interval between keep alive probes */

    int            linger2;

/* Receiver side RTT estimation */
    struct {
        u32    rtt;
        u32    seq;
        u32    time;
    } rcv_rtt_est;

/* Receiver queue space */
    struct {
        int    space;
        u32    seq;
        u32    time;
    } rcvq_space;

/* TCP-specific MTU probe information. */
    struct {
        u32          probe_seq_start;
        u32          probe_seq_end;
    } mtu_probe;
    u32    mtu_info; /* We received an ICMP_FRAG_NEEDED / ICMPV6_PKT_TOOBIG
               * while socket was owned by user.
               */

#ifdef CONFIG_TCP_MD5SIG
    const struct tcp_sock_af_ops    *af_specific;
    struct tcp_md5sig_info    __rcu *md5sig_info;
#endif

    struct tcp_fastopen_request *fastopen_req;

    struct request_sock *fastopen_rsk;
    u32    *saved_syn;
};
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11207

    瀏覽量

    208721
  • 網(wǎng)絡(luò)
    +關(guān)注

    關(guān)注

    14

    文章

    7485

    瀏覽量

    88541
  • 控制算法
    +關(guān)注

    關(guān)注

    4

    文章

    166

    瀏覽量

    21668
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    TCP協(xié)議技術(shù)之擁塞控制算法

    擁塞控制是在網(wǎng)絡(luò)層和傳輸層進(jìn)行的功能。在網(wǎng)絡(luò)層,擁塞控制可以通過(guò)路由
    的頭像 發(fā)表于 02-03 17:06 ?1899次閱讀
    TCP協(xié)議技術(shù)之<b class='flag-5'>擁塞</b><b class='flag-5'>控制</b><b class='flag-5'>算法</b>

    Linux內(nèi)核網(wǎng)絡(luò)的TCP傳輸控制塊相關(guān)資料分享

    1、Linux內(nèi)核網(wǎng)絡(luò)之傳輸層接收消息簡(jiǎn)析在傳輸層發(fā)送消息時(shí),TCP發(fā)送出去消息后,會(huì)跟蹤這些數(shù)據(jù)包,直到得到對(duì)方的確認(rèn)為止。對(duì)于接收方來(lái)講,當(dāng)收到一個(gè)報(bào)文段時(shí),其會(huì)根據(jù)情況把這些數(shù)據(jù)包添加到接收
    發(fā)表于 06-21 16:53

    Linux內(nèi)核網(wǎng)絡(luò)網(wǎng)絡(luò)層發(fā)送消息之IP分片簡(jiǎn)析

    1、Linux內(nèi)核網(wǎng)絡(luò)網(wǎng)絡(luò)層發(fā)送消息之IP分片簡(jiǎn)析本文分析下ip的分片。行 IP 分片。IP分片通常發(fā)生在網(wǎng)絡(luò)環(huán)境中,比如1個(gè)B環(huán)境中的MTU為500B,若的數(shù)據(jù)長(zhǎng)度超過(guò)
    發(fā)表于 07-20 15:34

    基于衛(wèi)星網(wǎng)絡(luò)的TCP擁塞控制算法

    分析衛(wèi)星網(wǎng)絡(luò)的特點(diǎn)和現(xiàn)有慢啟動(dòng)算法的不足,提出一種使擁塞窗口平滑增長(zhǎng)的慢啟動(dòng)算法。引入門限因子和粒度因子實(shí)現(xiàn)
    發(fā)表于 03-20 13:54 ?18次下載

    Linux中傳輸控制協(xié)議的擁塞控制分析

    TCP(transport control protocol)的性能在很大程度上取決于其所使用的擁塞控制算法。傳統(tǒng)的TCP在實(shí)現(xiàn)多種擁塞
    發(fā)表于 06-17 07:43 ?21次下載

    高速網(wǎng)絡(luò)中TCP擁塞控制算法的研究

    針對(duì)TCP 在高速網(wǎng)絡(luò)中的缺陷,提出了改進(jìn)的BIC TCP 擁塞控制算法。優(yōu)化算法通過(guò)監(jiān)控鏈路緩存的變化,調(diào)整探索可用帶寬過(guò)程中的
    發(fā)表于 09-17 10:18 ?15次下載

    嵌入式LINUX內(nèi)核網(wǎng)絡(luò)棧(源代碼)

    本文選擇 LINUX-1.2.13 內(nèi)核所包含的網(wǎng)絡(luò)部分代碼分析(注意網(wǎng)絡(luò)部分代碼與內(nèi)核代碼的演變是分離的,如
    發(fā)表于 05-12 10:39 ?57次下載
    嵌入式<b class='flag-5'>LINUX</b><b class='flag-5'>內(nèi)核網(wǎng)絡(luò)</b>棧(源代碼)

    基于模糊控制和壓縮感知的無(wú)線傳感網(wǎng)絡(luò)擁塞算法

    針對(duì)無(wú)線傳感網(wǎng)絡(luò)(WSN)的擁塞問(wèn)題,提出了一種將模糊控制和壓縮感知(cs)技術(shù)相結(jié)合來(lái)緩解無(wú)線傳感網(wǎng)絡(luò)擁塞
    發(fā)表于 01-03 09:59 ?0次下載
    基于模糊<b class='flag-5'>控制</b>和壓縮感知的無(wú)線傳感<b class='flag-5'>網(wǎng)絡(luò)</b><b class='flag-5'>擁塞</b><b class='flag-5'>算法</b>

    具有預(yù)測(cè)與自我調(diào)節(jié)能力的擁塞控制算法

    隨著網(wǎng)絡(luò)技術(shù)的日益發(fā)展,計(jì)算機(jī)網(wǎng)絡(luò)擁塞問(wèn)題已極大地影響了用戶的使用體驗(yàn)與數(shù)據(jù)傳遞。單一地提高硬件設(shè)備的投入并不能持續(xù)地防止網(wǎng)絡(luò)擁塞。因此
    發(fā)表于 01-18 16:18 ?0次下載
    具有預(yù)測(cè)與自我調(diào)節(jié)能力的<b class='flag-5'>擁塞</b><b class='flag-5'>控制</b><b class='flag-5'>算法</b>

    防止網(wǎng)絡(luò)擁塞現(xiàn)象的TCP擁塞控制算法

    ,近些年又出現(xiàn)了選擇性應(yīng)答(selectiveacknowledgement,SACK)算法,還有其他方面的大大小小的改進(jìn),成為網(wǎng)絡(luò)研究的一個(gè)熱點(diǎn)。 TCP的擁塞控制主要原理依賴于一個(gè)
    的頭像 發(fā)表于 10-29 14:54 ?2416次閱讀

    如何使用Linux內(nèi)核實(shí)現(xiàn)USB驅(qū)動(dòng)程序框架

    Linux內(nèi)核提供了完整的USB驅(qū)動(dòng)程序框架。USB總線采用樹(shù)形結(jié)構(gòu),在一條總線上只能有唯一的主機(jī)設(shè)備。 Linux內(nèi)核從主機(jī)和設(shè)備兩個(gè)角度
    發(fā)表于 11-06 17:59 ?20次下載
    如何使用<b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核實(shí)現(xiàn)</b>USB驅(qū)動(dòng)程序<b class='flag-5'>框架</b>

    如何用eBPF寫TCP擁塞控制算法?

    是兩個(gè)痛點(diǎn): 內(nèi)核越來(lái)越策略化。 內(nèi)核接口不穩(wěn)定。 分別簡(jiǎn)單說(shuō)一下。 所謂內(nèi)核策略化就是說(shuō)越來(lái)越多的?靈巧的算法?,?小tricks?等靈活多變的代碼進(jìn)入
    的頭像 發(fā)表于 12-26 09:44 ?1642次閱讀

    Linux內(nèi)核配置的網(wǎng)絡(luò)資料說(shuō)明

    Linux不止在上網(wǎng)時(shí)候才會(huì)用到網(wǎng)絡(luò)功能’一些程序在單機(jī)時(shí)候也會(huì)需要內(nèi)核網(wǎng)絡(luò)支持。 X server是個(gè)典型的例子。如果你是從一個(gè)老內(nèi)核
    發(fā)表于 03-12 10:33 ?14次下載

    Linux內(nèi)核網(wǎng)絡(luò)擁塞控制算法的具體實(shí)現(xiàn)框架(一)

    控制算法,有很大差別。本文從Linux內(nèi)核源碼中學(xué)習(xí)網(wǎng)絡(luò)擁塞
    的頭像 發(fā)表于 07-28 11:32 ?683次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核網(wǎng)絡(luò)</b><b class='flag-5'>擁塞</b><b class='flag-5'>控制</b><b class='flag-5'>算法</b>的具體<b class='flag-5'>實(shí)現(xiàn)</b><b class='flag-5'>框架</b>(一)

    Linux內(nèi)核網(wǎng)絡(luò)擁塞控制算法實(shí)現(xiàn)框架(三)

    下面看一個(gè)特別重要的框架,也可以稱為是擁塞控制引擎,如下結(jié)構(gòu)體所示, tcp_congestion_ops描述了一套擁塞控制
    的頭像 發(fā)表于 07-28 11:38 ?936次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核網(wǎng)絡(luò)</b><b class='flag-5'>擁塞</b><b class='flag-5'>控制</b><b class='flag-5'>算法</b>的<b class='flag-5'>實(shí)現(xiàn)</b><b class='flag-5'>框架</b>(三)