TCP Pacing的linux内核代码

本文提出了一种名为TCPPacing的机制,旨在通过均匀分配数据包发送间隔来改善TCP在网络中的性能表现,尤其是在高延迟和高带宽的环境中。该方案提供了一种非侵入式的实现方式,并详细介绍了其配置选项及内核代码变更。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



TCP Pacing

From: Daniele Lacamera <root@danielinux.net>
To: Stephen Hemminger <shemminger@osdl.org>, "David S. Miller" <davem@davemloft.net>
Subject: TCP Pacing
Date: Tue, 12 Sep 2006 19:58:21 +0200
Cc: netdev@vger.kernel.org, Carlo Caini <ccaini@deis.unibo.it>, Rosario Firrincieli <rfirrincieli@arces.unibo.it>, Giovanni Pau <gpau@cs.ucla.edu>

Hello,

Please let me insist once again on the importance of adding a TCP Pacing 
mechanism in our TCP, as many people are including this algorithm in 
their congestion control proposals. Recent researches have found out 
that it really can help improving performance in different scenarios, 
like satellites and long-delay high-speed channels (>100ms RTT, Gbit). 
Hybla module itself is cripple without this feature in its natural 
scenario. 

The following patch is totally non-invasive: it has a config option and 
a sysctl switch, both turned off by default. When the config option is 
enabled, it adds only 6B to the tcp_sock.

Signed-off by: Daniele Lacamera <root@danielinux.net>
--- 







diff -ruN linux-2.6.18-rc6/Documentation/networking/ip-sysctl.txt
linux-pacing/Documentation/networking/ip-sysctl.txt
--- linux-2.6.18-rc6/Documentation/networking/ip-sysctl.txt	2006-09-04 04:19:48.000000000 +0200
+++ linux-pacing/Documentation/networking/ip-sysctl.txt	2006-09-12 16:38:14.000000000 +0200
@@ -369,6 +369,12 @@
 	be timed out after an idle period.
 	Default: 1
 
+tcp_pacing - BOOLEAN
+	If set, enable time-based TCP segment sending, instead of normal
+	ack-based sending. A software timer is set every time a new ack 
+	is received, then packets are spreaded across round-trip time.
+	Default: 0
+
 IP Variables:
 
 ip_local_port_range - 2 INTEGERS
diff -ruN linux-2.6.18-rc6/include/linux/sysctl.h linux-pacing/include/linux/sysctl.h
--- linux-2.6.18-rc6/include/linux/sysctl.h	2006-09-04 04:19:48.000000000 +0200
+++ linux-pacing/include/linux/sysctl.h	2006-09-12 18:13:38.000000000 +0200
@@ -411,6 +411,7 @@
 	NET_IPV4_TCP_WORKAROUND_SIGNED_WINDOWS=115,
 	NET_TCP_DMA_COPYBREAK=116,
 	NET_TCP_SLOW_START_AFTER_IDLE=117,
+	NET_TCP_PACING=118,
 };
 
 enum {
diff -ruN linux-2.6.18-rc6/include/linux/tcp.h linux-pacing/include/linux/tcp.h
--- linux-2.6.18-rc6/include/linux/tcp.h	2006-09-04 04:19:48.000000000 +0200
+++ linux-pacing/include/linux/tcp.h	2006-09-12 16:45:32.000000000 +0200
@@ -356,6 +356,17 @@
 		__u32		  probe_seq_start;
 		__u32		  probe_seq_end;
 	} mtu_probe;
+	
+#ifdef CONFIG_TCP_PACING
+/* TCP Pacing structure */
+	struct {
+		struct timer_list timer;
+		__u16   count;
+		__u16   burst;
+		__u8    lock;
+		__u8    delta;
+	} pacing;
+#endif
 };
 
 static inline struct tcp_sock *tcp_sk(const struct sock *sk)
diff -ruN linux-2.6.18-rc6/include/net/tcp.h linux-pacing/include/net/tcp.h
--- linux-2.6.18-rc6/include/net/tcp.h	2006-09-04 04:19:48.000000000 +0200
+++ linux-pacing/include/net/tcp.h	2006-09-12 17:07:49.000000000 +0200
@@ -227,6 +227,9 @@
 extern int sysctl_tcp_base_mss;
 extern int sysctl_tcp_workaround_signed_windows;
 extern int sysctl_tcp_slow_start_after_idle;
+#ifdef CONFIG_TCP_PACING
+extern int sysctl_tcp_pacing;
+#endif
 
 extern atomic_t tcp_memory_allocated;
 extern atomic_t tcp_sockets_allocated;
@@ -449,6 +452,11 @@
 extern unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu);
 extern unsigned int tcp_current_mss(struct sock *sk, int large);
 
+#ifdef CONFIG_TCP_PACING
+extern void tcp_pacing_recalc_delta(struct sock *sk);
+extern void tcp_pacing_reset_timer(struct sock *sk);
+#endif
+
 /* tcp.c */
 extern void tcp_get_info(struct sock *, struct tcp_info *);
 
diff -ruN linux-2.6.18-rc6/net/ipv4/Kconfig linux-pacing/net/ipv4/Kconfig
--- linux-2.6.18-rc6/net/ipv4/Kconfig	2006-09-04 04:19:48.000000000 +0200
+++ linux-pacing/net/ipv4/Kconfig	2006-09-12 16:59:37.000000000 +0200
@@ -572,6 +572,20 @@
 	loss packets.
 	See http://www.ntu.edu.sg/home5/ZHOU0022/papers/CPFu03a.pdf
 
+config TCP_PACING
+	bool "TCP Pacing"
+	depends on EXPERIMENTAL
+	select HZ_1000
+	default n
+	---help---
+	Many researchers have observed that TCP's congestion control mechanisms 
+	can lead to bursty traffic flows on modern high-speed networks, with a 
+	negative impact on overall network efficiency. A proposed solution to this 
+	problem is to evenly space, or "pace", data sent into the network over an 
+	entire round-trip time, so that data is not sent in a burst.
+	To enable this feature, please refer to Documentation/networking/ip-sysctl.txt.
+	If unsure, say N.
+	
 endmenu
 
 config TCP_CONG_BIC
diff -ruN linux-2.6.18-rc6/net/ipv4/sysctl_net_ipv4.c linux-pacing/net/ipv4/sysctl_net_ipv4.c
--- linux-2.6.18-rc6/net/ipv4/sysctl_net_ipv4.c	2006-09-04 04:19:48.000000000 +0200
+++ linux-pacing/net/ipv4/sysctl_net_ipv4.c	2006-09-12 18:33:36.000000000 +0200
@@ -697,6 +697,16 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec
 	},
+#ifdef CONFIG_TCP_PACING
+	{
+		.ctl_name	= NET_TCP_PACING,
+		.procname	= "tcp_pacing",
+		.data		= &sysctl_tcp_pacing,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec
+	},
+#endif
 	{ .ctl_name = 0 }
 };
 
diff -ruN linux-2.6.18-rc6/net/ipv4/tcp_input.c linux-pacing/net/ipv4/tcp_input.c
--- linux-2.6.18-rc6/net/ipv4/tcp_input.c	2006-09-04 04:19:48.000000000 +0200
+++ linux-pacing/net/ipv4/tcp_input.c	2006-09-12 17:11:38.000000000 +0200
@@ -2569,6 +2569,11 @@
 			tcp_cong_avoid(sk, ack, seq_rtt, prior_in_flight, 1);
 	}
 
+#ifdef CONFIG_TCP_PACING
+	if(sysctl_tcp_pacing)
+		tcp_pacing_recalc_delta(sk);
+#endif
+
 	if ((flag & FLAG_FORWARD_PROGRESS) || !(flag&FLAG_NOT_DUP))
 		dst_confirm(sk->sk_dst_cache);
 
diff -ruN linux-2.6.18-rc6/net/ipv4/tcp_output.c linux-pacing/net/ipv4/tcp_output.c
--- linux-2.6.18-rc6/net/ipv4/tcp_output.c	2006-09-04 04:19:48.000000000 +0200
+++ linux-pacing/net/ipv4/tcp_output.c	2006-09-12 18:12:38.000000000 +0200
@@ -62,6 +62,10 @@
 /* By default, RFC2861 behavior.  */
 int sysctl_tcp_slow_start_after_idle = 1;
 
+#ifdef CONFIG_TCP_PACING
+int sysctl_tcp_pacing=0;
+#endif
+
 static void update_send_head(struct sock *sk, struct tcp_sock *tp,
 			     struct sk_buff *skb)
 {
@@ -414,7 +418,13 @@
 		
 	if (tcp_packets_in_flight(tp) == 0)
 		tcp_ca_event(sk, CA_EVENT_TX_START);
-
+	
+#ifdef CONFIG_TCP_PACING
+	if(sysctl_tcp_pacing) {
+		tcp_pacing_reset_timer(sk);
+		tp->pacing.lock = 1;
+	}
+#endif
 	th = (struct tcphdr *) skb_push(skb, tcp_header_size);
 	skb->h.th = th;
 	skb_set_owner_w(skb, sk);
@@ -1085,7 +1095,15 @@
 {
 	const struct inet_connection_sock *icsk = inet_csk(sk);
 	u32 send_win, cong_win, limit, in_flight;
-
+	
+#ifdef CONFIG_TCP_PACING
+	/* TCP Pacing conflicts with this algorithm.
+	 * When Pacing is enabled, don't try to defer.
+	 */
+	if(sysctl_tcp_pacing)
+		return 0;
+#endif
+	
 	if (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)
 		return 0;
 
@@ -1308,7 +1326,12 @@
 
 		if (unlikely(!tcp_snd_wnd_test(tp, skb, mss_now)))
 			break;
-
+		
+#ifdef CONFIG_TCP_PACING
+		if (sysctl_tcp_pacing && tp->pacing.lock)
+			return 0;
+#endif
+		
 		if (tso_segs == 1) {
 			if (unlikely(!tcp_nagle_test(tp, skb, mss_now,
 						     (tcp_skb_is_last(sk, skb) ?
@@ -1323,6 +1346,10 @@
 		if (tso_segs > 1) {
 			limit = tcp_window_allows(tp, skb,
 						  mss_now, cwnd_quota);
+#ifdef CONFIG_TCP_PACING
+		if (sysctl_tcp_pacing && sent_pkts >= tp->pacing.burst)
+			tp->pacing.lock=1;
+#endif
 
 			if (skb->len < limit) {
 				unsigned int trim = skb->len % mss_now;
@@ -1733,6 +1760,11 @@
 		}
 	}
 
+#ifdef CONFIG_TCP_PACING
+	if (sysctl_tcp_pacing && tp->pacing.lock)
+		return -EAGAIN;
+#endif
+
 	/* Make a copy, if the first transmission SKB clone we made
 	 * is still in somebody's hands, else make a clone.
 	 */
diff -ruN linux-2.6.18-rc6/net/ipv4/tcp_timer.c linux-pacing/net/ipv4/tcp_timer.c
--- linux-2.6.18-rc6/net/ipv4/tcp_timer.c	2006-09-04 04:19:48.000000000 +0200
+++ linux-pacing/net/ipv4/tcp_timer.c	2006-09-12 18:03:17.000000000 +0200
@@ -36,10 +36,21 @@
 static void tcp_delack_timer(unsigned long);
 static void tcp_keepalive_timer (unsigned long data);
 
+#ifdef CONFIG_TCP_PACING
+static void tcp_pacing_timer(unsigned long data);
+#endif
+
 void tcp_init_xmit_timers(struct sock *sk)
 {
 	inet_csk_init_xmit_timers(sk, &tcp_write_timer, &tcp_delack_timer,
 				  &tcp_keepalive_timer);
+	
+#ifdef CONFIG_TCP_PACING
+	init_timer(&(tcp_sk(sk)->pacing.timer));
+	tcp_sk(sk)->pacing.timer.function=&tcp_pacing_timer;
+	tcp_sk(sk)->pacing.timer.data = (unsigned long) sk;
+#endif
+
 }
 
 EXPORT_SYMBOL(tcp_init_xmit_timers);
@@ -522,3 +533,115 @@
 	bh_unlock_sock(sk);
 	sock_put(sk);
 }
+
+#ifdef CONFIG_TCP_PACING
+/*
+ * This is the timer used to spread packets.
+ * a delta value is computed on rtt/cwnd,
+ * and will be our expire interval.
+ * The timer has to be restarted when a segment is sent out.
+ */
+static void tcp_pacing_timer(unsigned long data)
+{
+	struct sock *sk = (struct sock*)data;
+	struct tcp_sock *tp = tcp_sk(sk);
+
+	if(!sysctl_tcp_pacing)
+		return;
+
+	bh_lock_sock(sk);
+	if (sock_owned_by_user(sk)) {
+		/* Try again later */
+		if (!mod_timer(&tp->pacing.timer, jiffies + 1))
+			sock_hold(sk);
+		goto out_unlock;
+	}
+
+	if (sk->sk_state == TCP_CLOSE)
+		goto out;
+
+	/* Unlock sending, so when next ack is received it will pass.
+	 *If there are no packets scheduled, do nothing.
+	 */
+	tp->pacing.lock=0;
+	
+	if(!sk->sk_send_head){
+		/* Sending queue empty */
+		goto out;
+	}
+	
+	/*  Handler */
+	tcp_push_pending_frames(sk,tp);
+
+	out:
+	if (tcp_memory_pressure)
+		sk_stream_mem_reclaim(sk);
+
+	out_unlock:
+		bh_unlock_sock(sk);
+		sock_put(sk);
+}
+
+void tcp_pacing_reset_timer(struct sock *sk)
+{
+	struct tcp_sock *tp = tcp_sk(sk);
+	__u32 timeout = jiffies+tp->pacing.delta;
+
+	if(!sysctl_tcp_pacing)
+		return;
+	if (!mod_timer(&tp->pacing.timer, timeout))
+			sock_hold(sk);
+}
+EXPORT_SYMBOL(tcp_pacing_reset_timer);
+
+/*
+ * This routine computes tcp_pacing delay, using
+ * a simplified uniform pacing policy.
+ */
+void tcp_pacing_recalc_delta(struct sock *sk)
+{
+       struct tcp_sock *tp=tcp_sk(sk);
+       __u32 window=(tp->snd_cwnd)<<3;
+       __u32 srtt = tp->srtt;
+       __u32 round=0;
+       __u32 curmss=tp->mss_cache;
+       int state=inet_csk(sk)->icsk_ca_state;
+
+       if( (state==TCP_CA_Recovery) &&(tp->snd_cwnd < tp->snd_ssthresh))
+		window=(tp->snd_ssthresh)<<3;
+
+       if( (tp->snd_wnd/curmss) < tp->snd_cwnd )
+		window = (tp->snd_wnd/curmss)<<3;
+
+       if (window>1 && srtt){
+               if (window <= srtt){
+                       tp->pacing.delta=(srtt/window);
+			if(srtt%window)
+				round=( (srtt/(srtt%window)) / tp->pacing.delta);
+			if (tp->pacing.count >= (round-1) &&(round>1)){
+				tp->pacing.delta++;
+				tp->pacing.count=0;
+			}
+			tp->pacing.burst=1;
+		} else {
+			tp->pacing.delta=1;
+			tp->pacing.burst=(window/srtt);
+			if(window%srtt)
+				round=( (window/(window%srtt)) * tp->pacing.burst);
+			if (tp->pacing.count >= (round-1) && (round>1)){
+				tp->pacing.burst++;
+				tp->pacing.count=0;
+			}
+		}
+	} else {
+		tp->pacing.delta=0;
+		tp->pacing.burst=1;
+       }
+}
+
+EXPORT_SYMBOL(tcp_pacing_recalc_delta);
+
+#endif
+
+
+
【转自】http://lwn.net/Articles/199644/

<think>好的,我现在需要帮助用户了解Linux中tc工具使用的拥塞避免算法的实现方式。用户之前的问题是关于为什么Linux TC没有实现WFQ和WRR算法,现在他转向了拥塞避免算法,这需要我结合之前的回答和相关引用资料来组织答案。 首先,我需要明确用户的问题:用户想知道Linux tc工具如何实现拥塞避免算法。拥塞避免和队列管理相关,所以可能需要讨论TC中的队列规则(qdisc)和相关算法。根据之前的引用,特别是引用[5]提到了FQ(公平队列)与BBR的结合,以及引用[2]中提到的入向流量整形,还有引用[4]中的TCP拥塞控制的发展方向,这些都可能与TC的拥塞避免有关。 接下来,我需要回顾之前关于TC的回答,其中提到了DRR、HTB、SFQ等队列规则,以及社区更倾向于使用fq_codel和cake这样的现代算法。拥塞避免通常与主动队列管理(AQM)相关,比如CoDel和RED算法,这些可能在TC中有实现。 用户提供的引用中有几个关键点需要注意:引用[2]提到入向流量整形,引用[5]详细解释了FQ如何与BBR配合使用,而引用[4]讨论了TCP拥塞控制的未来发展,包括智能算法和跨层优化。这些可能都需要在回答中涉及。 首先,我应该解释TC中的拥塞避免主要依赖哪些队列规则。例如,fq_codel和cake都是结合了AQM的算法,用于管理队列长度和延迟,从而避免拥塞。然后,需要说明这些算法如何工作,比如CoDel是如何监控延迟并丢弃数据包的,或者FQ如何与BBR协同实现流量平滑。 另外,用户提到的引用[5]中提到BBR必须与FQ一起使用,以实现pacing rate,这说明了TC中队列规则与TCP拥塞控制算法的协作。这也需要解释,比如FQ如何管理数据包发送的节奏,避免突发流量导致网络拥塞。 同时,之前的回答中提到了HTB和SFQ的组合,这可能与带宽分配和公平性有关,但拥塞避免更关注于防止队列溢出和减少延迟,所以可能需要区分队列调度算法和拥塞避免算法的不同侧重点。 接下来,我需要确保回答的结构清晰,分点说明不同的实现方式,例如基于AQM的算法、与TCP算法的协同、用户空间工具等。还需要结合具体的tc命令示例,比如如何配置fq_codel或cake,以及如何监控效果。 需要注意的是,引用中的资料可能没有直接说明TC的拥塞避免算法,但可以通过已有的知识补充。例如,CoDel和RED是经典的AQM算法,而Linux中的实现可能是通过相应的qdisc模块。同时,结合用户提供的引用[5],FQ与BBR的协作也是一个重点,需要说明TC如何通过FQ来辅助TCP的拥塞控制。 最后,生成相关问题时要考虑用户可能的后续疑问,比如如何选择算法、配置参数的影响,或者与其他工具的集成等。 现在,我需要将这些思考整理成一个结构化的回答,确保覆盖TC中的拥塞避免实现方式,包括算法类型、具体实现机制、配置示例以及与TCP层的协作,同时引用提供的资料来支持内容。</think>#### Linux TC 拥塞避免算法实现方式解析 --- ##### 一、核心实现架构 Linux TC 的拥塞避免主要通过**队列规则(qdisc)**和**主动队列管理(AQM)算法**实现,与 TCP 层的拥塞控制形成协同: - **层级化调度模型** TC 通过多级 `class` 和 `qdisc` 构建树形结构,例如: ```bash # 创建 HTB 根队列 + fq_codel 叶队列 tc qdisc add dev eth0 root handle 1: htb tc class add dev eth0 parent 1: classid 1:1 htb rate 100mbit tc qdisc add dev eth0 parent 1:1 fq_codel limit 1024 flows 4096 # AQM 核心配置[^2] ``` 这里 `fq_codel` 同时实现公平队列(FQ)和拥塞避免(CoDel)。 - **与 TCP 层的联动** 如引用[5]所述,BBR 算法依赖 `fq` 实现 pacing rate,TC 的队列规则通过**延迟测量**和**丢包反馈**直接影响 TCP 拥塞窗口调整: ```plaintext BBR 工作流程: 1. 应用层数据 → TCP BBR → 计算 pacing_rate 2. TC fq qdisc → 按 pacing_rate 平滑发送数据包 3. 网络拥塞 → CoDel 主动丢包 → TCP 触发拥塞控制[^5] ``` --- ##### 二、主要拥塞避免算法实现 ###### 1. **CoDel (Controlled Delay)** 通过动态监测**包停留时间**而非队列长度来触发丢包,更适合现代网络环境: - **实现机制**: ```c // 内核代码片段(net/sched/sch_codel.c): static bool codel_should_drop(struct sk_buff *skb, struct Qdisc *sch) { if (codel_time_after_eq(now, vars->drop_next)) { // 检查是否达到丢包时间阈值 vars->count++; // 丢包计数器递增(指数退避) return true; } return false; } ``` - **TC 配置示例**: ```bash tc qdisc add dev eth0 root codel target 5ms interval 100ms # target:最大容忍延迟(默认5ms) # interval:监测窗口(默认100ms)[^2] --- ###### 2. **FQ_Codel (Fair Queuing + CoDel)** 结合公平队列和延迟控制的双重机制: - **双重作用**: - **FQ 层**:通过哈希将流量分散到 1024 个子队列,防止单一流垄断带宽 - **CoDel 层**:在每个子队列独立运行 CoDel 算法 - **关键参数**: ```bash tc qdisc add dev eth0 parent 1:1 fq_codel \ limit 1024 \ # 总包缓存数量 flows 4096 \ # 最大并发流数 quantum 1514 \ # 每轮调度发送字节数 target 5ms \ # 目标最大延迟 interval 100ms \ # 延迟监测间隔 ecn # 启用显式拥塞通知[^2] --- ###### 3. **CAKE (Common Applications Kept Enhanced)** 面向复杂网络环境的增强型算法,集成多种优化: - **核心特性**: - 自动识别并优先处理 ACK/SYN 等控制包 - 支持 NAT 场景下的流识别(通过 triplets hash) - 集成双速率三色标记器(DiffServ 支持) - **配置示例**: ```bash tc qdisc add dev eth0 root cake \ bandwidth 500mbit \ # 接口总带宽 diffserv4 \ # DiffServ 优先级映射 nat \ # NAT 模式流识别 wash # 清除 DSCP 标记[^2] --- ##### 三、算法实现对比 | 特性 | CoDel | FQ_Codel | CAKE | |---------------------|-----------------|------------------|------------------| | 核心目标 | 单队列延迟控制 | 多流公平+延迟控制| 复杂网络综合优化 | | 流状态跟踪 | 无 | 哈希表(O(1)) | 三重哈希(NAT感知)| | 适用场景 | 家庭网关 | 数据中心 | 企业级路由器 | | 10Gbps 线速支持 | 部分(单核) | 是(多核扩展) | 是(硬件卸载) | | BBR 协同能力 | 低 | 高 | 中等 | --- ##### 四、与 TCP 层的协同优化 如引用[4]和[5]所述,现代拥塞控制算法(如 BBR/Cubic)与 TC 深度集成: - **BBR + FQ 组合** BBR 通过 `setsockopt` 设置 `SO_MAX_PACING_RATE`,`fq` qdisc 按此速率平滑发送: ```c // 内核 TCP 栈中的 pacing 计算(net/ipv4/tcp_output.c): void tcp_update_pacing_rate(struct sock *sk) { u64 rate = sk->sk_pacing_rate; // 由 BBR 动态计算 sk->sk_pacing_rate = min(rate, sk->sk_max_pacing_rate); } ``` TC 的 `fq` 会读取此值并按间隔调度包发送[^5]。 - **ECN (Explicit Congestion Notification)** 启用 ECN 后,TC 会通过 IP 头部的 ECN 位通知发送端降速,而非直接丢包: ```bash # 启用 ECN(需要内核和双方主机支持) tc qdisc add dev eth0 root fq_codel ecn sysctl -w net.ipv4.tcp_ecn=1 ``` --- ##### 五、监控与调优工具 - **实时队列状态查看**: ```bash tc -s qdisc show dev eth0 # 显示丢包/延迟统计 ``` 输出示例: ```plaintext qdisc fq_codel 8001: root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms ecn Sent 123456 bytes 789 pkt (dropped 12, overlimits 0 requeues 3) backlog 0b 0p requeues 3 maxpacket 512 drop_overlimit 0 new_flow_count 15 ecn_mark 0 delay 4.2ms # 当前队列延迟 ``` - **性能调优建议**: 1. **带宽过载场景**:优先使用 `cake` 并开启 `diffserv` 分级 2. **低延迟需求**:缩小 `fq_codel` 的 `target`(如 2ms) 3. **高吞吐场景**:增大 `quantum` 值减少调度开销 --- #### 扩展实践 若要实现类似传统网络设备的 WRED(加权随机早期检测),可通过 `red` qdisc: ```bash tc qdisc add dev eth0 root red \ limit 600000 min 30000 max 60000 avpkt 1500 \ burst 50 ecn bandwidth 1gbit # min/max:队列长度阈值(字节) # avpkt:平均包大小(用于计算平均队列深度) ``` [^1]: Linux 5.6 TCP 拥塞控制代码变更 [^2]: 《Linux 高级路由与流量控制手册》第九章 [^3]: TCP_Cubic_V2 项目文档 [^4]: 现代 TCP 协议发展趋势分析 [^5]: BBR 算法与 FQ 的协同设计原理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值