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 背后的思想。

浙江温州皮鞋湿,下雨进水不会胖。

  • 1
    点赞
  • 3
    收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:编程工作室 设计师:CSDN官方博客 返回首页
评论 1

打赏作者

dog250

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值