question about struct xdp_md


William Tu
 

Hi,

I'm looking at definition of xdp_md:
struct xdp_md {
__u32 data;
__u32 data_end;
};

I'm curious why are we using __u32? Isn't data and data_end an 8-byte
pointer to the packet's buffer? For example in xdp2_kern.c

int xdp_prog1(struct xdp_md *ctx)
{
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
struct ethhdr *eth = data;

Am I missing something? Thank you!
Regards,
William


Alexei Starovoitov
 

On Sun, Jul 31, 2016 at 11:05:55PM -0700, William Tu via iovisor-dev wrote:
Hi,

I'm looking at definition of xdp_md:
struct xdp_md {
__u32 data;
__u32 data_end;
};

I'm curious why are we using __u32? Isn't data and data_end an 8-byte
pointer to the packet's buffer? For example in xdp2_kern.c

int xdp_prog1(struct xdp_md *ctx)
{
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
struct ethhdr *eth = data;

Am I missing something? Thank you!
__u32 is a meta field that points to either smaller or larger real field.
All fields are __u32 so far for simplicity. We have a lot more of them
in __sk_buff, for example.
We could have made data and data_end to be __u64, but void* cast is still
needed and generated code is pretty much the same, so kept it as u32
to avoid kernel changes for no visible benefit.
Using void* in __sk_buff would be confusing. Despite __sk_buff suppose
to be used only in bpf program, the sizeof(void*) changes with arch and
bpf.h will appear in 32-bit userland.
Yet another option was __aligned_u64, but it's even more confusing.
At the end __sk_buff and xdp_md are meta fields, so having them all as
__u32 is more consistent.


William Tu
 

Hi Alexei,

Thanks! Looking at the xdp_convert_ctx_access(), now I understand that
it's actually doesn't matter and the generated code is the same.

Regards,
William

On Mon, Aug 1, 2016 at 10:02 AM, Alexei Starovoitov
<alexei.starovoitov@...> wrote:
On Sun, Jul 31, 2016 at 11:05:55PM -0700, William Tu via iovisor-dev wrote:
Hi,

I'm looking at definition of xdp_md:
struct xdp_md {
__u32 data;
__u32 data_end;
};

I'm curious why are we using __u32? Isn't data and data_end an 8-byte
pointer to the packet's buffer? For example in xdp2_kern.c

int xdp_prog1(struct xdp_md *ctx)
{
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
struct ethhdr *eth = data;

Am I missing something? Thank you!
__u32 is a meta field that points to either smaller or larger real field.
All fields are __u32 so far for simplicity. We have a lot more of them
in __sk_buff, for example.
We could have made data and data_end to be __u64, but void* cast is still
needed and generated code is pretty much the same, so kept it as u32
to avoid kernel changes for no visible benefit.
Using void* in __sk_buff would be confusing. Despite __sk_buff suppose
to be used only in bpf program, the sizeof(void*) changes with arch and
bpf.h will appear in 32-bit userland.
Yet another option was __aligned_u64, but it's even more confusing.
At the end __sk_buff and xdp_md are meta fields, so having them all as
__u32 is more consistent.