linux - AF-XDP:小数据包有问题吗?
问题描述
在 AF-XDP 套接字框架 (+ libbpf) 中是否存在关于数据包大小的已知(或可能未知)错误?
我的应用程序遇到奇怪的数据包丢失:
- IPv4/UDP/RTP 数据包流,所有数据包大小相同(1442 字节):无数据包丢失
- IPv4/UDP/RTP 数据包流,其中几乎所有数据包的大小都相同(1492 字节),除了一个特殊的“标记”数据包(只有 357 字节,但它们也是 IPv4/UDP 数据包):所有标记数据包都会丢失
bpf_printk
我在我的 XDP-Kernelprogram 中添加了一条语句:
const int len = bpf_ntohs(iph->tot_len);
if(len < 400) {
bpf_printk("FOUND PACKET LEN < 400: %d.\n", len);
}
永远不会通过 观察到此输出sudo cat /sys/kernel/debug/tracing/trace_pipe
。所以我的内核过滤器甚至没有收到这些小的 RTP 标记数据包——难怪我在用户空间中没有收到它们。
ethtool -S <if>
给我看这个号码:rx_256_to_511_bytes_phy
。这个数字的增长速度与标记数据包应该进来的速度相似(大约 30/s)。所以这意味着我的 NIC 确实收到了数据包,但我的 XDP 程序没有 - 为什么?
知道什么可能是这个问题的原因吗?
解决方案
首先,bpf_printk()
并不总是对我有用。您可能想看看这个片段(内核空间代码):
// Nicer way to call bpf_trace_printk()
#define bpf_custom_printk(fmt, ...) \
({ \
char ____fmt[] = fmt; \
bpf_trace_printk(____fmt, sizeof(____fmt), \
##__VA_ARGS__); \
})
// print:
bpf_custom_printk("This year is %d\n", 2020);
// output: sudo cat /sys/kernel/debug/tracing/trace_pipe
第二:可能是数据包进入了其他网卡队列。您可能想使用xdp-tutorial中的 vanilla 代码,并从上面的代码片段添加内核跟踪以打印数据包的大小,然后编译并运行示例程序,例如-q 1
队列号 1。
一种获取数据包大小的方法:
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
size_t size_pkt = data - data_end;
bpf_custom_printk("Packet size %d\n", size_pkt);
推荐阅读
- java - 使用spring 4从系统环境变量中获取数据
- c# - 如果我知道大部分时间结果将被缓存,则避免 async/await
- r - 如何合并长度不等但已知块长度的数据帧?
- r - 建立回归结果表
- android - java.lang.IllegalStateException:默认 FirebaseApp 未初始化
- html - 将 HTML 背景颜色设置为 JS 变量
- javascript - 通过 jQuery 和 PHP 设置元素的 html
- powershell - 不使用 WMI 获取磁盘信息
- scipy - 关于加快 SciPy 自定义分布采样和拟合的建议
- c# - 在 Visual Studio 中使用哪个 AWS Lambda 模板