On Thu, 18 Jul 2024 22:27:03 +0200 Morten Brørup <m...@smartsharesystems.com> wrote:
> > From: Robin Jarry [mailto:rja...@redhat.com] > > > > Hi folks, > > > > while working on IPv6 support for grout [1], I noticed that all DPDK > > IPv6 APIs used fixed sized arrays in the route lookup functions [2]. > > > > int rte_fib6_lookup_bulk(struct rte_fib6 *fib, > > uint8_t ips[][RTE_FIB6_IPV6_ADDR_SIZE], > > uint64_t *next_hops, > > int n); > > > > If I'm not mistaken, using sized arrays in function signatures is only > > for documentation purposes and does not result in any specific compiler > > checks. In the above example, the ips parameter is considered as a plain > > old `uint8_t **` pointer. > > > > Also, not having a dedicated type for IPv6 addresses requires obscure > > pointer arithmetic [3] and casting [4]. > > > > I'd like to introduce a real IPv6 address structure that has the same > > alignment than a dumb `uint8_t *` pointer but has an union to ease > > casting and most importantly presents the whole thing as an explicit > > typed structure: > > > > #define RTE_IPV6_ADDR_SIZE 16 > > > > struct rte_ipv6_addr { > > union { > > uint8_t u8[RTE_IPV6_ADDR_SIZE]; > > uint16_t u16[RTE_IPV6_ADDR_SIZE / sizeof(uint16_t)]; > > uint32_t u32[RTE_IPV6_ADDR_SIZE / sizeof(uint32_t)]; > > uint64_t u64[RTE_IPV6_ADDR_SIZE / sizeof(uint64_t)]; > > }; > > } __rte_packed __rte_aligned(1); > > > > This would require some breakage of the APIs but I think it would > > benefit code readability and maintainability in the long term. > > In short: Although I like the idea of a unified IPv6 address type very much, > I'm not sure consensus can be reached about the optimal alignment of such a > type. > > The long version: > > Please consider this proposal in a broader perspective. > > The IPv4 FIB lookup takes an uint32_t array, so the IPv4 address type here is > 4 byte aligned: uint32_t *ips > Generally, uint32_t or rte_be32_t is used for IPv4 addresses, and both these > types are 4 byte aligned. In other words: IPv4 addresses are considered 4 > byte aligned by DPDK. > > I don't think it is similarly simple for IPv6 addresses. > > The alignment of IPv6 addresses may depend on how/where they are used, e.g.: > 1. For the FIB library, it might be good for vector implementations to have > the IPv6 addresses naturally aligned (i.e. 16 byte aligned), like the > uint128_t/__int128/__m128i type (or the rte_xmm_t type [XMM]). Furthermore, a > simple integer type (uint128_t equivalent) might be preferable in this API. > 2. In the IPv6 packet header, the IPv6 addresses are not 16 byte aligned, > they are 8 byte aligned. So we cannot make the IPv6 address type 16 byte > aligned. > > I fear that broadly dumbing down the IPv6 address type to always use 1 byte > alignment could potentially introduce unwanted performance penalties (now or > in the future). We didn't do it for IPv4 addresses, so let's not do it for > IPv6 addresses. > > Perhaps we could use the lowest "non-exotic" (considering the use of IPv6 > addresses) alignment, which I would guess is 8 byte - as in the IPv6 packet > header. > For reference, Ethernet addresses are defined as 2 byte aligned [ETH]. > > [XMM]: > https://elixir.bootlin.com/dpdk/v24.03/source/lib/eal/x86/include/rte_vect.h#L42 > [ETH]: > https://elixir.bootlin.com/dpdk/v24.07-rc2/source/lib/net/rte_ether.h#L74 > > > > > int rte_fib6_lookup_bulk(struct rte_fib6 *fib, > > const struct rte_ipv6_addr *ips, > > uint64_t *next_hops, > > int n); > > > > I already have a semi-working draft and am in the process of splitting > > the changes into small chunks to make them easier to review. > > > > https://github.com/DPDK/dpdk/compare/main...rjarry:dpdk:ipv6-address- > > rework > > > > Is that something that would be of interest? If yes, I would like to > > announce API breakage before the release of 24.07 so that the changes > > can be integrated into 24.11. > > > > Cheers! > > > > [1] https://github.com/rjarry/grout > > [2] > > https://doc.dpdk.org/api/rte__fib6_8h.html#a924678410ccb9551cda3e75d742a > > 11e3 > > [3] https://git.dpdk.org/dpdk/tree/lib/fib/trie_avx512.c?h=v24.07- > > rc2#n340 > > [4] https://git.dpdk.org/dpdk/tree/lib/hash/rte_thash.h?h=v24.07- > > rc2#n156 > > > > -- > > Robin > If you look at the standard netinet/in.h the storage of IPv6 addresses is in in6_addr. DPDK has always wanted to do its own thing... The in6_addr is a union with no explicit alignment. struct in6_addr { union { uint8_t __u6_addr8[16]; uint16_t __u6_addr16[8]; uint32_t __u6_addr32[4]; } __in6_u; Better to not have explicit alignment and not have 64 bit value.