Kui-Feng, You are right. Maybe simply "load_word" and "load_byte" would be a better name here. WDYT? -Jordan On Fri, Apr 12, 2024 at 6:01 PM Kui-Feng Lee <sinquersw@xxxxxxxxx> wrote: > > > > On 4/12/24 09:52, Jordan Rife wrote: > > Without this fix, the bind4 and bind6 programs will reject bind attempts > > on big endian systems. This patch ensures that CI tests pass for the > > s390x architecture. > > > > Signed-off-by: Jordan Rife <jrife@xxxxxxxxxx> > > --- > > .../testing/selftests/bpf/progs/bind4_prog.c | 18 ++++++++++-------- > > .../testing/selftests/bpf/progs/bind6_prog.c | 18 ++++++++++-------- > > tools/testing/selftests/bpf/progs/bind_prog.h | 19 +++++++++++++++++++ > > 3 files changed, 39 insertions(+), 16 deletions(-) > > create mode 100644 tools/testing/selftests/bpf/progs/bind_prog.h > > > > diff --git a/tools/testing/selftests/bpf/progs/bind4_prog.c b/tools/testing/selftests/bpf/progs/bind4_prog.c > > index a487f60b73ac4..2bc052ecb6eef 100644 > > --- a/tools/testing/selftests/bpf/progs/bind4_prog.c > > +++ b/tools/testing/selftests/bpf/progs/bind4_prog.c > > @@ -12,6 +12,8 @@ > > #include <bpf/bpf_helpers.h> > > #include <bpf/bpf_endian.h> > > > > +#include "bind_prog.h" > > + > > #define SERV4_IP 0xc0a801feU /* 192.168.1.254 */ > > #define SERV4_PORT 4040 > > #define SERV4_REWRITE_IP 0x7f000001U /* 127.0.0.1 */ > > @@ -118,23 +120,23 @@ int bind_v4_prog(struct bpf_sock_addr *ctx) > > > > // u8 narrow loads: > > user_ip4 = 0; > > - user_ip4 |= ((volatile __u8 *)&ctx->user_ip4)[0] << 0; > > - user_ip4 |= ((volatile __u8 *)&ctx->user_ip4)[1] << 8; > > - user_ip4 |= ((volatile __u8 *)&ctx->user_ip4)[2] << 16; > > - user_ip4 |= ((volatile __u8 *)&ctx->user_ip4)[3] << 24; > > + user_ip4 |= load_byte_ntoh(ctx->user_ip4, 0, sizeof(user_ip4)); > > + user_ip4 |= load_byte_ntoh(ctx->user_ip4, 1, sizeof(user_ip4)); > > + user_ip4 |= load_byte_ntoh(ctx->user_ip4, 2, sizeof(user_ip4)); > > + user_ip4 |= load_byte_ntoh(ctx->user_ip4, 3, sizeof(user_ip4)); > > if (ctx->user_ip4 != user_ip4) > > return 0; > > > > user_port = 0; > > - user_port |= ((volatile __u8 *)&ctx->user_port)[0] << 0; > > - user_port |= ((volatile __u8 *)&ctx->user_port)[1] << 8; > > + user_port |= load_byte_ntoh(ctx->user_port, 0, sizeof(user_port)); > > + user_port |= load_byte_ntoh(ctx->user_port, 1, sizeof(user_port)); > > if (ctx->user_port != user_port) > > return 0; > > > > // u16 narrow loads: > > user_ip4 = 0; > > - user_ip4 |= ((volatile __u16 *)&ctx->user_ip4)[0] << 0; > > - user_ip4 |= ((volatile __u16 *)&ctx->user_ip4)[1] << 16; > > + user_ip4 |= load_word_ntoh(ctx->user_ip4, 0, sizeof(user_ip4)); > > + user_ip4 |= load_word_ntoh(ctx->user_ip4, 1, sizeof(user_ip4)); > > if (ctx->user_ip4 != user_ip4) > > return 0; > > > > diff --git a/tools/testing/selftests/bpf/progs/bind6_prog.c b/tools/testing/selftests/bpf/progs/bind6_prog.c > > index d62cd9e9cf0ea..194583e3375bf 100644 > > --- a/tools/testing/selftests/bpf/progs/bind6_prog.c > > +++ b/tools/testing/selftests/bpf/progs/bind6_prog.c > > @@ -12,6 +12,8 @@ > > #include <bpf/bpf_helpers.h> > > #include <bpf/bpf_endian.h> > > > > +#include "bind_prog.h" > > + > > #define SERV6_IP_0 0xfaceb00c /* face:b00c:1234:5678::abcd */ > > #define SERV6_IP_1 0x12345678 > > #define SERV6_IP_2 0x00000000 > > @@ -129,25 +131,25 @@ int bind_v6_prog(struct bpf_sock_addr *ctx) > > // u8 narrow loads: > > for (i = 0; i < 4; i++) { > > user_ip6 = 0; > > - user_ip6 |= ((volatile __u8 *)&ctx->user_ip6[i])[0] << 0; > > - user_ip6 |= ((volatile __u8 *)&ctx->user_ip6[i])[1] << 8; > > - user_ip6 |= ((volatile __u8 *)&ctx->user_ip6[i])[2] << 16; > > - user_ip6 |= ((volatile __u8 *)&ctx->user_ip6[i])[3] << 24; > > + user_ip6 |= load_byte_ntoh(ctx->user_ip6[i], 0, sizeof(user_ip6)); > > + user_ip6 |= load_byte_ntoh(ctx->user_ip6[i], 1, sizeof(user_ip6)); > > + user_ip6 |= load_byte_ntoh(ctx->user_ip6[i], 2, sizeof(user_ip6)); > > + user_ip6 |= load_byte_ntoh(ctx->user_ip6[i], 3, sizeof(user_ip6)); > > if (ctx->user_ip6[i] != user_ip6) > > return 0; > > } > > > > user_port = 0; > > - user_port |= ((volatile __u8 *)&ctx->user_port)[0] << 0; > > - user_port |= ((volatile __u8 *)&ctx->user_port)[1] << 8; > > + user_port |= load_byte_ntoh(ctx->user_port, 0, sizeof(user_port)); > > + user_port |= load_byte_ntoh(ctx->user_port, 1, sizeof(user_port)); > > if (ctx->user_port != user_port) > > return 0; > > > > // u16 narrow loads: > > for (i = 0; i < 4; i++) { > > user_ip6 = 0; > > - user_ip6 |= ((volatile __u16 *)&ctx->user_ip6[i])[0] << 0; > > - user_ip6 |= ((volatile __u16 *)&ctx->user_ip6[i])[1] << 16; > > + user_ip6 |= load_word_ntoh(ctx->user_ip6[i], 0, sizeof(user_ip6)); > > + user_ip6 |= load_word_ntoh(ctx->user_ip6[i], 1, sizeof(user_ip6)); > > if (ctx->user_ip6[i] != user_ip6) > > return 0; > > } > > diff --git a/tools/testing/selftests/bpf/progs/bind_prog.h b/tools/testing/selftests/bpf/progs/bind_prog.h > > new file mode 100644 > > index 0000000000000..0fdc466aec346 > > --- /dev/null > > +++ b/tools/testing/selftests/bpf/progs/bind_prog.h > > @@ -0,0 +1,19 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > +#ifndef __BIND_PROG_H__ > > +#define __BIND_PROG_H__ > > + > > +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ > > +#define load_byte_ntoh(src, b, s) \ > > + (((volatile __u8 *)&(src))[b] << 8 * b) > > +#define load_word_ntoh(src, w, s) \ > > + (((volatile __u16 *)&(src))[w] << 16 * w) > > +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ > > +#define load_byte_ntoh(src, b, s) \ > > + (((volatile __u8 *)&(src))[(b) + (sizeof(src) - (s))] << 8 * ((s) - (b) - 1)) > > +#define load_word_ntoh(src, w, s) \ > > + (((volatile __u16 *)&(src))[w] << 16 * (((s) / 2) - (w) - 1)) > These names, load_byte_ntoh() and load_word_ntoh(), are miss-leading. > > They don't actually do byte-order conversion from network order to host > order. Network order is big endian. 0xdeadbeef in u32 should be stored > as the sequence of > > 0xde, 0xad, 0xbe, 0xef > > The little endian implementation of load_word_ntoh() provided here will > return 0xadde and 0xefbe0000. However, a network order to host order > conversion should return 0xbeef and 0xdead0000 for little endian. > > The little endian implementation of load_byte_ntoh() here returns 0xde, > 0xad00, 0xbe0000, and 0xef000000. However, a network to host order > conversion should return 0xef, 0xbe00, 0xad0000, and 0xde00000. > > So, they just access raw data following the host byte order, not > providing any byte order conversion. > > > > +#else > > +# error "Fix your compiler's __BYTE_ORDER__?!" > > +#endif > > + > > +#endif