【问题标题】:Why am I receiving packer bigger than with raw packet为什么我收到的打包机比原始数据包大
【发布时间】:2021-10-23 06:52:26
【问题描述】:

我正在尝试使用原始数据包将数据包从一个接口传输到另一个接口(仅用于播放)。 首先,我专注于接收到的数据包。

在我的机器(archlinux,IP 为 192.168.30.3)上,我创建了以下代码:

#include <stdio.h>
#include <net/ethernet.h>       /* the L2 protocols */
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>

int main()
{
    int packet_socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IP));


    /* test reception */
    char packet[4096];
    struct sockaddr rcvaddr;
    struct in_addr addr;
    addr.s_addr = inet_addr("192.168.30.3");    //my ip

    // use nc to send a use packet
    while (1) {
        int len = sizeof(rcvaddr);
        int len_packet =
            recvfrom(packet_socket, packet, 4096, 0, &rcvaddr, &len);

        // check if the packet is for us
        struct iphdr *iph =
            (struct iphdr *) (packet + sizeof(struct ethhdr));
        if (iph->daddr != inet_addr("192.168.30.3"))
            continue;

        // check if tcp
        if (iph->protocol != IPPROTO_TCP)
            continue;

        printf("Total packet length: %d\n",
               sizeof(struct ethhdr) + ntohs(iph->tot_len));
    }
}

然后我以root身份运行它并执行nc -lp 12345 -n &gt; /dev/null

在另一台机器上(debian,192.168.30.4)我运行dd if=/dev/urandom | nc 192.168.30.3 12345 这使得我之前的程序打印接收到的数据包的长度。

从中,我看到有大于 MTU 大小的数据包(即 1500 在两台机器上)。例如,我可以从我的程序中读取“总数据包长度:16962”。 (linux raw ethernet socket receive more bytes than MTU 也观察到了)。

我知道 IP 分段,所以我首先想到了 IP 重组。 但是我在man 7 raw 中读到: “请注意,与原始套接字不同,数据包套接字不会重新组装 IP 片段。” 因为我使用了数据包套接字(AF_PACKET),所以我不应该有数据包 重新组装然后保持 MTU 大小正确?

我也做了sudo ethtool -K ens3 tx off sg off tso off 并使用值 0、1、2 和 3 进行测试 在两台机器上的 /proc/sys/net/ipv4/ip_no_pmtu_disc 中。

您认为 192.168.30.4 发送的 MTU 更多吗?或者我的机器是否进行了一些重新组装,尽管 说明书上写了什么?

ethtool -k ens3 给出:

在 192.168.30.4:

seb@SERVER:~$ sudo ethtool -k ens3 
Features for ens3:
rx-checksumming: off
tx-checksumming: off
        tx-checksum-ipv4: off [fixed]
        tx-checksum-ip-generic: off
        tx-checksum-ipv6: off [fixed]
        tx-checksum-fcoe-crc: off [fixed]
        tx-checksum-sctp: off [fixed]
scatter-gather: off
        tx-scatter-gather: off
        tx-scatter-gather-fraglist: off [fixed]
tcp-segmentation-offload: off
        tx-tcp-segmentation: off
        tx-tcp-ecn-segmentation: off [fixed]
        tx-tcp-mangleid-segmentation: off
        tx-tcp6-segmentation: off [fixed]
udp-fragmentation-offload: off
generic-segmentation-offload: off [requested on]
generic-receive-offload: on
large-receive-offload: off [fixed]
rx-vlan-offload: on
tx-vlan-offload: on [fixed]
ntuple-filters: off [fixed]
receive-hashing: off [fixed]
highdma: off [fixed]
rx-vlan-filter: on [fixed]
vlan-challenged: off [fixed]
tx-lockless: off [fixed]
netns-local: off [fixed]
tx-gso-robust: off [fixed]
tx-fcoe-segmentation: off [fixed]
tx-gre-segmentation: off [fixed]
tx-gre-csum-segmentation: off [fixed]
tx-ipxip4-segmentation: off [fixed]
tx-ipxip6-segmentation: off [fixed]
tx-udp_tnl-segmentation: off [fixed]
tx-udp_tnl-csum-segmentation: off [fixed]
tx-gso-partial: off [fixed]
tx-sctp-segmentation: off [fixed]
tx-esp-segmentation: off [fixed]
tx-udp-segmentation: off [fixed]
fcoe-mtu: off [fixed]
tx-nocache-copy: off
loopback: off [fixed]
rx-fcs: off
rx-all: off
tx-vlan-stag-hw-insert: off [fixed]
rx-vlan-stag-hw-parse: off [fixed]
rx-vlan-stag-filter: off [fixed]
l2-fwd-offload: off [fixed]
hw-tc-offload: off [fixed]
esp-hw-offload: off [fixed]
esp-tx-csum-hw-offload: off [fixed]
rx-udp_tunnel-port-offload: off [fixed]
tls-hw-tx-offload: off [fixed]
tls-hw-rx-offload: off [fixed]
rx-gro-hw: off [fixed]
tls-hw-record: off [fixed]

在 192.168.30.3:

[seb@archlinux ~]$ sudo ethtool -k ens3
Features for ens3:
rx-checksumming: off
tx-checksumming: off
        tx-checksum-ipv4: off [fixed]
        tx-checksum-ip-generic: off
        tx-checksum-ipv6: off [fixed]
        tx-checksum-fcoe-crc: off [fixed]
        tx-checksum-sctp: off [fixed]
scatter-gather: off
        tx-scatter-gather: off
        tx-scatter-gather-fraglist: off [fixed]
tcp-segmentation-offload: off
        tx-tcp-segmentation: off
        tx-tcp-ecn-segmentation: off [fixed]
        tx-tcp-mangleid-segmentation: off
        tx-tcp6-segmentation: off [fixed]
generic-segmentation-offload: off [requested on]
generic-receive-offload: on
large-receive-offload: off [fixed]
rx-vlan-offload: on
tx-vlan-offload: on [fixed]
ntuple-filters: off [fixed]
receive-hashing: off [fixed]
highdma: off [fixed]
rx-vlan-filter: on [fixed]
vlan-challenged: off [fixed]
tx-lockless: off [fixed]
netns-local: off [fixed]
tx-gso-robust: off [fixed]
tx-fcoe-segmentation: off [fixed]
tx-gre-segmentation: off [fixed]
tx-gre-csum-segmentation: off [fixed]
tx-ipxip4-segmentation: off [fixed]
tx-ipxip6-segmentation: off [fixed]
tx-udp_tnl-segmentation: off [fixed]
tx-udp_tnl-csum-segmentation: off [fixed]
tx-gso-partial: off [fixed]
tx-tunnel-remcsum-segmentation: off [fixed]
tx-sctp-segmentation: off [fixed]
tx-esp-segmentation: off [fixed]
tx-udp-segmentation: off [fixed]
tx-gso-list: off [fixed]
fcoe-mtu: off [fixed]
tx-nocache-copy: off
loopback: off [fixed]
rx-fcs: off
rx-all: off
tx-vlan-stag-hw-insert: off [fixed]
rx-vlan-stag-hw-parse: off [fixed]
rx-vlan-stag-filter: off [fixed]
l2-fwd-offload: off [fixed]
hw-tc-offload: off [fixed]
esp-hw-offload: off [fixed]
esp-tx-csum-hw-offload: off [fixed]
rx-udp_tunnel-port-offload: off [fixed]
tls-hw-tx-offload: off [fixed]
tls-hw-rx-offload: off [fixed]
rx-gro-hw: off [fixed]
tls-hw-record: off [fixed]
rx-gro-list: off
macsec-hw-offload: off [fixed]
rx-udp-gro-forwarding: off
hsr-tag-ins-offload: off [fixed]
hsr-tag-rm-offload: off [fixed]
hsr-fwd-offload: off [fixed]
hsr-dup-offload: off [fixed]

另外,请注意这两台机器是由 GNS3 运行的 qemu 机器,具有以下网络选项:-net none -device e1000,mac=0c:7e:08:49:13:00,netdev=gns3-0 -netdev socket,id=gns3-0,udp=127.0.0.1:20049,localaddr=127.0.0.1:20048

【问题讨论】:

  • 不幸的是,关闭 lro 会产生相同的结果。我只是编辑我的问题以添加您想要的信息。由于两台机器都是VM,所以我会在真机上尝试(可能hypervisor创建了一个大缓冲区)
  • 我的猜测:您忽略了选项。开始阅读这些 RFC...
  • @wildplasser:你能详细说明一下吗?你在说什么“选项”?什么 RFC?
  • @stackinside :我禁用了通用接收卸载。这会产生更好的结果。在确认之前我正在做更多的实验。
  • @stackinside:我确认禁用 GRO 可以解决我的问题(出于性能原因,这可能不是一件好事,但它回答了我的问题)。您的第一条评论显然给了我很好的思考方式,所以是的,您可以提供 LRO/GRO 建议作为答案。

标签: c networking raw-sockets mtu


【解决方案1】:

由于观察到的总数据包长度远大于典型巨型帧 (MTU 9k) 的总长度,因此接收端显然采用 Large Receive Offload (LRO) 或 Generic Receive Offload (GRO) ) 从而在网络接口驱动程序级别将较小的数据包重新组装成较大的数据包。这可以解释为什么有问题的数据包套接字看到已经重新组装的(大)数据包。

在这种特定情况下,ethtool -k 输出清楚地表明 LRO 始终处于禁用状态,而 GRO 确实处于活动状态并且可以进行调整。根据 cmets 中的讨论,禁用 GRO 确实有效果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-18
    • 2017-04-09
    • 1970-01-01
    • 1970-01-01
    • 2013-12-14
    • 1970-01-01
    相关资源
    最近更新 更多