为tuntap接口启用GSO似乎会减慢流量

问题描述 投票:0回答:1

我遇到了与内部制作的VPN相关的相对令人失望的表现。

界面 速度Mb/s
enp5s0 950
tun0 550

我开始相信罪魁祸首(以及其他一些)是 TCP 分段(参见这篇文章)。

问题是,linux网络不是我的专长,我觉得有点超出了我的深度,我不太确定理解GSO是如何工作的,它需要什么,甚至这确实是我正在寻找的(我希望不要陷入 XY 问题)。

我将使用 Homer Simpsonsimpletun 作为案例研究。

我愿意接受替代方案,但我主要是询问在 TUN 接口之间启用 GSO 的正确方法,以尽可能晚地卸载前向分段(我认为就性能而言这是有利的)。

问题涉及 Linux 上的网络。我暂时不关心与任何其他操作系统的互操作性。

扩展问题

记录

我一直很难找到有关此功能的正确文档。目前我只能找到

我做了什么

我添加了 ifr 标志

IFF_VNET_HDR
,如一些给出的来源中所解释的 我添加了一个 ioctl 调用,另一个是为了设置我认为正确的向前卸载标志

  • F_CSUM:禁用校验和
  • F_TS04、F_TSO6:启用 tcp 分段错误
/**************************************************************************
 * tun_alloc: allocates or reconnects to a tun/tap device. The caller     *
 *            must reserve enough space in *dev.                          *
 **************************************************************************/
int tun_alloc(char *dev, int flags) {

  struct ifreq ifr;
  int fd, err;
  char *clonedev = "/dev/net/tun";

  if( (fd = open(clonedev , O_RDWR)) < 0 ) {
    perror("Opening /dev/net/tun");
    return fd;
  }

  memset(&ifr, 0, sizeof(ifr));

  // flags = 0x0001 ≡ IFF_TUN
  // flag IFF_VNET_HDR necessary ?
  ifr.ifr_flags = flags | IFF_NO_PI | IFF_VNET_HDR;

  if (*dev) {
    strncpy(ifr.ifr_name, dev, IFNAMSIZ);
  }

  if( (err = ioctl(fd, TUNSETIFF, (void *)&ifr)) < 0 ) {
    perror("ioctl(TUNSETIFF)");
    close(fd);
    return err;
  }


  // setting up offload
  unsigned long offload_flags = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6;

  if ( (err = ioctl(fd, TUNSETOFFLOAD, offload_flags)) < 0 ) {
    perror("ioctl(TUNSETOFFLOAD)");
    close(fd);
    return err;
  }
  // --------------------------------------------------------------

  strcpy(dev, ifr.ifr_name);

  return fd;
}

预期结果

我预计 VPN 会因为卸载而提高性能。

取得的成果

这导致速度稍微慢一些。使用 iperf3 获得的结果

界面 速度Mb/s
enp5s0 942
tun0 324

这让我感到困惑,我可以理解一个特定的错误,但我不明白如何最终得到较慢的结果。

附件

iperf3

> iperf3 -c $SERVER_IP
Connecting to host 192.168.50.112, port 5201
[  5] local 192.168.30.175 port 53126 connected to 192.168.50.112 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec   114 MBytes   952 Mbits/sec    0    529 KBytes       
[  5]   1.00-2.00   sec   113 MBytes   949 Mbits/sec    0    557 KBytes       
[  5]   2.00-3.00   sec   112 MBytes   939 Mbits/sec    0    617 KBytes       
[  5]   3.00-4.00   sec   111 MBytes   933 Mbits/sec    0    747 KBytes       
[  5]   4.00-5.00   sec   112 MBytes   944 Mbits/sec    0    783 KBytes       
[  5]   5.00-6.00   sec   112 MBytes   944 Mbits/sec    0    783 KBytes       
[  5]   6.00-7.00   sec   111 MBytes   933 Mbits/sec    0    820 KBytes       
[  5]   7.00-8.00   sec   112 MBytes   944 Mbits/sec    0    909 KBytes       
[  5]   8.00-9.00   sec   112 MBytes   944 Mbits/sec    0    909 KBytes       
[  5]   9.00-10.00  sec   111 MBytes   933 Mbits/sec    0    953 KBytes       
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  1.10 GBytes   942 Mbits/sec    0             sender
[  5]   0.00-10.00  sec  1.09 GBytes   939 Mbits/sec                  receiver

iperf Done.

> iperf3 -B 10.10.9.1%tun0 -c $SERVER_IP
Connecting to host 192.168.50.112, port 5201
[  5] local 10.10.9.1 port 52443 connected to 192.168.50.112 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec   107 KBytes   879 Kbits/sec   20   2.83 KBytes       
[  5]   1.00-2.00   sec  45.2 KBytes   371 Kbits/sec   10   4.24 KBytes       
[  5]   2.00-3.00   sec  41.0 KBytes   336 Kbits/sec   10   5.66 KBytes       
[  5]   3.00-4.00   sec  39.6 KBytes   324 Kbits/sec    8   4.24 KBytes       
[  5]   4.00-5.00   sec  39.6 KBytes   324 Kbits/sec   10   5.66 KBytes       
[  5]   5.00-6.00   sec  39.6 KBytes   324 Kbits/sec   10   5.66 KBytes       
[  5]   6.00-7.00   sec  79.2 KBytes   649 Kbits/sec    8   7.07 KBytes       
[  5]   7.00-8.00   sec  39.6 KBytes   324 Kbits/sec   10   5.66 KBytes       
[  5]   8.00-9.00   sec  39.6 KBytes   324 Kbits/sec   11   1.41 KBytes       
[  5]   9.00-10.00  sec  39.6 KBytes   324 Kbits/sec    9   2.83 KBytes       
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec   510 KBytes   418 Kbits/sec  106             sender
[  5]   0.00-10.08  sec   431 KBytes   351 Kbits/sec                  receiver

iperf Done.
c linux performance networking tun-tap
1个回答
0
投票

查看 iperf3 输出,通过 tun0 接口时似乎出现数据包丢失问题。请注意 iperf 输出中的“Retr”和“Cwnd”列。第一个是重传。第二个是拥塞窗口。 TCP 连接性能的(许多)限制之一是:

吞吐量 <= EffectiveWindow / RoundTripTime

如果您将 Cwnd 的值插入为“EffectiveWindow”以及连接的 RoundTripTime(例如 ping 显示的内容),我怀疑您会发现在 tun0 情况下您受到拥塞窗口大小的限制。要增加这一点,您需要找到丢弃的来源(也许 tun0 上的传输队列太短?只是猜测)并解决它。

Linux 下默认的拥塞控制启发式“cubic”对连接早期的数据包丢失特别敏感。

© www.soinside.com 2019 - 2024. All rights reserved.