I am new in eBPF and want to learn how to do a few basic things. My question is how to write in the C code for my eBPF code in order to print (bpf_trace_printk
) the UPD payload of an obtained packet in HEX. I have tried with no luck. Here is my current code:
int udppingpong(struct __sk_buff *skb)
{
void *data = (void *)(long)skb->data;
void *data_end = (void *)(long)skb->data_end;
struct ethhdr *eth = data;
struct iphdr *ip;
struct udphdr *udpdata;
if ((void *)eth + sizeof(*eth) > data_end) {
return TC_ACT_UNSPEC;
}
ip = data + sizeof(*eth);
if ((void *)ip + sizeof(*ip) > data_end) {
return TC_ACT_UNSPEC;
}
udpdata = (void *)ip + sizeof(*ip);
if ((void *)udpdata + sizeof(*udpdata) > data_end) {
return TC_ACT_UNSPEC;
}
if (eth->h_proto != htons(ETH_P_IP)) {
return TC_ACT_UNSPEC;
}
if (ip->protocol != IPPROTO_UDP) {
return TC_ACT_UNSPEC;
}
unsigned int payload_size;
unsigned char *payload;
payload_size = ntohs(udpdata->len) - sizeof(*udpdata);
payload = (unsigned char *)udpdata + sizeof(*udpdata);
if ((void *)payload + payload_size > data_end) {
return TC_ACT_UNSPEC;
}
__be16 port = udpdata->dest;
__be16 portToFilter = htons(7878);
if (port != portToFilter) {
return TC_ACT_OK;
}
__u32 src_ip = ip->saddr;
bpf_trace_printk("proto= %d, src= %lu\n", ip->protocol, src_ip); // --> This shows in decimal and network format (reversed), how to show actual IP like 1.2.3.4?
bpf_trace_printk("payload= %02x\n", payload); // --> HOW? I need it in hex to compare what is received
return TC_ACT_OK;
}
Special attention to the final lines with the traces. Could you help me on how to print the UDP payload in hex format as well as the source IP?
Thanks.
I would strongly recommend doing this sort of post processing in userspace; bpf_trace_printk
isn't meant for production environment anyway (see the large warnings it leaves in syslogs). It will also be difficult and inefficient to print the UDP payload with bpf_trace_printk
.
To post-process in userspace, you can rely on bpf_skb_output
, or its higher-level counterpart in bcc, perf_submit_skb()
. That will allow you to pass the packet to userspace, which can then display its UDP payload.
You can find a tutorial and an example on the bcc repository.
What you can do on the BPF side:
src_ip
in the IP address format is fairly easy. You can follow this StackOverflow answer.bpf_trace_printk
as follows.__u32 *data = payload;
bpf_trace_printk("payload= %x %x %x\n", *data, *(data+1), *(data+2));