Im trying to get the IHL and Version fields from an IP header using XDP, and when I output these values to the trace pipe using bpf_trace_printk the values appear correct but using perf_output i get invalid values such as IPV = 0, IHL = 69. Code is as follows
struct data_t{
u8 header_len:4, version:4;
}
BPF_PERF_OUTPUT(packets);
int xdp(struct xdp_md *ctx) {
void *data = (void *)(long)ctx->data;
void *data_end = (void *)(long)ctx->data_end;
struct data_t packet = {};
if (is_tcp_packet(data, data_end)) {
struct ethhdr *eth = data;
packet.type = eth->h_proto;
__builtin_memcpy(packet.src_mac, eth->h_source, ETH_ALEN);
__builtin_memcpy(packet.dst_mac, eth->h_dest, ETH_ALEN);
struct iphdr *iph = data + sizeof(struct ethhdr);
packet.version = iph->version;
packet.header_len = iph->ihl;
bpf_trace_printk("testing %u, %u", packet.version, packet.header_len);
packets.perf_submit(ctx, &packet, sizeof(packet));
}
return XDP_PASS;
}
And in the userspace i have
def callback(ctx, data, size):
packet = bpf["packets"].event(data)
print("VERSION=%u;HEADER_LEN=%u;" % (packet.version, packet.header_len))
bpf["packets"].open_perf_buffer(callback)
try:
print("Listening on IP:", ip)
#bpf.trace_print()
while True:
bpf.perf_buffer_poll()
except KeyboardInterrupt:
print("\n Unloading")
exit()
Why does this different behavior occur? Thanks in advance!
As mentioned in a comment by Dylan Reimerink assigning the variables to two separate bytes solved this issue: