Morten Brørup, Jul 19, 2024 at 12:46:
When passing an IPv4 address as a value, alignment does matter; it
must be 4 byte aligned.
I was expecting the compiler to do what is necessary to copy the data to
an aligned register before jumping to the function.
On a CPU with 128 bit registers, I would probably also pass an IPv6
address as a value. With such a CPU, the parameter type should be
uint128_t or rte_be128_t, depending on byte order.
I don't think there is a portable/standard uint128_t yet. Everything
I could find is either GCC or linux specific.
There's a 3rd option:
Have an IPv6 type that is simply an array of 16 bytes with no explicitly
specified alignment:
struct rte_ipv6_addr {
unsigned char addr_bytes[RTE_IPV6_ADDR_LEN];
};
Or:
typedef struct rte_ipv6_addr {
unsigned char addr_bytes[RTE_IPV6_ADDR_LEN];
} rte_ipv6_addr_t;
If used as is, it will be unaligned.
And if alignment offers improved performance for some use cases,
explicit alignment attributes can be added to the type in those use
cases.
Not using an uint128_t type (or a union of other types than unsigned
char) will also avoid byte order issues.
I guess Stephen was right to begin with. :-)
Having the type as a union (as is the POSIX type) makes casting to
integers a lot less tedious and makes the structure overall more
flexible.
We could completely add an unaligned be128 member to the union by the
way. I don't see what is wrong with having sub union members.
About your concern with byte order, since the union members have
explicit rte_be*_t types, I don't think confusion can happen. I have
also renamed the members, replacing the "u" prefix with "a" so that it
does not indicate that it should be used as a host integer.
struct __rte_aligned(1) rte_ipv6_addr {
union {
unsigned char a[16];
unaligned_be16_t a16[8];
unaligned_be32_t a32[4];
unaligned_be64_t a64[2];
unaligned_be128_t a128[1];
};
} __rte_packed;