UDP 丢包的艺术
Posted dog250
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UDP 丢包的艺术相关的知识,希望对你有一定的参考价值。
不像 TCP 内置端到端流控机制,无连接的 UDP 在 Buffer 满了之后,只能丢弃当前收到的数据包,这是一个常规操作。
但注意,如果这是一条 UDP 隧道,即 UDP 运载了 TCP 载荷,简单丢弃该 UDP 报文就是一个针对 TCP 的尾丢操作:
尾丢往往会持续,进而引发 TCP 超时,如果多流共享隧道,还可能全局同步。总之,尾丢至少会引起 TCP (以及同样使能 Loss-based cc 的 AIMD 流量,如 CUBIC-QUIC)载荷带宽随时间呈大锯齿形波动。
这个地方做个 RED(random early detection)/WRED(weighted random early detection) 就好了,但只针对隧道 UDP,可以通过 iptables 命令模拟:
iptables -I INPUT -p udp --dport $隧道服务端口 -m statistic --mode random --probability 0.005 -j DROP
但这显然无法体现随机丢包的阈值,大突发流量下以稳定换吞吐(额外的丢包率"有可能"降低平均吞吐)。
下面的 HOOK 函数挂在 NF_INET_LOCAL_IN 上将会很高尚:
static unsigned int red_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
struct iphdr *iph;
struct sock *sk;
int rmem;
unsigned long rand[1];
iph = ip_hdr(skb);
if (iph->protocol != IPPROTO_UDP)
return NF_ACCEPT;
if (!skb->sk)
return NF_ACCEPT;
sk = skb->sk;
rmem = atomic_read(&sk->sk_rmem_alloc);
if (rmem > (sk->sk_rcvbuf - (sk->sk_rcvbuf >> 2)))
get_random_bytes(&rand[0], sizeof(unsigned long));
if (rand[0] % 200 == 0)
return NF_DROP;
return NF_ACCEPT;
RED/WRED 不仅可用于 UDP 隧道,对于普通 UDP 流量,RED/WRED 替换尾丢的高尚之处在于:
- 避开了连续丢包,统计分辨率和公平性更好。
- 应用层若做拥塞控制,拥塞更容易被感知。
端主机的 UDP Buffer,是 UDP 端到端的最后一个拥塞点,就像它在链路上一样好咯。
全局同步,准全局同步( RTT 一般都不同)都不是高尚的,对文件传输虽慢点倒还无害,但对流媒体传输就是咔咔咔了,瞬时速率无征兆跌零,给人一种失控之感觉。祸首是 Buffer 尾丢,这种风格的丢包会导致同一连接连续丢包,这也是时间局部性和 Bursty style 的结果。把丢包损失在事前分担给所有流量,最廉价的方案就是随机,就是 RED 背后的思想。
浙江温州皮鞋湿,下雨进水不会胖。
以上是关于UDP 丢包的艺术的主要内容,如果未能解决你的问题,请参考以下文章