下面看一個特別重要的框架,也可以稱為是擁塞控制引擎,如下結構體所示, tcp_congestion_ops描述了一套擁塞控制算法所需要支持的操作 。這個框架定義了一些鉤子函數,Linux內核中不同的擁塞控制算法根據算法思想實現以下鉤子函數,然后進行注冊即可完成擁塞控制算法的設計。
struct tcp_congestion_ops {
struct list_head list;
u32 key;
u32 flags;
/* initialize private data (optional) */
void (*init)(struct sock *sk);
/* cleanup private data (optional) */
void (*release)(struct sock *sk);
/* return slow start threshold (required) */
u32 (*ssthresh)(struct sock *sk);
/* do new cwnd calculation (required) */
void (*cong_avoid)(struct sock *sk, u32 ack, u32 acked);
/* call before changing ca_state (optional) */
void (*set_state)(struct sock *sk, u8 new_state);
/* call when cwnd event occurs (optional) */
void (*cwnd_event)(struct sock *sk, enum tcp_ca_event ev);
/* call when ack arrives (optional) */
void (*in_ack_event)(struct sock *sk, u32 flags);
/* new value of cwnd after loss (required) */
u32 (*undo_cwnd)(struct sock *sk);
/* hook for packet ack accounting (optional) */
void (*pkts_acked)(struct sock *sk, const struct ack_sample *sample);
/* suggest number of segments for each skb to transmit (optional) */
u32 (*tso_segs_goal)(struct sock *sk);
/* returns the multiplier used in tcp_sndbuf_expand (optional) */
u32 (*sndbuf_expand)(struct sock *sk);
/* call when packets are delivered to update cwnd and pacing rate,
* after all the ca_state processing. (optional)
*/
void (*cong_control)(struct sock *sk, const struct rate_sample *rs);
/* get info for inet_diag (optional) */
size_t (*get_info)(struct sock *sk, u32 ext, int *attr,
union tcp_cc_info *info);
char name[TCP_CA_NAME_MAX];
struct module *owner;
};
用戶可以通過自定義以上鉤子函數實現定制擁塞控制算法,并進行注冊。以下截取cubic擁塞控制算法對接口的實現、注冊****的代碼片段。 可以注意到cubic只實現了擁塞控制引擎tcp_congestion_ops的部分鉤子函數,因為有一些鉤子函數是必須實現,有一些是根據算法選擇實現的。
static struct tcp_congestion_ops cubictcp __read_mostly = {
.init = bictcp_init,
.ssthresh = bictcp_recalc_ssthresh,
.cong_avoid = bictcp_cong_avoid,
.set_state = bictcp_state,
.undo_cwnd = tcp_reno_undo_cwnd,
.cwnd_event = bictcp_cwnd_event,
.pkts_acked = bictcp_acked,
.owner = THIS_MODULE,
.name = "cubic",
};
static int __init cubictcp_register(void)
{
BUILD_BUG_ON(sizeof(struct bictcp) > ICSK_CA_PRIV_SIZE);
beta_scale = 8*(BICTCP_BETA_SCALE+beta) / 3
/ (BICTCP_BETA_SCALE - beta);
cube_rtt_scale = (bic_scale * 10); /* 1024*c/rtt */
cube_factor = 1ull < < (10+3*BICTCP_HZ); /* 2^40 */
/* divide by bic_scale and by constant Srtt (100ms) */
do_div(cube_factor, bic_scale * 10);
return tcp_register_congestion_control(&cubictcp);
}
static void __exit cubictcp_unregister(void)
{
tcp_unregister_congestion_control(&cubictcp);
}
module_init(cubictcp_register);
module_exit(cubictcp_unregister);
在Linux用戶態可以 通過參數查看當前使用的擁塞控制算法、當前可支持的擁塞控制算法 。如下表所示是兩個參數以及含義。
參數 | 含義 |
---|---|
net.ipv4.tcp_congestion_control | 當前運行的擁塞控制算法 |
net.ipv4.tcp_available_congestion_control | 當前可支持的擁塞控制算法 |
具體如下圖所示,通過參數看到當前可支持的擁塞控制算法以及當前使用的擁塞控制算法。可以看到當前可支持的擁塞控制算法中包含bbr算法, bbr算法在內核版本4.9開始支持的。
如果留意的話,在本文開始時提到了很多傳統的擁塞控制算法,那么在上面的命令中沒有看到,其實有眾多擁塞控制算法在Linux中沒有進行安裝,如下命令 查看Linux系統中所有已實現的擁塞控制算法模塊 :
如果想安裝特定的擁塞控制算法可以通過modprobe命令對指定的擁塞控制算法進行安裝,如下所示安裝了Vegas擁塞控制算法,此時再查看當前系統中可以使用的擁塞控制算法,多了一個Vegas算法。
除了可以動態查看當前Linux系統可用的擁塞控制算法、當前使用的擁塞控制算法外還可以動態切換擁塞控制算法。如下所示將默認的cubic擁塞控制算法切換為bbr擁塞控制算法。
切換后驗證如下,當前運行的擁塞控制算法由之前的cubic擁塞控制算法切換到了bbr擁塞控制算法。
至此本文關于Linux內核網絡中擁塞控制的大概框架、原理介紹到這,文中有表達有誤或者不準確的地方歡迎指正。關于具體的每個擁塞控制算法的實現,將在后續文章中呈現。
-
內核
+關注
關注
3文章
1372瀏覽量
40290 -
Linux
+關注
關注
87文章
11304瀏覽量
209521 -
網絡
+關注
關注
14文章
7565瀏覽量
88792
發布評論請先 登錄
相關推薦
評論