199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 299a2dd95SBruce Richardson * Copyright(c) 2018 Vladimir Medvedkin <medvedkinv@gmail.com> 399a2dd95SBruce Richardson * Copyright(c) 2019 Intel Corporation 499a2dd95SBruce Richardson */ 599a2dd95SBruce Richardson 699a2dd95SBruce Richardson #ifndef _TRIE_H_ 799a2dd95SBruce Richardson #define _TRIE_H_ 899a2dd95SBruce Richardson 9e9fd1ebfSTyler Retzlaff #include <stdalign.h> 10e9fd1ebfSTyler Retzlaff 11*6cb10a9bSRobin Jarry #include <rte_common.h> 12*6cb10a9bSRobin Jarry #include <rte_fib6.h> 13*6cb10a9bSRobin Jarry 1499a2dd95SBruce Richardson /** 1599a2dd95SBruce Richardson * @file 1699a2dd95SBruce Richardson * RTE IPv6 Longest Prefix Match (LPM) 1799a2dd95SBruce Richardson */ 1899a2dd95SBruce Richardson 1999a2dd95SBruce Richardson /* @internal Total number of tbl24 entries. */ 2099a2dd95SBruce Richardson #define TRIE_TBL24_NUM_ENT (1 << 24) 2199a2dd95SBruce Richardson /* @internal Number of entries in a tbl8 group. */ 2299a2dd95SBruce Richardson #define TRIE_TBL8_GRP_NUM_ENT 256ULL 2399a2dd95SBruce Richardson /* @internal Total number of tbl8 groups in the tbl8. */ 2499a2dd95SBruce Richardson #define TRIE_TBL8_NUM_GROUPS 65536 2599a2dd95SBruce Richardson /* @internal bitmask with valid and valid_group fields set */ 2699a2dd95SBruce Richardson #define TRIE_EXT_ENT 1 2799a2dd95SBruce Richardson 2899a2dd95SBruce Richardson #define BITMAP_SLAB_BIT_SIZE_LOG2 6 2999a2dd95SBruce Richardson #define BITMAP_SLAB_BIT_SIZE (1ULL << BITMAP_SLAB_BIT_SIZE_LOG2) 3099a2dd95SBruce Richardson #define BITMAP_SLAB_BITMASK (BITMAP_SLAB_BIT_SIZE - 1) 3199a2dd95SBruce Richardson 3299a2dd95SBruce Richardson struct rte_trie_tbl { 3399a2dd95SBruce Richardson uint32_t number_tbl8s; /**< Total number of tbl8s */ 3499a2dd95SBruce Richardson uint32_t rsvd_tbl8s; /**< Number of reserved tbl8s */ 3599a2dd95SBruce Richardson uint32_t cur_tbl8s; /**< Current cumber of tbl8s */ 3699a2dd95SBruce Richardson uint64_t def_nh; /**< Default next hop */ 3799a2dd95SBruce Richardson enum rte_fib_trie_nh_sz nh_sz; /**< Size of nexthop entry */ 3899a2dd95SBruce Richardson uint64_t *tbl8; /**< tbl8 table. */ 3999a2dd95SBruce Richardson uint32_t *tbl8_pool; /**< bitmap containing free tbl8 idxes*/ 4099a2dd95SBruce Richardson uint32_t tbl8_pool_pos; 4199a2dd95SBruce Richardson /* tbl24 table. */ 4296f25531STyler Retzlaff alignas(RTE_CACHE_LINE_SIZE) uint64_t tbl24[]; 4399a2dd95SBruce Richardson }; 4499a2dd95SBruce Richardson 4599a2dd95SBruce Richardson static inline uint32_t 46*6cb10a9bSRobin Jarry get_tbl24_idx(const struct rte_ipv6_addr *ip) 4799a2dd95SBruce Richardson { 48*6cb10a9bSRobin Jarry return ip->a[0] << 16|ip->a[1] << 8|ip->a[2]; 4999a2dd95SBruce Richardson } 5099a2dd95SBruce Richardson 5199a2dd95SBruce Richardson static inline void * 52*6cb10a9bSRobin Jarry get_tbl24_p(struct rte_trie_tbl *dp, const struct rte_ipv6_addr *ip, uint8_t nh_sz) 5399a2dd95SBruce Richardson { 5499a2dd95SBruce Richardson uint32_t tbl24_idx; 5599a2dd95SBruce Richardson 5699a2dd95SBruce Richardson tbl24_idx = get_tbl24_idx(ip); 5799a2dd95SBruce Richardson return (void *)&((uint8_t *)dp->tbl24)[tbl24_idx << nh_sz]; 5899a2dd95SBruce Richardson } 5999a2dd95SBruce Richardson 6099a2dd95SBruce Richardson static inline uint8_t 6199a2dd95SBruce Richardson bits_in_nh(uint8_t nh_sz) 6299a2dd95SBruce Richardson { 6399a2dd95SBruce Richardson return 8 * (1 << nh_sz); 6499a2dd95SBruce Richardson } 6599a2dd95SBruce Richardson 6699a2dd95SBruce Richardson static inline uint64_t 6799a2dd95SBruce Richardson get_max_nh(uint8_t nh_sz) 6899a2dd95SBruce Richardson { 6999a2dd95SBruce Richardson return ((1ULL << (bits_in_nh(nh_sz) - 1)) - 1); 7099a2dd95SBruce Richardson } 7199a2dd95SBruce Richardson 7299a2dd95SBruce Richardson static inline uint64_t 7399a2dd95SBruce Richardson lookup_msk(uint8_t nh_sz) 7499a2dd95SBruce Richardson { 7599a2dd95SBruce Richardson return ((1ULL << ((1 << (nh_sz + 3)) - 1)) << 1) - 1; 7699a2dd95SBruce Richardson } 7799a2dd95SBruce Richardson 7899a2dd95SBruce Richardson static inline uint8_t 7999a2dd95SBruce Richardson get_psd_idx(uint32_t val, uint8_t nh_sz) 8099a2dd95SBruce Richardson { 8199a2dd95SBruce Richardson return val & ((1 << (3 - nh_sz)) - 1); 8299a2dd95SBruce Richardson } 8399a2dd95SBruce Richardson 8499a2dd95SBruce Richardson static inline uint32_t 8599a2dd95SBruce Richardson get_tbl_pos(uint32_t val, uint8_t nh_sz) 8699a2dd95SBruce Richardson { 8799a2dd95SBruce Richardson return val >> (3 - nh_sz); 8899a2dd95SBruce Richardson } 8999a2dd95SBruce Richardson 9099a2dd95SBruce Richardson static inline uint64_t 9199a2dd95SBruce Richardson get_tbl_val_by_idx(uint64_t *tbl, uint32_t idx, uint8_t nh_sz) 9299a2dd95SBruce Richardson { 9399a2dd95SBruce Richardson return ((tbl[get_tbl_pos(idx, nh_sz)] >> (get_psd_idx(idx, nh_sz) * 9499a2dd95SBruce Richardson bits_in_nh(nh_sz))) & lookup_msk(nh_sz)); 9599a2dd95SBruce Richardson } 9699a2dd95SBruce Richardson 9799a2dd95SBruce Richardson static inline void * 9899a2dd95SBruce Richardson get_tbl_p_by_idx(uint64_t *tbl, uint64_t idx, uint8_t nh_sz) 9999a2dd95SBruce Richardson { 10099a2dd95SBruce Richardson return (uint8_t *)tbl + (idx << nh_sz); 10199a2dd95SBruce Richardson } 10299a2dd95SBruce Richardson 10399a2dd95SBruce Richardson static inline int 10499a2dd95SBruce Richardson is_entry_extended(uint64_t ent) 10599a2dd95SBruce Richardson { 10699a2dd95SBruce Richardson return (ent & TRIE_EXT_ENT) == TRIE_EXT_ENT; 10799a2dd95SBruce Richardson } 10899a2dd95SBruce Richardson 10999a2dd95SBruce Richardson #define LOOKUP_FUNC(suffix, type, nh_sz) \ 11099a2dd95SBruce Richardson static inline void rte_trie_lookup_bulk_##suffix(void *p, \ 111*6cb10a9bSRobin Jarry const struct rte_ipv6_addr *ips, \ 11299a2dd95SBruce Richardson uint64_t *next_hops, const unsigned int n) \ 11399a2dd95SBruce Richardson { \ 11499a2dd95SBruce Richardson struct rte_trie_tbl *dp = (struct rte_trie_tbl *)p; \ 11599a2dd95SBruce Richardson uint64_t tmp; \ 11699a2dd95SBruce Richardson uint32_t i, j; \ 11799a2dd95SBruce Richardson \ 11899a2dd95SBruce Richardson for (i = 0; i < n; i++) { \ 119*6cb10a9bSRobin Jarry tmp = ((type *)dp->tbl24)[get_tbl24_idx(&ips[i])]; \ 12099a2dd95SBruce Richardson j = 3; \ 12199a2dd95SBruce Richardson while (is_entry_extended(tmp)) { \ 122*6cb10a9bSRobin Jarry tmp = ((type *)dp->tbl8)[ips[i].a[j++] + \ 12399a2dd95SBruce Richardson ((tmp >> 1) * TRIE_TBL8_GRP_NUM_ENT)]; \ 12499a2dd95SBruce Richardson } \ 12599a2dd95SBruce Richardson next_hops[i] = tmp >> 1; \ 12699a2dd95SBruce Richardson } \ 12799a2dd95SBruce Richardson } 12899a2dd95SBruce Richardson LOOKUP_FUNC(2b, uint16_t, 1) 12999a2dd95SBruce Richardson LOOKUP_FUNC(4b, uint32_t, 2) 13099a2dd95SBruce Richardson LOOKUP_FUNC(8b, uint64_t, 3) 13199a2dd95SBruce Richardson 13299a2dd95SBruce Richardson void * 13399a2dd95SBruce Richardson trie_create(const char *name, int socket_id, struct rte_fib6_conf *conf); 13499a2dd95SBruce Richardson 13599a2dd95SBruce Richardson void 13699a2dd95SBruce Richardson trie_free(void *p); 13799a2dd95SBruce Richardson 13899a2dd95SBruce Richardson rte_fib6_lookup_fn_t 13999a2dd95SBruce Richardson trie_get_lookup_fn(void *p, enum rte_fib6_lookup_type type); 14099a2dd95SBruce Richardson 14199a2dd95SBruce Richardson int 142*6cb10a9bSRobin Jarry trie_modify(struct rte_fib6 *fib, const struct rte_ipv6_addr *ip, 14399a2dd95SBruce Richardson uint8_t depth, uint64_t next_hop, int op); 14499a2dd95SBruce Richardson 14599a2dd95SBruce Richardson #endif /* _TRIE_H_ */ 146