diff --git a/tools/testing/selftests/bpf/progs/test_tunnel_kern.c b/tools/testing/selftests/bpf/progs/test_tunnel_kern.c index 2318edf510bd..a1046c2ecba4 100644 --- a/tools/testing/selftests/bpf/progs/test_tunnel_kern.c +++ b/tools/testing/selftests/bpf/progs/test_tunnel_kern.c @@ -8,12 +8,16 @@ */ #define BPF_NO_PRESERVE_ACCESS_INDEX #include "vmlinux.h" +#include #include #include #include "bpf_kfuncs.h" #include "bpf_tracing_net.h" #define log_err(__ret) bpf_printk("ERROR line:%d ret:%d\n", __LINE__, __ret) +#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER)) +#define offsetofend(TYPE, MEMBER) \ + (offsetof(TYPE, MEMBER) + sizeof_field(TYPE, MEMBER)) #define VXLAN_UDP_PORT 4789 #define ETH_P_IP 0x0800 @@ -144,6 +148,15 @@ int ip6gretap_get_tunnel(struct __sk_buff *skb) return TC_ACT_OK; } +/* Direct bitfield writes make the verifier unhappy. + * Access struct erspan_md2's i'th bitfield as a u8 to avoid + * unhappiness. + */ +#define __ERSPAN_MD2_BITFIELD(m, i) \ + *(((__u8 *)m) + offsetofend(struct erspan_md2, sgt) + i) +#define ERSPAN_MD2_BITFIELD0(m) __ERSPAN_MD2_BITFIELD(m, 0) +#define ERSPAN_MD2_BITFIELD1(m) __ERSPAN_MD2_BITFIELD(m, 1) + SEC("tc") int erspan_set_tunnel(struct __sk_buff *skb) { @@ -173,9 +186,9 @@ int erspan_set_tunnel(struct __sk_buff *skb) __u8 hwid = 7; md.version = 2; - md.u.md2.dir = direction; - md.u.md2.hwid = hwid & 0xf; - md.u.md2.hwid_upper = (hwid >> 4) & 0x3; + ERSPAN_MD2_BITFIELD0(&md.u.md2) |= (hwid >> 4) & 0x3; /* hwid_upper */ + ERSPAN_MD2_BITFIELD1(&md.u.md2) |= (direction & 0x1) << 3; /* dir */ + ERSPAN_MD2_BITFIELD1(&md.u.md2) |= (hwid & 0xf) << 4; /* hwid */ #endif ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md)); @@ -214,8 +227,9 @@ int erspan_get_tunnel(struct __sk_buff *skb) bpf_printk("\tindex %x\n", index); #else bpf_printk("\tdirection %d hwid %x timestamp %u\n", - md.u.md2.dir, - (md.u.md2.hwid_upper << 4) + md.u.md2.hwid, + BPF_CORE_READ_BITFIELD(&md.u.md2, dir), + (BPF_CORE_READ_BITFIELD(&md.u.md2, hwid_upper) << 4) + + BPF_CORE_READ_BITFIELD(&md.u.md2, hwid), bpf_ntohl(md.u.md2.timestamp)); #endif @@ -252,9 +266,9 @@ int ip4ip6erspan_set_tunnel(struct __sk_buff *skb) __u8 hwid = 17; md.version = 2; - md.u.md2.dir = direction; - md.u.md2.hwid = hwid & 0xf; - md.u.md2.hwid_upper = (hwid >> 4) & 0x3; + ERSPAN_MD2_BITFIELD0(&md.u.md2) |= (hwid >> 4) & 0x3; /* hwid_upper */ + ERSPAN_MD2_BITFIELD1(&md.u.md2) |= (direction & 0x1) << 3; /* dir */ + ERSPAN_MD2_BITFIELD1(&md.u.md2) |= (hwid & 0xf) << 4; /* hwid */ #endif ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md)); @@ -294,8 +308,9 @@ int ip4ip6erspan_get_tunnel(struct __sk_buff *skb) bpf_printk("\tindex %x\n", index); #else bpf_printk("\tdirection %d hwid %x timestamp %u\n", - md.u.md2.dir, - (md.u.md2.hwid_upper << 4) + md.u.md2.hwid, + BPF_CORE_READ_BITFIELD(&md.u.md2, dir), + (BPF_CORE_READ_BITFIELD(&md.u.md2, hwid_upper) << 4) + + BPF_CORE_READ_BITFIELD(&md.u.md2, hwid), bpf_ntohl(md.u.md2.timestamp)); #endif