如何定位发送设备中udp乱序的原因?

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

我正在使用 rk3588 设备将一些数据传输到与 phy 连接的设备,并且设备接收数据无序,例如 pack 0 pack 2 pack 1。但我确信我使用 0 1 2 顺序发送它1个线程,所以我使用tcpdump来定位数据出错的地方,我发现tcpdump中的数据在设备中已经乱序了,所以问题不是udp它自己(我想想),设备中的buf。 我试过 放大内存,如 sysctl -w net.core.wmem_default=33554423
sysctl -w net.core.wmem_max=33554423 ethtool -K eth tso 关闭 gso 关闭 tx 关闭, 它不起作用。dmesg 看起来一切都很好,我想找到问题并解决(如果有任何方法),至少定位问题。 根据研究,很多人建议使用tcp,并在我的数据中添加seq,但是在成熟的产品中不可能切换协议,而我已经添加了seq。但我的领导要求我找出原因,而不仅仅是逃避问题。我不知道,请帮助我。

设备接收乱序是可以接受的,但在rk3588本身,封装乱序是异常的。

发送功能主要结构:

    while (rate < 100)
    {
        memset(&st_read_restult.arr_pic_data, 0, sizeof(st_read_restult.arr_pic_data));
        st_read_restult.pic_data_index = 0;
        n_ret = st_sdk_bkg_dma_process.read_file_buf(&st_read_in, &st_read_restult);
        
        LOG_DEBUG(LOG_PICTURE, "n_picture_id [%d] en_file_type [%d] arr_file_path[%s] n_effective_num [%d]", g_st_bkg_tmp.n_picture_id, g_st_bkg_tmp.en_file_type, \
                g_st_bkg_tmp.arr_file_path, n_effective_num);
        //calculate package num
        n_op_cnt = 0;
        n_write_start = 0;
        n_effective_num = (st_read_restult.pic_data_index % PICTURE_DMA_WRITE_LEN) ? (st_read_restult.pic_data_index / PICTURE_DMA_WRITE_LEN + 1) : st_read_restult.pic_data_index / PICTURE_DMA_WRITE_LEN;

        for (i = 0; i < n_effective_num; i++)
        {
            bkg_write_t st_bkg_write = {0};
            //assign seq
            st_read_restult.n_pack_seq = n_pack_seq++;
            st_bkg_write.arr_pic_data = st_read_restult.arr_pic_data;
            st_bkg_write.n_write_start = n_write_start;
            st_bkg_write.n_bkg_data_len = (n_write_start + PICTURE_DMA_WRITE_LEN > st_read_restult.pic_data_index) ? (st_read_restult.pic_data_index - n_write_start) : PICTURE_DMA_WRITE_LEN;
            n_write_start += st_bkg_write.n_bkg_data_len;


            LOG_DEBUG(LOG_PICTURE,"start send dma[%d]", j);
            p_bkg_data_op[n_op_cnt] = NULL;
            SDK_MEM_ALLOC(p_bkg_data_op[n_op_cnt], sizeof(transfer_op_t), (transfer_op_t *)malloc, LOG_PICTURE, &n_ret, SDK_RET_MEM_OVER);
            n_ret = st_sdk_bkg_dma_process.dma_write_func_0(&st_bkg_write, p_index[j], p_bkg_data_op[n_op_cnt]);//send called finally
            n_op_cnt++;
            SDK_RET_CHECK(n_ret, LOG_PICTURE);
            // usleep(20);//add this sleep can slove out of oder problem
        }
    }
       

这是我的seq在包中的tcpdump结果

c udp
1个回答
0
投票

您的网络接口可能有多个传输队列(大多数现代网卡都有),并且根据您设置的流量整形排队规则,您生成的 UDP 包可能会根据填充状态放入不同的队列中每个队列——这可能会导致数据包重新排序。 (例如,默认的

mqprio
tc qdisc 就会执行此操作。)

您有几个选择:

  • 您可以选择始终将生成的 UDP 数据包排序到同一队列中的排队规则(但可能将其他数据包排序到不同的队列中)。不过,流量整形基础设施非常难以理解。

  • 您可以使用

    ethtool --set-channels ethXYZ tx 1
    (如果您的 NIC 驱动程序不支持单独配置 tx/rx,则使用
    ethtool --set-channels ethXYZ combined 1
    )强制您的 NIC 仅使用单个传输队列(systemd-networkd 也将其公开为
    TxChannels=
    /
    CombinedChannels=
    *.link
    文件的配置选项)。这可能会带来性能/CPU 使用率分布的缺点,特别是对于快速 NIC。 (特别是如果您必须将其用于组合通道,这也会影响您的接收队列。)

  • 您可以接受这样一个事实:NIC 中的多个传输队列会导致网络数据包重新排序。

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