Linux kernel eBPF:将UDP有效负载和源IP打印为十六进制

Linux kernel eBPF:将UDP有效负载和源IP打印为十六进制,linux-kernel,kernel,bpf,ebpf,Linux Kernel,Kernel,Bpf,Ebpf,我是eBPF的新手,想学习如何做一些基本的事情。我的问题是如何为我的eBPF代码编写C代码,以便以十六进制打印(bpf\u trace\u printk)获得的数据包的UPD有效负载。我试过了,但运气不好。这是我目前的代码: int-udppingpong(结构) { 空*数据=(空*)(长)skb->数据; 空*数据结束=(空*)(长)skb->数据结束; 结构ethhdr*eth=数据; 结构iphdr*ip; 结构udphdr*udpdata; 如果((空*)eth+sizeof(*eth

我是eBPF的新手,想学习如何做一些基本的事情。我的问题是如何为我的eBPF代码编写C代码,以便以十六进制打印(
bpf\u trace\u printk
)获得的数据包的UPD有效负载。我试过了,但运气不好。这是我目前的代码:

int-udppingpong(结构)
{
空*数据=(空*)(长)skb->数据;
空*数据结束=(空*)(长)skb->数据结束;
结构ethhdr*eth=数据;
结构iphdr*ip;
结构udphdr*udpdata;
如果((空*)eth+sizeof(*eth)>数据结束){
返回TC_ACT_UNSPEC;
}
ip=数据+尺寸(*eth);
如果((无效*)ip+sizeof(*ip)>数据结束){
返回TC_ACT_UNSPEC;
}
udpdata=(无效*)ip+sizeof(*ip);
如果((void*)udpdata+sizeof(*udpdata)>数据结束){
返回TC_ACT_UNSPEC;
}
if(eth->h_proto!=htons(eth_P_IP)){
返回TC_ACT_UNSPEC;
}
如果(ip->协议!=IPPROTO_UDP){
返回TC_ACT_UNSPEC;
}
无符号整数有效载荷大小;
无符号字符*有效载荷;
有效载荷大小=ntohs(udpdata->len)-sizeof(*udpdata);
有效负载=(无符号字符*)udpdata+sizeof(*udpdata);
如果((无效*)有效载荷+有效载荷大小>数据结束){
返回TC_ACT_UNSPEC;
}
__be16端口=udpdata->dest;
__be16端口过滤器=htons(7878);
if(端口!=端口过滤器){
返回TC\u ACT\u OK;
}
__u32 src_ip=ip->SADD;
bpf_trace_printk(“proto=%d,src=%lu\n”,ip->protocol,src_ip);//-->这以十进制和网络格式(反向)显示,如何显示实际ip,如1.2.3.4?
bpf_trace_printk(“有效负载=%02x\n”,有效负载);//-->如何使用?我需要十六进制的它来比较接收到的内容
返回TC\u ACT\u OK;
}
特别注意带有痕迹的最终线条。您能帮助我如何以十六进制格式打印UDP有效负载以及源IP吗


谢谢。

我强烈建议在用户空间中进行这种后期处理<代码>bpf_trace_printk并不适用于生产环境(请参阅它在系统日志中留下的大量警告)。使用
bpf\u trace\u printk
打印UDP有效负载也将是困难和低效的


在用户空间中进行后期处理,您可以依赖
bpf_skb_输出
,或其在bcc中的更高级别对应项,
perf_submit_skb()
。这将允许您将数据包传递给用户空间,然后用户空间可以显示其UDP负载

您可以在bcc存储库中找到和


您可以在BPF端执行的操作

  • 以ip地址格式打印
    src_ip
    相当容易。你可以跟着
  • 您不能打印完整的、可变长度的UDP有效负载,但可以通过将前N个字节传递给
    bpf\u trace\u printk
    来打印,如下所示
\uu32*数据=有效载荷;
bpf_trace_printk(“有效负载=%x%x%x\n”,*数据,*(数据+1),*(数据+2));

当我这样做时,我看不到该行的任何输出:code:trace\u printk(“payload\u size=%u\n”,payload\u size);trace_printk(“a=%02x b=%02x c=%02x\n”,数据,数据+1,数据+2);输出:-0[000]…s。795860.863937:0:payload_size=15未打印有效负载。请参阅警告:bpf.c:115:9:警告:不兼容的指针类型使用类型为“unsigned char*”[-Wincompatible pointer types]\uuuu u32*dataudp=payload的表达式初始化“uuu u32*”(也称为“unsigned int*”);可以尝试类似于
bpf_trace_printk(“有效负载=%x%x%x\n”、*数据、*(数据+1)、*(数据+2))?看起来您需要取消引用这些指针,并且格式修饰符(
%02x
中的
02
)不受支持,因此禁止输出
bpf\u trace\u printk()
@qole在这两个错误上是正确的。我更新了答案。面向未来读者的指针:中的
bpf\u trace\u printk()
说明了支持的格式说明符和修饰符。