Output from trace pipe and perf_output are different

45 Views Asked by At

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!

1

There are 1 best solutions below

0
Afonso Pinto On

As mentioned in a comment by Dylan Reimerink assigning the variables to two separate bytes solved this issue:

struct data_t{
    u8 header_len;
    u8 version;
}